diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/AssetManager.cpp | 3 | ||||
-rw-r--r-- | src/AssetManager.hpp | 1 | ||||
-rw-r--r-- | src/Gal.hpp | 58 | ||||
-rw-r--r-- | src/GalOgl.cpp | 339 | ||||
-rw-r--r-- | src/Render.cpp | 188 | ||||
-rw-r--r-- | src/Render.hpp | 15 | ||||
-rw-r--r-- | src/RenderConfigs.cpp | 287 | ||||
-rw-r--r-- | src/RenderConfigs.hpp | 137 | ||||
-rw-r--r-- | src/RendererEntity.cpp | 2 | ||||
-rw-r--r-- | src/RendererSectionData.cpp | 243 | ||||
-rw-r--r-- | src/RendererSectionData.hpp | 63 | ||||
-rw-r--r-- | src/RendererWorld.cpp | 163 | ||||
-rw-r--r-- | src/RendererWorld.hpp | 5 | ||||
-rw-r--r-- | src/Rml.cpp | 13 | ||||
-rw-r--r-- | src/TextureAtlas.cpp | 1 |
15 files changed, 1093 insertions, 425 deletions
diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index 0976e30..3e3f677 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -557,7 +557,7 @@ void ParseBlockModels() { if (face.second.tintIndex) parsedFace.color = glm::vec3(0.486, 0.745, 0.423); else - parsedFace.color = glm::vec3(0, 0, 0); + parsedFace.color = glm::vec3(1.0f); model.parsedFaces.push_back(parsedFace); } @@ -594,6 +594,7 @@ BlockFaces &AssetManager::GetBlockModelByBlockId(BlockId block) { blockFaces.transform = glm::mat4(1.0); blockFaces.faces = assetModel->blockModel.parsedFaces; blockFaces.isBlock = assetModel->blockModel.IsBlock; + blockFaces.ambientOcclusion = assetModel->blockModel.AmbientOcclusion; glm::mat4 transform = glm::mat4(1.0); if (model.y != 0) { diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp index 2bee47c..59fc851 100644 --- a/src/AssetManager.hpp +++ b/src/AssetManager.hpp @@ -48,6 +48,7 @@ struct BlockFaces { glm::mat4 transform; std::vector<ParsedFace> faces; bool isBlock; + bool ambientOcclusion; Vector faceDirectionVector[FaceDirection::none]; }; diff --git a/src/Gal.hpp b/src/Gal.hpp index f448c89..ed0b559 100644 --- a/src/Gal.hpp +++ b/src/Gal.hpp @@ -20,7 +20,7 @@ namespace Gal { struct PipelineInstance; struct FramebufferConfig; struct Framebuffer; - struct ShaderParameters; + struct ShaderParametersBuffer; struct Shader; @@ -61,8 +61,12 @@ namespace Gal { enum class Format { D24S8, + R8, + R8G8, R8G8B8, + R8G8B8SN, R8G8B8A8, + R32G32B32A32F, }; enum class Filtering { @@ -85,6 +89,11 @@ namespace Gal { TriangleFan, }; + enum class Blending { + Opaque, + Additive, + }; + struct VertexAttribute { std::string name; Type type; @@ -106,6 +115,8 @@ namespace Gal { virtual void SetScissor(bool enabled) = 0; + virtual void SetWireframe(bool enabled) = 0; + virtual std::shared_ptr<Buffer> CreateBuffer() = 0; @@ -129,7 +140,7 @@ namespace Gal { virtual std::shared_ptr<Framebuffer> GetDefaultFramebuffer() = 0; - virtual std::shared_ptr<ShaderParameters> GetGlobalShaderParameters() = 0; + virtual std::shared_ptr<ShaderParametersBuffer> GetGlobalShaderParameters() = 0; virtual std::shared_ptr<Shader> LoadVertexShader(std::string_view code) = 0; @@ -156,11 +167,15 @@ namespace Gal { virtual void SetWrapping(Wrapping wrapping) = 0; + virtual void SetLinear(bool isLinear) = 0; + }; struct Texture { virtual ~Texture() = default; + virtual std::tuple<size_t, size_t, size_t> GetSize() = 0; + virtual void SetData(std::vector<std::byte>&& data, size_t mipLevel = 0) = 0; virtual void SetSubData(size_t x, size_t y, size_t z, size_t width, size_t height, size_t depth, std::vector<std::byte> &&data, size_t mipLevel = 0) = 0; @@ -181,6 +196,8 @@ namespace Gal { virtual void SetPrimitive(Primitive primitive) = 0; + virtual void SetBlending(Blending blendingMode) = 0; + virtual std::shared_ptr<BufferBinding> BindVertexBuffer(std::vector<VertexAttribute> &&bufferLayout) = 0; virtual std::shared_ptr<BufferBinding> BindIndexBuffer() = 0; @@ -248,34 +265,23 @@ namespace Gal { virtual void SetTexture(size_t location, std::shared_ptr<Texture> texture) = 0; }; - struct ShaderParameters { - virtual ~ShaderParameters() = default; - - virtual void AddGlobalShaderParameter(std::string_view name, Type type) = 0; - - virtual void SetGlobalShaderParameter(std::string_view name, float value) = 0; - - virtual void SetGlobalShaderParameter(std::string_view name, double value) = 0; - - virtual void SetGlobalShaderParameter(std::string_view name, int8_t value) = 0; - - virtual void SetGlobalShaderParameter(std::string_view name, int16_t value) = 0; - - virtual void SetGlobalShaderParameter(std::string_view name, int32_t value) = 0; - - virtual void SetGlobalShaderParameter(std::string_view name, uint8_t value) = 0; - - virtual void SetGlobalShaderParameter(std::string_view name, uint16_t value) = 0; - - virtual void SetGlobalShaderParameter(std::string_view name, uint32_t value) = 0; + struct ShaderParametersBuffer { + virtual ~ShaderParametersBuffer() = default; - virtual void SetGlobalShaderParameter(std::string_view name, glm::vec2 value) = 0; + template<typename T> + T* Get() { + return reinterpret_cast<T*>(GetDataPtr()); + } - virtual void SetGlobalShaderParameter(std::string_view name, glm::vec3 value) = 0; + template<typename T> + void Resize() { + Resize(sizeof(T)); + *Get<T>() = T{}; + } - virtual void SetGlobalShaderParameter(std::string_view name, glm::vec4 value) = 0; + virtual std::byte* GetDataPtr() = 0; - virtual void SetGlobalShaderParameter(std::string_view name, glm::mat4 value) = 0; + virtual void Resize(size_t newSize) = 0; }; struct Shader { diff --git a/src/GalOgl.cpp b/src/GalOgl.cpp index 052c68a..b046d4b 100644 --- a/src/GalOgl.cpp +++ b/src/GalOgl.cpp @@ -7,76 +7,13 @@ #include "Utility.hpp" -enum class GlResourceType { - Vbo, - Vao, - Texture, - Fbo, - Program, - None, -}; - -class GlResource { - GlResourceType type = GlResourceType::None; - GLuint res = 0; -public: - GlResource() = default; - - GlResource(GLuint resource, GlResourceType resType) noexcept : res(resource), type(resType) {} - - GlResource(const GlResource&) = delete; - - GlResource(GlResource&& rhs) noexcept { - std::swap(this->res, rhs.res); - std::swap(this->type, rhs.type); - } - - GlResource& operator=(const GlResource&) = delete; - - GlResource& operator=(GlResource&& rhs) noexcept { - std::swap(this->res, rhs.res); - std::swap(this->type, rhs.type); - return *this; - } - - ~GlResource() { - switch (type) { - case GlResourceType::Vbo: - glDeleteBuffers(1, &res); - break; - case GlResourceType::Vao: - glDeleteVertexArrays(1, &res); - break; - case GlResourceType::Texture: - glDeleteTextures(1, &res); - break; - case GlResourceType::Fbo: - glDeleteFramebuffers(1, &res); - break; - case GlResourceType::Program: - glDeleteProgram(res); - break; - case GlResourceType::None: - default: - break; - } - } - - operator GLuint() const noexcept { - return res; - } - - GLuint Get() const noexcept { - return res; - } -}; - using namespace Gal; -class ImplOgl; -class ShaderOgl; -class FramebufferOgl; +struct ImplOgl; +struct ShaderOgl; +struct FramebufferOgl; +struct ShaderParametersBufferOgl; class OglState { GLuint activeFbo = 0; @@ -88,6 +25,7 @@ class OglState { GLuint activeTextureUnit = 0; GLint vpX = 0, vpY = 0; GLsizei vpW = 0, vpH = 0; + bool blending = false; public: @@ -137,6 +75,7 @@ public: if (activeTexture[textureUnit] != texture) { SetTextureUnit(textureUnit); glBindTexture(type, texture); + activeTexture[textureUnit] = texture; } glCheckError(); } @@ -160,10 +99,119 @@ public: glCheckError(); } + void EnableBlending(bool enable) { + if (enable != blending) { + blending = enable; + if (blending) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + } + } + + void ReleaseFbo(GLuint vao) { + if (activeVao == vao) + activeVao = 0; + } + + void ReleaseVao(GLuint fbo) { + if (activeFbo == fbo) + activeEbo = 0; + } + + void ReleaseVbo(GLuint vbo) { + if (activeVbo == vbo) + activeVbo = 0; + if (activeEbo == vbo) + activeEbo = 0; + } + + void ReleaseProgram(GLuint program) { + if (activeProgram == program) + activeProgram = 0; + } + + void ReleaseTexture(GLuint texture) { + for (auto& activeTex : activeTexture) { + if (activeTex == texture) + activeTex = 0; + } + } + } oglState; +enum class GlResourceType { + Vbo, + Vao, + Texture, + Fbo, + Program, + None, +}; + +class GlResource { + GlResourceType type = GlResourceType::None; + GLuint res = 0; +public: + GlResource() = default; + + GlResource(GLuint resource, GlResourceType resType) noexcept : res(resource), type(resType) {} + + GlResource(const GlResource&) = delete; + + GlResource(GlResource&& rhs) noexcept { + std::swap(this->res, rhs.res); + std::swap(this->type, rhs.type); + } + + GlResource& operator=(const GlResource&) = delete; + + GlResource& operator=(GlResource&& rhs) noexcept { + std::swap(this->res, rhs.res); + std::swap(this->type, rhs.type); + return *this; + } + + ~GlResource() { + switch (type) { + case GlResourceType::Vbo: + oglState.ReleaseVbo(res); + glDeleteBuffers(1, &res); + break; + case GlResourceType::Vao: + oglState.ReleaseVao(res); + glDeleteVertexArrays(1, &res); + break; + case GlResourceType::Texture: + oglState.ReleaseTexture(res); + glDeleteTextures(1, &res); + break; + case GlResourceType::Fbo: + oglState.ReleaseFbo(res); + glDeleteFramebuffers(1, &res); + break; + case GlResourceType::Program: + oglState.ReleaseProgram(res); + glDeleteProgram(res); + break; + case GlResourceType::None: + default: + break; + } + } + + operator GLuint() const noexcept { + return res; + } + + GLuint Get() const noexcept { + return res; + } +}; + std::unique_ptr<ImplOgl> impl; std::shared_ptr<FramebufferOgl> fbDefault; +std::shared_ptr<ShaderParametersBufferOgl> spbDefault; size_t GalTypeGetComponents(Gal::Type type) { switch (type) { @@ -308,24 +356,64 @@ GLenum GalTypeGetComponentGlType(Gal::Type type) { size_t GalFormatGetSize(Format format) { switch (format) { + case Format::D24S8: + return 4; + case Format::R8: + return 1; + case Format::R8G8: + return 2; case Format::R8G8B8: return 3; + case Format::R8G8B8SN: + return 3; case Format::R8G8B8A8: return 4; + case Format::R32G32B32A32F: + return 16; default: return 0; } return 0; } -GLenum GalFormatGetGlInternalFormat(Format format) { +GLenum GalFormatGetGlLinearInternalFormat(Format format) { switch (format) { case Format::D24S8: return GL_DEPTH24_STENCIL8; + case Format::R8: + return GL_R8; + case Format::R8G8: + return GL_RG8; case Format::R8G8B8: return GL_RGB8; + case Format::R8G8B8SN: + return GL_RGB8_SNORM; case Format::R8G8B8A8: return GL_RGBA8; + case Format::R32G32B32A32F: + return GL_RGBA32F; + default: + return 0; + } + return 0; +} + +GLenum GalFormatGetGlInternalFormat(Format format) { + switch (format) { + case Format::D24S8: + return 0; + case Format::R8: + return 0; + case Format::R8G8: + return 0; + case Format::R8G8B8: + return GL_SRGB; + case Format::R8G8B8SN: + return 0; + case Format::R8G8B8A8: + return GL_SRGB_ALPHA; + case Format::R32G32B32A32F: + return 0; default: return 0; } @@ -336,10 +424,18 @@ GLenum GalFormatGetGlFormat(Format format) { switch (format) { case Format::D24S8: return GL_DEPTH_STENCIL; + case Format::R8: + return GL_RED; + case Format::R8G8: + return GL_RG; case Format::R8G8B8: return GL_RGB; + case Format::R8G8B8SN: + return GL_RGB; case Format::R8G8B8A8: return GL_RGBA; + case Format::R32G32B32A32F: + return GL_RGBA; default: return 0; } @@ -350,10 +446,18 @@ GLenum GalFormatGetGlType(Format format) { switch (format) { case Format::D24S8: return GL_UNSIGNED_INT_24_8; + case Format::R8: + return GL_UNSIGNED_BYTE; + case Format::R8G8: + return GL_UNSIGNED_BYTE; case Format::R8G8B8: return GL_UNSIGNED_BYTE; + case Format::R8G8B8SN: + return GL_BYTE; case Format::R8G8B8A8: return GL_UNSIGNED_BYTE; + case Format::R32G32B32A32F: + return GL_FLOAT; default: return 0; } @@ -577,6 +681,7 @@ struct TextureConfigOgl : public TextureConfig { Format format; size_t width = 1, height = 1, depth = 1; bool interpolateLayers = false; + bool linear = true; GLenum type; Filtering min = Filtering::Nearest, max = Filtering::Nearest; @@ -594,6 +699,10 @@ struct TextureConfigOgl : public TextureConfig { wrap = wrapping; } + virtual void SetLinear(bool isLinear) override { + linear = isLinear; + } + }; struct TextureOgl : public Texture { @@ -602,12 +711,19 @@ struct TextureOgl : public Texture { GlResource texture; Format format; size_t width, height, depth; + bool linear; + + virtual std::tuple<size_t, size_t, size_t> GetSize() override { + return { width, height, depth }; + } virtual void SetData(std::vector<std::byte>&& data, size_t mipLevel = 0) override { size_t expectedSize = width * height * depth * GalFormatGetSize(format); if (data.size() != expectedSize && !data.empty()) throw std::logic_error("Size of data is not valid for this texture"); + GLenum internalFormat = linear ? GalFormatGetGlLinearInternalFormat(format) : GalFormatGetGlInternalFormat(format); + oglState.BindTexture(type, texture); switch (type) { @@ -627,13 +743,13 @@ struct TextureOgl : public Texture { case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: case GL_PROXY_TEXTURE_CUBE_MAP: - glTexImage2D(type, mipLevel, GalFormatGetGlInternalFormat(format), width, height, 0, GalFormatGetGlFormat(format), GalFormatGetGlType(format), data.empty() ? nullptr : data.data()); + glTexImage2D(type, mipLevel, internalFormat, width, height, 0, GalFormatGetGlFormat(format), GalFormatGetGlType(format), data.empty() ? nullptr : data.data()); break; case GL_TEXTURE_3D: case GL_PROXY_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: case GL_PROXY_TEXTURE_2D_ARRAY: - glTexImage3D(type, mipLevel, GalFormatGetGlInternalFormat(format), width, height, depth, 0, GalFormatGetGlFormat(format), GalFormatGetGlType(format), data.empty() ? nullptr : data.data()); + glTexImage3D(type, mipLevel, internalFormat, width, height, depth, 0, GalFormatGetGlFormat(format), GalFormatGetGlType(format), data.empty() ? nullptr : data.data()); break; default: throw std::runtime_error("Unknown texture type"); @@ -690,6 +806,7 @@ struct FramebufferOgl : public Framebuffer { size_t vpX = 0, vpY = 0, vpW = 1, vpH = 1; std::shared_ptr<TextureOgl> depthStencil; std::vector<std::shared_ptr<TextureOgl>> colors; + std::vector<GLenum> attachments; GlResource fbo; @@ -729,6 +846,22 @@ struct FramebufferConfigOgl : public FramebufferConfig { } }; +struct ShaderParametersBufferOgl : public ShaderParametersBuffer { + std::shared_ptr<BufferOgl> buffer; + bool dirty = true; + std::vector<std::byte> data; + + virtual std::byte* GetDataPtr() override { + dirty = true; + return data.data(); + } + + virtual void Resize(size_t newSize) override { + dirty = true; + data.resize(newSize); + } +}; + struct PipelineConfigOgl : public PipelineConfig { std::shared_ptr<ShaderOgl> vertexShader, pixelShader; @@ -737,6 +870,7 @@ struct PipelineConfigOgl : public PipelineConfig { std::shared_ptr<FramebufferOgl> targetFb; std::vector<std::vector<VertexAttribute>> vertexBuffers; Primitive vertexPrimitive = Primitive::Triangle; + Blending blending = Blending::Opaque; virtual void SetVertexShader(std::shared_ptr<Shader> shader) override { vertexShader = std::static_pointer_cast<ShaderOgl,Shader>(shader); @@ -764,6 +898,10 @@ struct PipelineConfigOgl : public PipelineConfig { vertexPrimitive = primitive; } + virtual void SetBlending(Blending blendingMode) override { + blending = blendingMode; + } + virtual std::shared_ptr<BufferBinding> BindVertexBuffer(std::vector<VertexAttribute> &&bufferLayout) override { auto binding = std::make_shared<BufferBindingOgl>(vertexBuffers.size()); vertexBuffers.push_back(bufferLayout); @@ -832,7 +970,7 @@ struct PipelineInstanceOgl : public PipelineInstance { }; struct PipelineOgl : public Pipeline { - + std::vector<std::shared_ptr<ShaderParametersBufferOgl>> spbs; std::map<std::string, size_t> shaderParameters; std::vector<std::shared_ptr<TextureOgl>> staticTextures; GlResource program; @@ -847,16 +985,27 @@ struct PipelineOgl : public Pipeline { }; std::vector<VertexBindingCommand> vertexBindCmds; Primitive primitive; + Blending blending; std::shared_ptr<FramebufferOgl> target; virtual void Activate() override { oglState.UseProgram(program); oglState.BindFbo(target->fbo); oglState.SetViewport(target->vpX, target->vpY, target->vpW, target->vpH); + oglState.EnableBlending(blending == Blending::Additive); + if (target->fbo) + glDrawBuffers(target->attachments.size(), target->attachments.data()); for (size_t i = 0; i < staticTextures.size(); i++) { oglState.BindTexture(staticTextures[i]->type, staticTextures[i]->texture, i); } + + for (auto& spb : spbs) { + if (spb->dirty) { + spb->buffer->SetData(std::vector<std::byte>(spb->data)); + spb->dirty = false; + } + } } virtual void SetDynamicTexture(std::string_view name, std::shared_ptr<Texture> texture) override { @@ -1013,13 +1162,15 @@ struct ImplOgl : public Impl { glCullFace(GL_BACK); glFrontFace(GL_CCW); - glEnable(GL_BLEND); + oglState.EnableBlending(true); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glCheckError(); if (glActiveTexture == nullptr) { throw std::runtime_error("GLEW initialization failed with unknown reason"); } + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GLint flags; glGetIntegerv(GL_CONTEXT_FLAGS, &flags); if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) @@ -1055,6 +1206,10 @@ struct ImplOgl : public Impl { glCheckError(); } + virtual void SetWireframe(bool enabled) override { + glPolygonMode(GL_FRONT_AND_BACK, enabled ? GL_LINE : GL_FILL); + } + virtual std::shared_ptr<Buffer> CreateBuffer() override { auto buff = std::make_shared<BufferOgl>(); @@ -1101,6 +1256,7 @@ struct ImplOgl : public Impl { texture->width = texConfig->width; texture->height = texConfig->height; texture->depth = texConfig->depth; + texture->linear = texConfig->linear; GLuint newTex; glGenTextures(1, &newTex); @@ -1131,6 +1287,7 @@ struct ImplOgl : public Impl { auto config = std::static_pointer_cast<PipelineConfigOgl, PipelineConfig>(pipelineConfig); pipeline->primitive = config->vertexPrimitive; + pipeline->blending = config->blending; pipeline->target = config->targetFb; if (!pipeline->target) @@ -1198,6 +1355,23 @@ struct ImplOgl : public Impl { /* + * Shader parameters buffers + */ + constexpr auto spbGlobalsName = "Globals"; + size_t spbGlobalsBind = 0; + size_t spbIndex = glGetUniformBlockIndex(program, spbGlobalsName); + if (spbIndex != GL_INVALID_VALUE) { + glUniformBlockBinding(program, spbIndex, spbGlobalsBind); + auto spbGlobals = std::static_pointer_cast<ShaderParametersBufferOgl, ShaderParametersBuffer>(GetGlobalShaderParameters()); + glBindBufferBase(GL_UNIFORM_BUFFER, spbGlobalsBind, spbGlobals->buffer->vbo); + pipeline->spbs.emplace_back(spbGlobals); + } + else + LOG(ERROR) << "Cannot bind Globals UBO to shader. Maybe uniform block Globals missing?"; + glCheckError(); + + + /* * Shader parameters */ for (auto&& [name, type] : config->shaderParameters) { @@ -1222,6 +1396,7 @@ struct ImplOgl : public Impl { glUniform1i(location, usedTextureBlocks); pipeline->staticTextures.push_back(texture); + usedTextureBlocks++; } glCheckError(); @@ -1247,6 +1422,11 @@ struct ImplOgl : public Impl { size_t attribSize = GalTypeGetSize(type); for (size_t i = 0; i < count; i++) { + if (location < 0) { + vertexSize += attribSize; + continue; + } + pipeline->vertexBindCmds.push_back({ bufferId, static_cast<size_t>(location + i), @@ -1295,6 +1475,7 @@ struct ImplOgl : public Impl { for (auto&& [location, texture] : conf->colors) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + location, texture->type, texture->texture, 0); fb->colors.emplace_back(std::move(texture)); + fb->attachments.push_back(GL_COLOR_ATTACHMENT0 + location); } if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { @@ -1308,15 +1489,21 @@ struct ImplOgl : public Impl { } virtual std::shared_ptr<Framebuffer> GetDefaultFramebuffer() override { - if (!fbDefault) + if (!fbDefault) { fbDefault = std::make_shared<FramebufferOgl>(); - fbDefault->fbo = GlResource(0, GlResourceType::None); + fbDefault->fbo = GlResource(0, GlResourceType::None); + fbDefault->attachments.push_back(GL_COLOR_ATTACHMENT0); + } return std::static_pointer_cast<Framebuffer, FramebufferOgl>(fbDefault); } - virtual std::shared_ptr<ShaderParameters> GetGlobalShaderParameters() override { - return nullptr; + virtual std::shared_ptr<ShaderParametersBuffer> GetGlobalShaderParameters() override { + if (!spbDefault) { + spbDefault = std::make_shared<ShaderParametersBufferOgl>(); + spbDefault->buffer = std::static_pointer_cast<BufferOgl, Buffer>(GetImplementation()->CreateBuffer()); + } + return spbDefault; } virtual std::shared_ptr<Shader> LoadVertexShader(std::string_view code) override { diff --git a/src/Render.cpp b/src/Render.cpp index 6301ff5..fe9dc04 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -1,5 +1,7 @@ #include "Render.hpp" +#include <random> + #include <easylogging++.h> #include <optick.h> #include <RmlUi/Core.h> @@ -17,6 +19,7 @@ #include "Plugin.hpp" #include "Rml.hpp" #include "Gal.hpp" +#include "RenderConfigs.hpp" const std::map<SDL_Keycode, Rml::Input::KeyIdentifier> keyMapping = { {SDLK_BACKSPACE, Rml::Input::KI_BACK}, @@ -77,9 +80,8 @@ Render::~Render() { rmlRender.reset(); rmlSystem.reset(); - PluginSystem::Init(); + PluginSystem::Init(); - framebuffer.reset(); SDL_GL_DeleteContext(glContext); SDL_DestroyWindow(window); SDL_Quit(); @@ -123,6 +125,7 @@ void Render::InitSdl(unsigned int WinWidth, unsigned int WinHeight, std::string void Render::InitGlew() { auto gal = Gal::GetImplementation(); gal->Init(); + gal->GetGlobalShaderParameters()->Resize<GlobalShaderParameters>(); int width, height; SDL_GL_GetDrawableSize(window, &width, &height); @@ -139,64 +142,79 @@ void Render::PrepareToRendering() { auto gal = Gal::GetImplementation(); gal->GetDefaultFramebuffer()->SetViewport(0, 0, width, height); + gal->GetGlobalShaderParameters()->Get<GlobalShaderParameters>()->gamma = Settings::ReadDouble("gamma", 2.2); + + gbuffer.reset(); + resizeTextureCopy.reset(); + fbTextureCopy.reset(); + fbTextureColor.reset(); + fbTextureDepthStencil.reset(); + fbTarget.reset(); + + bool useDeffered = Settings::ReadBool("deffered", false); + bool useResize = scaledW != width; + + if (useDeffered) { + std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count()); + std::uniform_real_distribution<float> dis(-1.0f, 1.0f); + auto& ssaoKernels = gal->GetGlobalShaderParameters()->Get<GlobalShaderParameters>()->ssaoKernels; + for (auto& vec : ssaoKernels) { + vec.x = dis(rng); + vec.y = dis(rng); + vec.z = (dis(rng) + 1.0f) / 2.0f; + vec.w = 0.0f; + vec = glm::normalize(vec); + } + for (size_t i = 0; i < sizeof(ssaoKernels) / sizeof(*ssaoKernels); i++) { + float scale = i / 64.0f; + scale = glm::mix(0.1f, 1.0f, scale * scale); + ssaoKernels[i] *= scale; + } - - auto dsTexConf = gal->CreateTexture2DConfig(scaledW, scaledH, Gal::Format::D24S8); - dsTexConf->SetMinFilter(Gal::Filtering::Nearest); - dsTexConf->SetMaxFilter(Gal::Filtering::Nearest); - fbDepthStencil = gal->BuildTexture(dsTexConf); - - auto texConf = gal->CreateTexture2DConfig(scaledW, scaledH, Gal::Format::R8G8B8A8); - texConf->SetMinFilter(Gal::Filtering::Nearest); - texConf->SetMaxFilter(Gal::Filtering::Nearest); - fbColor = gal->BuildTexture(texConf); - - auto fbConf = gal->CreateFramebufferConfig(); - fbConf->SetTexture(0, fbColor); - fbConf->SetDepthStencil(fbDepthStencil); - - framebuffer = gal->BuildFramebuffer(fbConf); - framebuffer->SetViewport(0, 0, scaledW, scaledH); - framebuffer->Clear(); - - std::string vertexSource, pixelSource; - { - auto vertAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/vert/fbo"); - vertexSource = std::string((char*)vertAsset->data.data(), (char*)vertAsset->data.data() + vertAsset->data.size()); - - auto pixelAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/fbo"); - pixelSource = std::string((char*)pixelAsset->data.data(), (char*)pixelAsset->data.data() + pixelAsset->data.size()); + int ssaoSamples = Settings::ReadDouble("ssaoSamples", 0); + float ssaoScale = Settings::ReadDouble("ssaoScale", 0.5f); + size_t ssaoW = scaledW * ssaoScale, ssaoH = scaledH * ssaoScale; + + gbuffer = std::make_unique<Gbuffer>(scaledW, scaledH, scaledW, scaledH, ssaoSamples, ssaoW, ssaoH); + gbuffer->SetRenderBuff(renderBuff); + fbTarget = gbuffer->GetGeometryTarget(); + if (useResize) { + auto fbTextureColorConf = gal->CreateTexture2DConfig(scaledW, scaledH, Gal::Format::R8G8B8); + fbTextureColorConf->SetMinFilter(Gal::Filtering::Bilinear); + fbTextureColorConf->SetMaxFilter(Gal::Filtering::Bilinear); + fbTextureColor = gal->BuildTexture(fbTextureColorConf); + + resizeTextureCopy = std::make_unique<TextureFbCopy>(gbuffer->GetFinalTexture(), fbTextureColor); + fbTextureCopy = std::make_unique<TextureFbCopy>(fbTextureColor, gal->GetDefaultFramebuffer()); + } else { + fbTextureCopy = std::make_unique<TextureFbCopy>(gbuffer->GetFinalTexture(), gal->GetDefaultFramebuffer()); + } + } else { + if (useResize) { + auto fbTextureColorConf = gal->CreateTexture2DConfig(scaledW, scaledH, Gal::Format::R8G8B8); + fbTextureColorConf->SetMinFilter(Gal::Filtering::Bilinear); + fbTextureColorConf->SetMaxFilter(Gal::Filtering::Bilinear); + fbTextureColor = gal->BuildTexture(fbTextureColorConf); + + auto fbTextureDepthStencilConf = gal->CreateTexture2DConfig(scaledW, scaledH, Gal::Format::D24S8); + fbTextureDepthStencilConf->SetMinFilter(Gal::Filtering::Bilinear); + fbTextureDepthStencilConf->SetMaxFilter(Gal::Filtering::Bilinear); + fbTextureDepthStencil = gal->BuildTexture(fbTextureDepthStencilConf); + + auto fbTargetConf = gal->CreateFramebufferConfig(); + fbTargetConf->SetTexture(0, fbTextureColor); + fbTargetConf->SetDepthStencil(fbTextureDepthStencil); + fbTarget = gal->BuildFramebuffer(fbTargetConf); + fbTarget->SetViewport(0, 0, scaledW, scaledH); + + fbTextureCopy = std::make_unique<TextureFbCopy>(fbTextureColor, gal->GetDefaultFramebuffer()); + } else { + fbTarget = gal->GetDefaultFramebuffer(); + } } - constexpr float quadVertices[] = { - // positions // texCoords - -1.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - - -1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f - }; - fbBuffer = gal->CreateBuffer(); - fbBuffer->SetData({ reinterpret_cast<const std::byte*>(quadVertices), reinterpret_cast<const std::byte*>(quadVertices) + sizeof(quadVertices) }); - auto fbPPC = gal->CreatePipelineConfig(); - fbPPC->SetTarget(gal->GetDefaultFramebuffer()); - fbPPC->SetVertexShader(gal->LoadVertexShader(vertexSource)); - fbPPC->SetPixelShader(gal->LoadPixelShader(pixelSource)); - fbPPC->AddStaticTexture("inputTexture", fbColor); - auto fbColorBB = fbPPC->BindVertexBuffer({ - {"Pos", Gal::Type::Vec2}, - {"TextureCoords", Gal::Type::Vec2} - }); - - fbPipeline = gal->BuildPipeline(fbPPC); - fbPipelineInstance = fbPipeline->CreateInstance({ - {fbColorBB, fbBuffer} - }); - if (world) - world->PrepareRender(framebuffer); + world->PrepareRender(fbTarget, useDeffered); } void Render::UpdateKeyboard() { @@ -221,18 +239,29 @@ void Render::RenderFrame() { OPTICK_EVENT(); Gal::GetImplementation()->GetDefaultFramebuffer()->Clear(); - framebuffer->Clear(); - - //if (isWireframe) - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - if (renderWorld) + if (gbuffer) + gbuffer->Clear(); + if (fbTarget) + fbTarget->Clear(); + if (resizeTextureCopy) + resizeTextureCopy->Clear(); + if (fbTextureCopy) + fbTextureCopy->Clear(); + + if (isWireframe) + Gal::GetImplementation()->SetWireframe(true); + if (renderWorld) { world->Render(static_cast<float>(windowWidth) / static_cast<float>(windowHeight)); - //if (isWireframe) - //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + if (isWireframe) + Gal::GetImplementation()->SetWireframe(false); - fbPipeline->Activate(); - fbPipelineInstance->Activate(); - fbPipelineInstance->Render(0, 6); + if (gbuffer) + gbuffer->Render(); + if (resizeTextureCopy) + resizeTextureCopy->Copy(); + if (fbTextureCopy) + fbTextureCopy->Copy(); RenderGui(); @@ -266,6 +295,7 @@ void Render::HandleEvents() { windowHeight = height; rmlRender->Update(width, height); rmlContext->SetDimensions(Rml::Vector2i(width, height)); + Gal::GetImplementation()->GetGlobalShaderParameters()->Get<GlobalShaderParameters>()->viewportSize = glm::uvec2(width, height); PrepareToRendering(); break; } @@ -347,6 +377,23 @@ void Render::HandleEvents() { break; } + case SDL_SCANCODE_F9: { + if (sdlKeyMods & KMOD_CTRL) { + renderBuff = 0; + } else if (sdlKeyMods & KMOD_SHIFT) { + renderBuff--; + if (renderBuff < 0) + renderBuff = 0; + } else { + renderBuff++; + if (renderBuff > gbuffer->GetMaxRenderBuffers()) + renderBuff = 0; + } + if (gbuffer) + gbuffer->SetRenderBuff(renderBuff); + break; + } + default: break; } @@ -487,7 +534,7 @@ void Render::InitEvents() { listener.RegisterHandler("PlayerConnected", [this](const Event&) { stateString = "Loading terrain..."; - world = std::make_unique<RendererWorld>(framebuffer); + world = std::make_unique<RendererWorld>(fbTarget, Settings::ReadBool("deffered", false), Settings::ReadBool("smoothlight", false)); world->MaxRenderingDistance = Settings::ReadDouble("renderDistance", 2.0f); PUSH_EVENT("UpdateSectionsRender", 0); }); @@ -497,7 +544,6 @@ void Render::InitEvents() { renderWorld = true; SetState(State::Playing); GetGameState()->GetPlayer()->isFlying = Settings::ReadBool("flight", false); - PUSH_EVENT("SetMinLightLevel", (float)Settings::ReadDouble("brightness", 0.2f)); }); listener.RegisterHandler("ConnectionFailed", [this](const Event& eventData) { @@ -560,6 +606,7 @@ void Render::InitEvents() { listener.RegisterHandler("SettingsUpdate", [this](const Event& eventData) { if (world) { + world->smoothLighting = Settings::ReadBool("smoothlight", false); float renderDistance = Settings::ReadDouble("renderDistance", 2.0f); if (renderDistance != world->MaxRenderingDistance) { world->MaxRenderingDistance = renderDistance; @@ -591,8 +638,8 @@ void Render::InitEvents() { else SDL_GL_SetSwapInterval(0); - float brightness = Settings::ReadDouble("brightness", 0.2f); - PUSH_EVENT("SetMinLightLevel", brightness); + + Gal::GetImplementation()->GetGlobalShaderParameters()->Get<GlobalShaderParameters>()->gamma = Settings::ReadDouble("gamma", 2.2); PrepareToRendering(); }); @@ -607,6 +654,7 @@ void Render::InitRml() { rmlRender = std::make_unique<RmlRenderInterface>(); Rml::SetRenderInterface(rmlRender.get()); rmlRender->Update(windowWidth, windowHeight); + Gal::GetImplementation()->GetGlobalShaderParameters()->Get<GlobalShaderParameters>()->viewportSize = glm::uvec2(windowWidth, windowHeight); rmlFile = std::make_unique<RmlFileInterface>(); Rml::SetFileInterface(rmlFile.get()); diff --git a/src/Render.hpp b/src/Render.hpp index 87494fa..3ac76e3 100644 --- a/src/Render.hpp +++ b/src/Render.hpp @@ -11,6 +11,8 @@ #include "Event.hpp" #include "Gal.hpp" +class Gbuffer; +class TextureFbCopy; class RendererWorld; class RmlRenderInterface; class RmlSystemInterface; @@ -35,12 +37,12 @@ class Render { bool HasFocus=true; float sensetivity = 0.1f; bool isWireframe = false; - std::shared_ptr<Gal::Framebuffer> framebuffer; - std::shared_ptr<Gal::Texture> fbDepthStencil; - std::shared_ptr<Gal::Texture> fbColor; - std::shared_ptr<Gal::Pipeline> fbPipeline; - std::shared_ptr<Gal::PipelineInstance> fbPipelineInstance; - std::shared_ptr<Gal::Buffer> fbBuffer; + std::unique_ptr<TextureFbCopy> resizeTextureCopy; + std::unique_ptr<TextureFbCopy> fbTextureCopy; + std::shared_ptr<Gal::Texture> fbTextureColor; + std::shared_ptr<Gal::Texture> fbTextureDepthStencil; + std::shared_ptr<Gal::Framebuffer> fbTarget; + std::unique_ptr<Gbuffer> gbuffer; EventListener listener; std::string stateString; std::unique_ptr<RmlRenderInterface> rmlRender; @@ -49,6 +51,7 @@ class Render { Rml::Context* rmlContext; unsigned short sdlKeyMods = 0; bool hideRml = false; + size_t renderBuff = 0; void SetMouseCapture(bool IsCaptured); diff --git a/src/RenderConfigs.cpp b/src/RenderConfigs.cpp new file mode 100644 index 0000000..78b442d --- /dev/null +++ b/src/RenderConfigs.cpp @@ -0,0 +1,287 @@ +#include "RenderConfigs.hpp" + +#include <chrono> +#include <random> + +#include "AssetManager.hpp" + +std::string LoadShaderCode(std::string_view assetPath) { + auto gal = Gal::GetImplementation(); + auto codeAsset = AssetManager::GetAssetByAssetName(std::string(assetPath)); + auto codePtr = reinterpret_cast<const char*>(codeAsset->data.data()); + return std::string(codePtr, codePtr + codeAsset->data.size()); +} + +std::shared_ptr<Gal::Shader> LoadVertexShader(std::string_view assetPath) { + auto gal = Gal::GetImplementation(); + return gal->LoadVertexShader(LoadShaderCode(assetPath)); +} + +std::shared_ptr<Gal::Shader> LoadPixelShader(std::string_view assetPath) { + auto gal = Gal::GetImplementation(); + return gal->LoadPixelShader(LoadShaderCode(assetPath)); +} + +TextureFbCopy::TextureFbCopy( + std::shared_ptr<Gal::Texture> inputTexture, + std::shared_ptr<Gal::Texture> outputTexture, + std::shared_ptr<Gal::Shader> copyShader) { + + auto gal = Gal::GetImplementation(); + + auto fbConf = gal->CreateFramebufferConfig(); + fbConf->SetTexture(0, outputTexture); + + auto [outputW, outputH, outputD] = outputTexture->GetSize(); + + framebuffer = gal->BuildFramebuffer(fbConf); + framebuffer->SetViewport(0, 0, outputW, outputH); + + auto fbPPC = gal->CreatePipelineConfig(); + fbPPC->SetTarget(framebuffer); + + fbPPC->AddStaticTexture("inputTexture", inputTexture); + + fbPPC->SetVertexShader(LoadVertexShader("/altcraft/shaders/vert/quad")); + fbPPC->SetPixelShader(copyShader ? copyShader : LoadPixelShader("/altcraft/shaders/frag/copy")); + auto fbBufferBB = fbPPC->BindVertexBuffer({ + {"pos", Gal::Type::Vec2}, + {"uvPos", Gal::Type::Vec2} + }); + + pipeline = gal->BuildPipeline(fbPPC); + + fbBuffer = gal->CreateBuffer(); + constexpr float quadVertices[] = { + // pos // uv + -1.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f + }; + auto quadPtr = reinterpret_cast<const std::byte*>(quadVertices); + fbBuffer->SetData({ quadPtr, quadPtr + sizeof(quadVertices) }); + + pipelineInstance = pipeline->CreateInstance({ + {fbBufferBB, fbBuffer} + }); +} + +TextureFbCopy::TextureFbCopy( + std::shared_ptr<Gal::Texture> inputTexture, + std::shared_ptr<Gal::Framebuffer> outputFb, + std::shared_ptr<Gal::Shader> copyShader) { + + auto gal = Gal::GetImplementation(); + + framebuffer = outputFb; + + auto fbPPC = gal->CreatePipelineConfig(); + fbPPC->SetTarget(framebuffer); + + fbPPC->AddStaticTexture("inputTexture", inputTexture); + + fbPPC->SetVertexShader(LoadVertexShader("/altcraft/shaders/vert/quad")); + fbPPC->SetPixelShader(copyShader ? copyShader : LoadPixelShader("/altcraft/shaders/frag/copy")); + auto fbBufferBB = fbPPC->BindVertexBuffer({ + {"pos", Gal::Type::Vec2}, + {"uvPos", Gal::Type::Vec2} + }); + + pipeline = gal->BuildPipeline(fbPPC); + + fbBuffer = gal->CreateBuffer(); + constexpr float quadVertices[] = { + // pos // uv + -1.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f + }; + auto quadPtr = reinterpret_cast<const std::byte*>(quadVertices); + fbBuffer->SetData({ quadPtr, quadPtr + sizeof(quadVertices) }); + + pipelineInstance = pipeline->CreateInstance({ + {fbBufferBB, fbBuffer} + }); +} + +PostProcess::PostProcess( + std::shared_ptr<Gal::Shader> pixelShader, + std::vector<std::pair<std::string_view, std::shared_ptr<Gal::Texture>>> inputTextures, + std::vector<std::pair<std::string_view, Gal::Type>> inputParameters, + size_t width, + size_t height, + Gal::Format format, + Gal::Filtering filtering) { + auto gal = Gal::GetImplementation(); + + auto texConf = gal->CreateTexture2DConfig(width, height, format); + texConf->SetMinFilter(filtering); + texConf->SetMaxFilter(filtering); + + result = gal->BuildTexture(texConf); + + auto fbConf = gal->CreateFramebufferConfig(); + fbConf->SetTexture(0, result); + + framebuffer = gal->BuildFramebuffer(fbConf); + framebuffer->SetViewport(0, 0, width, height); + + auto fbPPC = gal->CreatePipelineConfig(); + fbPPC->SetTarget(framebuffer); + for (auto&& [name, texture] : inputTextures) { + fbPPC->AddStaticTexture(name, texture); + } + for (auto&& [name, type] : inputParameters) { + fbPPC->AddShaderParameter(name, type); + } + fbPPC->SetVertexShader(LoadVertexShader("/altcraft/shaders/vert/quad")); + fbPPC->SetPixelShader(pixelShader); + auto fbBufferBB = fbPPC->BindVertexBuffer({ + {"pos", Gal::Type::Vec2}, + {"uvPos", Gal::Type::Vec2} + }); + + pipeline = gal->BuildPipeline(fbPPC); + + fbBuffer = gal->CreateBuffer(); + constexpr float quadVertices[] = { + // pos // uv + -1.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f + }; + auto quadPtr = reinterpret_cast<const std::byte*>(quadVertices); + fbBuffer->SetData({ quadPtr, quadPtr + sizeof(quadVertices) }); + + pipelineInstance = pipeline->CreateInstance({ + {fbBufferBB, fbBuffer} + }); +} + +Gbuffer::Gbuffer(size_t geomW, size_t geomH, size_t lightW, size_t lightH, int ssaoSamples, size_t ssaoW, size_t ssaoH) { + auto gal = Gal::GetImplementation(); + + auto colorConf = gal->CreateTexture2DConfig(geomW, geomH, Gal::Format::R8G8B8); + colorConf->SetMinFilter(Gal::Filtering::Bilinear); + colorConf->SetMaxFilter(Gal::Filtering::Bilinear); + color = gal->BuildTexture(colorConf); + + auto normalConf = gal->CreateTexture2DConfig(geomW, geomH, Gal::Format::R8G8B8SN); + normalConf->SetMinFilter(Gal::Filtering::Bilinear); + normalConf->SetMaxFilter(Gal::Filtering::Bilinear); + normal = gal->BuildTexture(normalConf); + + auto lightConf = gal->CreateTexture2DConfig(geomW, geomH, Gal::Format::R8G8B8); + lightConf->SetMinFilter(Gal::Filtering::Bilinear); + lightConf->SetMaxFilter(Gal::Filtering::Bilinear); + light = gal->BuildTexture(lightConf); + + auto dsConf = gal->CreateTexture2DConfig(geomW, geomH, Gal::Format::D24S8); + dsConf->SetMinFilter(Gal::Filtering::Bilinear); + dsConf->SetMaxFilter(Gal::Filtering::Bilinear); + depthStencil = gal->BuildTexture(dsConf); + + auto geomFbConf = gal->CreateFramebufferConfig(); + geomFbConf->SetDepthStencil(depthStencil); + geomFbConf->SetTexture(0, color); + geomFbConf->SetTexture(1, normal); + geomFbConf->SetTexture(2, light); + + geomFramebuffer = gal->BuildFramebuffer(geomFbConf); + geomFramebuffer->SetViewport(0, 0, geomW, geomH); + + if (ssaoSamples > 0) { + auto noiseConf = gal->CreateTexture2DConfig(4, 4, Gal::Format::R8G8B8SN); + noiseConf->SetWrapping(Gal::Wrapping::Repeat); + noiseConf->SetMinFilter(Gal::Filtering::Bilinear); + noiseConf->SetMaxFilter(Gal::Filtering::Bilinear); + ssaoNoise = gal->BuildTexture(noiseConf); + + std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count()); + std::uniform_real_distribution<> dis(-1.0f, 1.0f); + std::vector<glm::i8vec3> noiseTexData(16); + for (auto& vec : noiseTexData) { + vec.x = static_cast<int8_t>(dis(rng) * 128.0f); + vec.y = static_cast<int8_t>(dis(rng) * 128.0f); + vec.z = 0.0f; + } + ssaoNoise->SetData({ reinterpret_cast<std::byte*>(noiseTexData.data()), reinterpret_cast<std::byte*>(noiseTexData.data() + noiseTexData.size()) }); + + std::vector<std::pair<std::string_view, std::shared_ptr<Gal::Texture>>> ssaoTextures = { + {"normal", normal}, + {"light", light}, + {"depthStencil", depthStencil}, + {"ssaoNoise", ssaoNoise}, + }; + + std::vector<std::pair<std::string_view, Gal::Type>> ssaoParameters = { + {"ssaoSamples", Gal::Type::Int32}, + }; + + ssaoPass = std::make_unique<PostProcess>(LoadPixelShader("/altcraft/shaders/frag/ssao"), + ssaoTextures, + ssaoParameters, + ssaoW, + ssaoH, + Gal::Format::R8, + Gal::Filtering::Bilinear); + + ssaoPass->SetShaderParameter("ssaoSamples", ssaoSamples); + + std::vector<std::pair<std::string_view, std::shared_ptr<Gal::Texture>>> ssaoBlurTextures = { + {"blurInput", ssaoPass->GetResultTexture()}, + }; + + std::vector<std::pair<std::string_view, Gal::Type>> ssaoBlurParameters = { + {"blurScale", Gal::Type::Int32}, + }; + + ssaoBlurPass = std::make_unique<PostProcess>(LoadPixelShader("/altcraft/shaders/frag/blur"), + ssaoBlurTextures, + ssaoBlurParameters, + ssaoW, + ssaoH, + Gal::Format::R8, + Gal::Filtering::Bilinear); + + ssaoBlurPass->SetShaderParameter("blurScale", 2); + } + + std::vector<std::pair<std::string_view, Gal::Type>> lightingParameters = { + {"renderBuff", Gal::Type::Int32}, + {"applySsao", Gal::Type::Int32}, + }; + + std::vector<std::pair<std::string_view, std::shared_ptr<Gal::Texture>>> lightingTextures = { + {"depthStencil", depthStencil}, + {"color", color}, + {"normal", normal}, + {"light", light}, + }; + + if (ssaoSamples > 0) + lightingTextures.emplace_back("ssao", ssaoBlurPass->GetResultTexture()); + + lightingPass = std::make_unique<PostProcess>(LoadPixelShader("/altcraft/shaders/frag/light"), + lightingTextures, + lightingParameters, + lightW, + lightH, + Gal::Format::R8G8B8, + Gal::Filtering::Bilinear); + + lightingPass->SetShaderParameter("applySsao", ssaoSamples); +} + diff --git a/src/RenderConfigs.hpp b/src/RenderConfigs.hpp new file mode 100644 index 0000000..9d1ffcd --- /dev/null +++ b/src/RenderConfigs.hpp @@ -0,0 +1,137 @@ +#pragma once + +#include "Gal.hpp" + +struct GlobalShaderParameters { + glm::mat4 projView; + glm::mat4 proj; + glm::mat4 invProj; + glm::mat4 view; + glm::uvec2 viewportSize; + glm::uint32 paddingFA = 0xFAAFFAFA; + glm::uint32 paddingFB = 0xFBFBFBFB; + glm::vec4 ssaoKernels[64]; + glm::float32 globalTime; + glm::float32 dayTime; + glm::float32 gamma; + glm::uint32 paddingF0 = 0xF0F0F0F0; + glm::uint32 paddingF1 = 0xF1F1F1F1; + glm::uint32 paddingF2 = 0xF2F2F2F2; +}; + +std::shared_ptr<Gal::Shader> LoadVertexShader(std::string_view assetPath); + +std::shared_ptr<Gal::Shader> LoadPixelShader(std::string_view assetPath); + +class TextureFbCopy { + std::shared_ptr<Gal::Framebuffer> framebuffer; + std::shared_ptr<Gal::Buffer> fbBuffer; + std::shared_ptr<Gal::Pipeline> pipeline; + std::shared_ptr<Gal::PipelineInstance> pipelineInstance; +public: + + TextureFbCopy( + std::shared_ptr<Gal::Texture> inputTexture, + std::shared_ptr<Gal::Texture> outputTexture, + std::shared_ptr<Gal::Shader> copyShader = nullptr); + + TextureFbCopy( + std::shared_ptr<Gal::Texture> inputTexture, + std::shared_ptr<Gal::Framebuffer> outputFb, + std::shared_ptr<Gal::Shader> copyShader = nullptr); + + void Clear() { + framebuffer->Clear(); + } + + void Copy() { + pipeline->Activate(); + pipelineInstance->Activate(); + pipelineInstance->Render(0, 6); + } +}; + +class PostProcess { + std::shared_ptr<Gal::Framebuffer> framebuffer; + std::shared_ptr<Gal::Buffer> fbBuffer; + std::shared_ptr<Gal::Pipeline> pipeline; + std::shared_ptr<Gal::PipelineInstance> pipelineInstance; + std::shared_ptr<Gal::Texture> result; +public: + + PostProcess( + std::shared_ptr<Gal::Shader> pixelShader, + std::vector<std::pair<std::string_view, std::shared_ptr<Gal::Texture>>> inputTextures, + std::vector<std::pair<std::string_view, Gal::Type>> inputParameters, + size_t width, + size_t height, + Gal::Format format, + Gal::Filtering filtering); + + void Clear() { + framebuffer->Clear(); + } + + void Render() { + pipeline->Activate(); + pipelineInstance->Activate(); + pipelineInstance->Render(0, 6); + } + + template<typename T> + void SetShaderParameter(std::string_view name, T value) { + pipeline->SetShaderParameter(name, value); + } + + std::shared_ptr<Gal::Texture> GetResultTexture() { + return result; + } +}; + +class Gbuffer { + std::shared_ptr<Gal::Texture> ssaoNoise; + std::unique_ptr<PostProcess> ssaoPass; + std::unique_ptr<PostProcess> ssaoBlurPass; + std::unique_ptr<PostProcess> lightingPass; + std::shared_ptr<Gal::Texture> depthStencil; + std::shared_ptr<Gal::Texture> color; //RGB - color + std::shared_ptr<Gal::Texture> normal; //RGB - normal + std::shared_ptr<Gal::Texture> light; //R - faceLight, G - skyLight, B - ssaoDepthMask + std::shared_ptr<Gal::Framebuffer> geomFramebuffer; + +public: + Gbuffer(size_t geomW, size_t geomH, size_t lightW, size_t lightH, int ssaoSamples, size_t ssaoW, size_t ssaoH); + + std::shared_ptr<Gal::Framebuffer> GetGeometryTarget() { + return geomFramebuffer; + } + + std::shared_ptr<Gal::Texture> GetFinalTexture() { + return lightingPass->GetResultTexture(); + } + + void Render() { + if (ssaoPass) { + ssaoPass->Render(); + ssaoBlurPass->Render(); + } + lightingPass->Render(); + } + + void Clear() { + geomFramebuffer->Clear(); + if (ssaoPass) { + ssaoPass->Clear(); + ssaoBlurPass->Clear(); + } + lightingPass->Clear(); + } + + int GetMaxRenderBuffers() { + return 7; + } + + void SetRenderBuff(int renderBuff) { + lightingPass->SetShaderParameter("renderBuff", renderBuff); + } +}; diff --git a/src/RendererEntity.cpp b/src/RendererEntity.cpp index 02a5f54..d014bdb 100644 --- a/src/RendererEntity.cpp +++ b/src/RendererEntity.cpp @@ -18,5 +18,5 @@ void RendererEntity::Render(std::shared_ptr<Gal::Pipeline> pipeline, const World model = glm::scale(model, glm::vec3(entity.width, entity.height, entity.width)); pipeline->SetShaderParameter("model", model); - pipeline->SetShaderParameter("color", entity.renderColor); + pipeline->SetShaderParameter("entityColor", entity.renderColor); } diff --git a/src/RendererSectionData.cpp b/src/RendererSectionData.cpp index 2588fd6..761dd14 100644 --- a/src/RendererSectionData.cpp +++ b/src/RendererSectionData.cpp @@ -3,6 +3,7 @@ #include <array> #include <glm/gtc/matrix_transform.hpp> +#include <glm/gtc/matrix_inverse.hpp> #include <optick.h> #include "World.hpp" @@ -24,12 +25,44 @@ glm::vec2 TransformTextureCoord(glm::vec4 TextureAtlasCoords, glm::vec2 UvCoords return transformed; } -void AddFacesByBlockModel(RendererSectionData &data, const BlockFaces &model, const glm::mat4 &transform, bool visibility[FaceDirection::none], BlockLightness light, BlockLightness skyLight) { - for (const auto &face : model.faces) { - glm::vec2 lightness; - lightness.x = _max(light.face[0], light.face[1], light.face[2], light.face[3], light.face[4], light.face[5]); - lightness.y = _max(skyLight.face[0], skyLight.face[1], skyLight.face[2], skyLight.face[3], skyLight.face[4], skyLight.face[5]); - if (face.visibility != FaceDirection::none) { +//Maps [0.0, 0.5] range to [0.0, 1.0] +float MapNeg(float x) { + float y = x * 2.0f; + return glm::clamp(y, 0.0f, 1.0f); +} + +//Maps [0.5, 1.0] range to [0.0, 1.0] +float MapPos(float x) { + float y = (x * 2.0f) - 1.0f; + return glm::clamp(y, 0.0f, 1.0f); +} + +float InterpolateBlockLightness(const BlockLightness& light, const glm::vec3 &point) { + float xNeg = MapNeg(point.x); + float xPos = MapPos(point.x); + float xNegLight = glm::mix(light.face[FaceDirection::east], light.self, xNeg); + float xPosLight = glm::mix(light.self, light.face[FaceDirection::west], xPos); + float xLight = (glm::max)(xNegLight, xPosLight); + + float yNeg = MapNeg(point.y); + float yPos = MapPos(point.y); + float yNegLight = glm::mix(light.face[FaceDirection::down], light.self, yNeg); + float yPosLight = glm::mix(light.self, light.face[FaceDirection::up], yPos); + float yLight = (glm::max)(yNegLight, yPosLight); + + float zNeg = MapNeg(point.z); + float zPos = MapPos(point.z); + float zNegLight = glm::mix(light.face[FaceDirection::south], light.self, zNeg); + float zPosLight = glm::mix(light.self, light.face[FaceDirection::north], zPos); + float zLight = (glm::max)(zNegLight, zPosLight); + + return (glm::max)(xLight, (glm::max)(yLight, zLight)); +} + +void AddFacesByBlockModel(RendererSectionData& data, const BlockFaces& model, const glm::mat4& transform, bool visibility[FaceDirection::none], const Vector &pos, const SectionsData §ions, bool smoothLighting) { + glm::vec3 absPos = (sections.data[1][1][1].GetPosition() * 16).glm(); + for (const auto& face : model.faces) { + if (face.visibility != FaceDirection::none) { FaceDirection direction = face.visibility; Vector directionVec = model.faceDirectionVector[direction]; FaceDirection faceDirection = FaceDirection::none; @@ -44,7 +77,6 @@ void AddFacesByBlockModel(RendererSectionData &data, const BlockFaces &model, co if (visibility[faceDirection]) continue; - lightness = glm::vec2(light.face[faceDirection], skyLight.face[faceDirection]); } data.vertices.emplace_back(); @@ -56,16 +88,47 @@ void AddFacesByBlockModel(RendererSectionData &data, const BlockFaces &model, co vertexData.positions[2] = transformed * glm::vec4(1, 0, 1, 1); vertexData.positions[3] = transformed * glm::vec4(1, 0, 0, 1); + glm::vec3 normal = glm::cross(vertexData.positions[1] - vertexData.positions[0], vertexData.positions[3] - vertexData.positions[0]); + vertexData.normal = glm::normalize(normal); + vertexData.uvs[0] = TransformTextureCoord(face.texture, glm::vec2(0, 0), face.frames); vertexData.uvs[1] = TransformTextureCoord(face.texture, glm::vec2(1, 0), face.frames); vertexData.uvs[2] = TransformTextureCoord(face.texture, glm::vec2(1, 1), face.frames); vertexData.uvs[3] = TransformTextureCoord(face.texture, glm::vec2(0, 1), face.frames); - vertexData.uvLayers = face.layer; - vertexData.animations = face.frames; + vertexData.layerAnimationAo.r = face.layer; + vertexData.layerAnimationAo.g = face.frames; vertexData.colors = face.color; - vertexData.lights = lightness; - } + + if (smoothLighting) { + for (size_t i = 0; i < 4; i++) { + glm::vec3 baseLightPos = vertexData.positions[i] - absPos; + glm::vec3 lightPos = baseLightPos + normal * 0.5f; + glm::ivec3 basePos = glm::trunc(lightPos); + BlockLightness light = sections.GetLight(Vector(basePos.x, basePos.y, basePos.z)); + BlockLightness skyLight = sections.GetSkyLight(Vector(basePos.x, basePos.y, basePos.z)); + vertexData.lights[i].x = InterpolateBlockLightness(light, lightPos - glm::vec3(basePos)); + vertexData.lights[i].y = InterpolateBlockLightness(skyLight, lightPos - glm::vec3(basePos)); + } + } else { + BlockLightness light = sections.GetLight(pos); + BlockLightness skyLight = sections.GetSkyLight(pos); + glm::vec2 lightness; + + lightness.x = face.visibility != FaceDirection::none ? light.face[face.visibility] : light.self; + lightness.x = (glm::max)(lightness.x, static_cast<float>(light.self)); + + lightness.y = face.visibility != FaceDirection::none ? skyLight.face[face.visibility] : skyLight.self; + lightness.y = (glm::max)(lightness.y, static_cast<float>(skyLight.self)); + + vertexData.lights[0] = lightness; + vertexData.lights[1] = lightness; + vertexData.lights[2] = lightness; + vertexData.lights[3] = lightness; + } + + vertexData.layerAnimationAo.b = model.ambientOcclusion ? 1.0f : 0.0f; + } } BlockFaces *GetInternalBlockModel(const BlockId& id, std::vector<std::pair<BlockId, BlockFaces*>> &idModels) { @@ -117,14 +180,14 @@ std::array<BlockId, 4096> SetBlockIdData(const SectionsData §ions) { for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { - blockIdData[y * 256 + z * 16 + x] = sections.section.GetBlockId(Vector(x, y, z)); + blockIdData[y * 256 + z * 16 + x] = sections.data[1][1][1].GetBlockId(Vector(x, y, z)); } } } return blockIdData; } -RendererSectionData ParseSection(const SectionsData §ions) { +RendererSectionData ParseSection(const SectionsData §ions, bool smoothLighting) { OPTICK_EVENT(); RendererSectionData data; @@ -133,10 +196,10 @@ RendererSectionData ParseSection(const SectionsData §ions) { std::array<bool[FaceDirection::none], 4096> blockVisibility = GetBlockVisibilityData(sections, blockIdData, idModels); std::string textureName; - data.hash = sections.section.GetHash(); - data.sectionPos = sections.section.GetPosition(); + data.hash = sections.data[1][1][1].GetHash(); + data.sectionPos = sections.data[1][1][1].GetPosition(); - glm::mat4 baseOffset = glm::translate(glm::mat4(1.0), (sections.section.GetPosition() * 16).glm()), transform; + glm::mat4 baseOffset = glm::translate(glm::mat4(1.0), (sections.data[1][1][1].GetPosition() * 16).glm()), transform; for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { @@ -149,11 +212,8 @@ RendererSectionData ParseSection(const SectionsData §ions) { transform = glm::translate(baseOffset, vec.glm()); - BlockLightness light = sections.GetLight(vec); - BlockLightness skyLight = sections.GetSkyLight(vec); - BlockFaces *model = GetInternalBlockModel(block, idModels); - AddFacesByBlockModel(data, *model, transform, blockVisibility[y * 256 + z * 16 + x], light, skyLight); + AddFacesByBlockModel(data, *model, transform, blockVisibility[y * 256 + z * 16 + x], vec, sections, smoothLighting); } } } @@ -163,127 +223,34 @@ RendererSectionData ParseSection(const SectionsData §ions) { } BlockId SectionsData::GetBlockId(const Vector &pos) const { - if (pos.x < 0) - return east.GetBlockId(Vector(15, pos.y, pos.z)); - - if (pos.x > 15) - return west.GetBlockId(Vector(0, pos.y, pos.z)); - - if (pos.y < 0) - return bottom.GetBlockId(Vector(pos.x, 15, pos.z)); - - if (pos.y > 15) - return top.GetBlockId(Vector(pos.x, 0, pos.z)); - - if (pos.z < 0) - return south.GetBlockId(Vector(pos.x, pos.y, 15)); - - if (pos.z > 15) - return north.GetBlockId(Vector(pos.x, pos.y, 0)); - - return section.GetBlockId(pos); + Vector sectionPos = pos; + return GetSection(sectionPos).GetBlockId(sectionPos); } -BlockLightness SectionsData::GetLight(const Vector &pos) const { - BlockLightness lightness; - static const Vector directions[] = { - Vector(1,0,0), - Vector(-1,0,0), - Vector(0,1,0), - Vector(0,-1,0), - Vector(0,0,1), - Vector(0,0,-1), - }; - - unsigned char self = section.GetBlockLight(pos); - - for (const Vector &dir : directions) { - Vector vec = pos + dir; - unsigned char dirValue = 0; - - if (vec.x < 0 || vec.x > 15 || vec.y < 0 || vec.y > 15 || vec.z < 0 || vec.z > 15) { - if (vec.x < 0) - dirValue = east.GetBlockLight(Vector(15, vec.y, vec.z)); - if (vec.x > 15) - dirValue = west.GetBlockLight(Vector(0, vec.y, vec.z)); - if (vec.y < 0) - dirValue = bottom.GetBlockLight(Vector(vec.x, 15, vec.z)); - if (vec.y > 15) - dirValue = top.GetBlockLight(Vector(vec.x, 0, vec.z)); - if (vec.z < 0) - dirValue = south.GetBlockLight(Vector(vec.x, vec.y, 15)); - if (vec.z > 15) - dirValue = north.GetBlockLight(Vector(vec.x, vec.y, 0)); - } - else - dirValue = section.GetBlockLight(vec); - - dirValue = _max(self, dirValue); - - if (dir == directions[0]) - lightness.face[FaceDirection::east] = dirValue; - if (dir == directions[1]) - lightness.face[FaceDirection::west] = dirValue; - if (dir == directions[2]) - lightness.face[FaceDirection::up] = dirValue; - if (dir == directions[3]) - lightness.face[FaceDirection::down] = dirValue; - if (dir == directions[4]) - lightness.face[FaceDirection::south] = dirValue; - if (dir == directions[5]) - lightness.face[FaceDirection::north] = dirValue; - } - return lightness; +BlockLightness SectionsData::GetLight(const Vector& pos) const { + BlockLightness lightness; + for (size_t i = 0; i <= FaceDirection::none; i++) { + Vector vec = pos + FaceDirectionVector[i]; + uint8_t dirValue = GetSection(vec).GetBlockLight(vec); + + if (i == FaceDirection::none) + lightness.self = dirValue; + else + lightness.face[i] = dirValue; + } + return lightness; } BlockLightness SectionsData::GetSkyLight(const Vector &pos) const { - BlockLightness lightness; - static const Vector directions[] = { - Vector(1,0,0), - Vector(-1,0,0), - Vector(0,1,0), - Vector(0,-1,0), - Vector(0,0,1), - Vector(0,0,-1), - }; - - unsigned char self = section.GetBlockSkyLight(pos); - - for (const Vector &dir : directions) { - Vector vec = pos + dir; - unsigned char dirValue = 0; - - if (vec.x < 0 || vec.x > 15 || vec.y < 0 || vec.y > 15 || vec.z < 0 || vec.z > 15) { - if (vec.x < 0) - dirValue = east.GetBlockSkyLight(Vector(15, vec.y, vec.z)); - if (vec.x > 15) - dirValue = west.GetBlockSkyLight(Vector(0, vec.y, vec.z)); - if (vec.y < 0) - dirValue = bottom.GetBlockSkyLight(Vector(vec.x, 15, vec.z)); - if (vec.y > 15) - dirValue = top.GetBlockSkyLight(Vector(vec.x, 0, vec.z)); - if (vec.z < 0) - dirValue = south.GetBlockSkyLight(Vector(vec.x, vec.y, 15)); - if (vec.z > 15) - dirValue = north.GetBlockSkyLight(Vector(vec.x, vec.y, 0)); - } - else - dirValue = section.GetBlockSkyLight(vec); - - dirValue = _max(self, dirValue); - - if (dir == directions[0]) - lightness.face[FaceDirection::east] = dirValue; - if (dir == directions[1]) - lightness.face[FaceDirection::west] = dirValue; - if (dir == directions[2]) - lightness.face[FaceDirection::up] = dirValue; - if (dir == directions[3]) - lightness.face[FaceDirection::down] = dirValue; - if (dir == directions[4]) - lightness.face[FaceDirection::south] = dirValue; - if (dir == directions[5]) - lightness.face[FaceDirection::north] = dirValue; - } - return lightness; + BlockLightness lightness; + for (size_t i = 0; i <= FaceDirection::none; i++) { + Vector vec = pos + FaceDirectionVector[i]; + uint8_t dirValue = GetSection(vec).GetBlockSkyLight(vec); + + if (i == FaceDirection::none) + lightness.self = dirValue; + else + lightness.face[i] = dirValue; + } + return lightness; } diff --git a/src/RendererSectionData.hpp b/src/RendererSectionData.hpp index edd2992..0f9ade6 100644 --- a/src/RendererSectionData.hpp +++ b/src/RendererSectionData.hpp @@ -11,17 +11,45 @@ class World; struct BlockLightness { - unsigned char face[FaceDirection::none] = { 0,0,0,0,0,0 }; + uint8_t face[FaceDirection::none + 1] = { 0,0,0,0,0,0 }; + uint8_t self = 0; }; struct SectionsData { - Section section; - Section west; - Section east; - Section top; - Section bottom; - Section north; - Section south; + Section data[3][3][3]; + + const Section& GetSection(Vector& pos) const { + size_t x = 1, y = 1, z = 1; + while (true) { + if (pos.x < 0) { + x--; + pos.x += 16; + } + else if (pos.x > 15) { + x++; + pos.x -= 16; + } + else if (pos.y < 0) { + y--; + pos.y += 16; + } + else if (pos.y > 15) { + y++; + pos.y -= 16; + } + else if (pos.z < 0) { + z--; + pos.z += 16; + } + else if (pos.z > 15) { + z++; + pos.z -= 16; + } + else + break; + } + return data[x][y][z]; + } BlockId GetBlockId(const Vector &pos) const; @@ -31,20 +59,19 @@ struct SectionsData { }; struct VertexData { - glm::vec3 positions[4]; - glm::vec2 uvs[4]; - float uvLayers; - float animations; - glm::vec3 colors; - glm::vec2 lights; - uint8_t padding[20]; + glm::vec3 positions[4]; + glm::vec2 uvs[4]; + glm::vec2 lights[4]; + glm::vec3 normal; + glm::vec3 colors; + glm::vec3 layerAnimationAo; //R - uvLayer, G - animation, B - ambientOcclusion }; struct RendererSectionData { - std::vector<VertexData> vertices; + std::vector<VertexData> vertices; size_t hash = 0; Vector sectionPos; - bool forced = false; + bool forced = false; }; -RendererSectionData ParseSection(const SectionsData §ions);
\ No newline at end of file +RendererSectionData ParseSection(const SectionsData §ions, bool smoothLighting); diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index cb4551f..af177d7 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -2,6 +2,7 @@ #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> +#include <glm/gtx/norm.hpp> #include <optick.h> #include "DebugInfo.hpp" @@ -12,6 +13,7 @@ #include "Section.hpp" #include "RendererSectionData.hpp" #include "Game.hpp" +#include "RenderConfigs.hpp" void RendererWorld::WorkerFunction(size_t workerId) { OPTICK_THREAD("Worker"); @@ -24,7 +26,7 @@ void RendererWorld::WorkerFunction(size_t workerId) { return; size_t id = std::get<1>(data); bool forced = std::get<2>(data); - parsing[id].renderer = ParseSection(parsing[id].data); + parsing[id].renderer = ParseSection(parsing[id].data, smoothLighting); parsing[id].renderer.forced = forced; PUSH_EVENT("SectionParsed", id); }); @@ -55,13 +57,13 @@ void RendererWorld::ParseQueueUpdate() { vec.y -= 4500; } - parsing[id].data.section = GetGameState()->GetWorld().GetSection(vec); - parsing[id].data.north = GetGameState()->GetWorld().GetSection(vec + Vector(0, 0, 1)); - parsing[id].data.south = GetGameState()->GetWorld().GetSection(vec + Vector(0, 0, -1)); - parsing[id].data.west = GetGameState()->GetWorld().GetSection(vec + Vector(1, 0, 0)); - parsing[id].data.east = GetGameState()->GetWorld().GetSection(vec + Vector(-1, 0, 0)); - parsing[id].data.bottom = GetGameState()->GetWorld().GetSection(vec + Vector(0, -1, 0)); - parsing[id].data.top = GetGameState()->GetWorld().GetSection(vec + Vector(0, 1, 0)); + for (int x = -1; x < 2; x++) { + for (int y = -1; y < 2; y++) { + for (int z = -1; z < 2; z++) { + parsing[id].data.data[x + 1][y + 1][z + 1] = GetGameState()->GetWorld().GetSection(vec + Vector(x, y, z)); + } + } + } parsing[id].parsing = true; @@ -95,7 +97,7 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() { bool skip = false; for (int i = 0; i < RendererWorld::parsingBufferSize; i++) { - if (parsing[i].data.section.GetHash() == section.GetHash()) { + if (parsing[i].data.data[1][1][1].GetHash() == section.GetHash()) { skip = true; break; } @@ -151,8 +153,9 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) { } } -RendererWorld::RendererWorld(std::shared_ptr<Gal::Framebuffer> target) { - OPTICK_EVENT(); +RendererWorld::RendererWorld(std::shared_ptr<Gal::Framebuffer> target, bool defferedShading, bool smoothLighting) { + OPTICK_EVENT(); + this->smoothLighting = smoothLighting; MaxRenderingDistance = 2; numOfWorkers = _max(1, (signed int) std::thread::hardware_concurrency() - 2); @@ -160,7 +163,7 @@ RendererWorld::RendererWorld(std::shared_ptr<Gal::Framebuffer> target) { globalTimeStart = std::chrono::high_resolution_clock::now(); - PrepareRender(target); + PrepareRender(target, defferedShading); listener->RegisterHandler("DeleteSectionRender", [this](const Event& eventData) { OPTICK_EVENT("EV_DeleteSectionRender"); @@ -255,11 +258,6 @@ RendererWorld::RendererWorld(std::shared_ptr<Gal::Framebuffer> target) { sections.erase(it); }); - listener->RegisterHandler("SetMinLightLevel", [this](const Event& eventData) { - auto value = eventData.get<float>(); - sectionsPipeline->SetShaderParameter("MinLightLevel", value); - }); - for (int i = 0; i < numOfWorkers; i++) workers.push_back(std::thread(&RendererWorld::WorkerFunction, this, i)); @@ -282,18 +280,26 @@ RendererWorld::~RendererWorld() { void RendererWorld::Render(float screenRatio) { OPTICK_EVENT(); //Common - glm::mat4 projection = glm::perspective( + + auto globalSpb = Gal::GetImplementation()->GetGlobalShaderParameters(); + + auto& projection = globalSpb->Get<GlobalShaderParameters>()->proj; + projection = glm::perspective( glm::radians(70.0f), screenRatio, 0.1f, 10000000.0f ); - glm::mat4 view = GetGameState()->GetViewMatrix(); - glm::mat4 projView = projection * view; + + globalSpb->Get<GlobalShaderParameters>()->invProj = glm::inverse(projection); + + auto& view = globalSpb->Get<GlobalShaderParameters>()->view; + view = GetGameState()->GetViewMatrix(); + + auto& projView = globalSpb->Get<GlobalShaderParameters>()->projView; + projView = projection * view; //Render Entities constexpr size_t entitiesVerticesCount = 240; entitiesPipeline->Activate(); - entitiesPipeline->SetShaderParameter("projView", projView); - entitiesPipelineInstance->Activate(); for (auto& it : entities) { it.Render(entitiesPipeline, &GetGameState()->GetWorld()); @@ -309,7 +315,7 @@ void RendererWorld::Render(float screenRatio) { model = glm::translate(model,glm::vec3(0.5f,0.5f,0.5f)); model = glm::scale(model,glm::vec3(1.01f,1.01f,1.01f)); entitiesPipeline->SetShaderParameter("model", model); - entitiesPipeline->SetShaderParameter("color", glm::vec3(0, 0, 0)); + entitiesPipeline->SetShaderParameter("entityColor", glm::vec3(0, 0, 0)); entitiesPipelineInstance->Render(0, entitiesVerticesCount); } } @@ -325,14 +331,50 @@ void RendererWorld::Render(float screenRatio) { //entityShader->SetUniform("model", model); entitiesPipeline->SetShaderParameter("model", model); if (selectedBlock == Vector()) - entitiesPipeline->SetShaderParameter("color", glm::vec3(0.7f, 0.0f, 0.0f)); + entitiesPipeline->SetShaderParameter("entityColor", glm::vec3(0.7f, 0.0f, 0.0f)); else - entitiesPipeline->SetShaderParameter("color", glm::vec3(0.0f, 0.0f, 0.7f)); + entitiesPipeline->SetShaderParameter("entityColor", glm::vec3(0.0f, 0.0f, 0.7f)); entitiesPipelineInstance->Render(0, entitiesVerticesCount); } } - //Render sky + //Render sections + auto rawGlobalTime = (std::chrono::high_resolution_clock::now() - globalTimeStart); + float globalTime = rawGlobalTime.count() / 1000000000.0f; + globalSpb->Get<GlobalShaderParameters>()->globalTime = globalTime; + sectionsPipeline->Activate(); + + Frustum frustum(projView); + renderList.clear(); + size_t culledSections = sections.size(); + unsigned int renderedFaces = 0; + for (auto& section : sections) { + glm::vec3 point{ + section.second.GetPosition().x * 16 + 8, + section.second.GetPosition().y * 16 + 8, + section.second.GetPosition().z * 16 + 8 + }; + + bool isVisible = frustum.TestSphere(point, 16.0f); + + if (!isVisible) { + culledSections--; + continue; + } + renderList.push_back(section.first); + renderedFaces += section.second.numOfFaces; + } + glm::vec3 playerChunk(GetGameState()->GetPlayer()->pos / 16); + std::sort(renderList.begin(), renderList.end(), [playerChunk](const Vector& lhs, const Vector& rhs) { + return glm::distance2(lhs.glm(), playerChunk) < glm::distance2(rhs.glm(), playerChunk); + }); + for (const auto& renderPos : renderList) { + sections.at(renderPos).Render(); + } + DebugInfo::culledSections = culledSections; + DebugInfo::renderFaces = renderedFaces; + + //Render sky glm::mat4 model = glm::mat4(1.0); model = glm::translate(model, GetGameState()->GetPlayer()->pos.glm()); const float scale = 1000000.0f; @@ -367,52 +409,22 @@ void RendererWorld::Render(float screenRatio) { mixLevel = 1.0 - (timePassed / moonriseLength); } + globalSpb->Get<GlobalShaderParameters>()->dayTime = mixLevel; + skyPipeline->Activate(); - skyPipeline->SetShaderParameter("projView", projView); skyPipeline->SetShaderParameter("model", model); - skyPipeline->SetShaderParameter("DayTime", mixLevel); skyPipelineInstance->Activate(); skyPipelineInstance->Render(0, 36); - - - //Render sections - auto rawGlobalTime = (std::chrono::high_resolution_clock::now() - globalTimeStart); - float globalTime = rawGlobalTime.count() / 1000000000.0f; - sectionsPipeline->Activate(); - sectionsPipeline->SetShaderParameter("DayTime", mixLevel); - sectionsPipeline->SetShaderParameter("projView", projView); - - Frustum frustum(projView); - - size_t culledSections = sections.size(); - unsigned int renderedFaces = 0; - for (auto& section : sections) { - glm::vec3 point{ - section.second.GetPosition().x * 16 + 8, - section.second.GetPosition().y * 16 + 8, - section.second.GetPosition().z * 16 + 8 - }; - - bool isVisible = frustum.TestSphere(point, 16.0f); - - if (!isVisible) { - culledSections--; - continue; - } - section.second.Render(); - renderedFaces += section.second.numOfFaces; - } - DebugInfo::culledSections = culledSections; - DebugInfo::renderFaces = renderedFaces; } -void RendererWorld::PrepareRender(std::shared_ptr<Gal::Framebuffer> target) { +void RendererWorld::PrepareRender(std::shared_ptr<Gal::Framebuffer> target, bool defferedShading) { std::string sectionVertexSource, sectionPixelSource; { auto vertAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/vert/face"); sectionVertexSource = std::string((char*)vertAsset->data.data(), (char*)vertAsset->data.data() + vertAsset->data.size()); - auto pixelAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/face"); + auto pixelAsset = defferedShading ? AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/face") : + AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/fwd_face"); sectionPixelSource = std::string((char*)pixelAsset->data.data(), (char*)pixelAsset->data.data() + pixelAsset->data.size()); } @@ -421,7 +433,8 @@ void RendererWorld::PrepareRender(std::shared_ptr<Gal::Framebuffer> target) { auto vertAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/vert/entity"); entitiesVertexSource = std::string((char*)vertAsset->data.data(), (char*)vertAsset->data.data() + vertAsset->data.size()); - auto pixelAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/entity"); + auto pixelAsset = defferedShading ? AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/entity") : + AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/fwd_entity"); entitiesPixelSource = std::string((char*)pixelAsset->data.data(), (char*)pixelAsset->data.data() + pixelAsset->data.size()); } @@ -430,7 +443,8 @@ void RendererWorld::PrepareRender(std::shared_ptr<Gal::Framebuffer> target) { auto vertAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/vert/sky"); skyVertexSource = std::string((char*)vertAsset->data.data(), (char*)vertAsset->data.data() + vertAsset->data.size()); - auto pixelAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/sky"); + auto pixelAsset = defferedShading ? AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/sky") : + AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/fwd_sky"); skyPixelSource = std::string((char*)pixelAsset->data.data(), (char*)pixelAsset->data.data() + pixelAsset->data.size()); } @@ -438,38 +452,31 @@ void RendererWorld::PrepareRender(std::shared_ptr<Gal::Framebuffer> target) { { auto sectionsPLC = gal->CreatePipelineConfig(); sectionsPLC->SetTarget(target); - sectionsPLC->AddShaderParameter("projView", Gal::Type::Mat4); - sectionsPLC->AddShaderParameter("DayTime", Gal::Type::Float); - sectionsPLC->AddShaderParameter("GlobalTime", Gal::Type::Float); - sectionsPLC->AddShaderParameter("MinLightLevel", Gal::Type::Float); sectionsPLC->AddStaticTexture("textureAtlas", AssetManager::GetTextureAtlas()); sectionsPLC->SetVertexShader(gal->LoadVertexShader(sectionVertexSource)); sectionsPLC->SetPixelShader(gal->LoadPixelShader(sectionPixelSource)); sectionsPLC->SetPrimitive(Gal::Primitive::TriangleFan); sectionsBufferBinding = sectionsPLC->BindVertexBuffer({ - {"position", Gal::Type::Vec3, 4, 1}, + {"pos", Gal::Type::Vec3, 4, 1}, {"uv", Gal::Type::Vec2, 4, 1}, - {"uvLayer", Gal::Type::Float, 1, 1}, - {"animation", Gal::Type::Float, 1, 1}, + {"light", Gal::Type::Vec2, 4, 1}, + {"normal", Gal::Type::Vec3, 1, 1}, {"color", Gal::Type::Vec3, 1, 1}, - {"light", Gal::Type::Vec2, 1, 1}, - {"", Gal::Type::Uint8, 20, 1} + {"layerAnimationAo", Gal::Type::Vec3, 1, 1}, }); sectionsPipeline = gal->BuildPipeline(sectionsPLC); - sectionsPipeline->SetShaderParameter("MinLightLevel", 0.2f); } { auto entitiesPLC = gal->CreatePipelineConfig(); entitiesPLC->SetTarget(target); - entitiesPLC->AddShaderParameter("projView", Gal::Type::Mat4); entitiesPLC->AddShaderParameter("model", Gal::Type::Mat4); - entitiesPLC->AddShaderParameter("color", Gal::Type::Vec3); + entitiesPLC->AddShaderParameter("entityColor", Gal::Type::Vec3); entitiesPLC->SetVertexShader(gal->LoadVertexShader(entitiesVertexSource)); entitiesPLC->SetPixelShader(gal->LoadPixelShader(entitiesPixelSource)); entitiesPLC->SetPrimitive(Gal::Primitive::Triangle); auto entitiesPosBB = entitiesPLC->BindVertexBuffer({ - {"position", Gal::Type::Vec3}, + {"pos", Gal::Type::Vec3}, }); auto entitiesIndicesBB = entitiesPLC->BindIndexBuffer(); @@ -630,14 +637,12 @@ void RendererWorld::PrepareRender(std::shared_ptr<Gal::Framebuffer> target) { skyPPC->AddShaderParameter("sunTextureLayer", Gal::Type::Float); skyPPC->AddShaderParameter("moonTexture", Gal::Type::Vec4); skyPPC->AddShaderParameter("moonTextureLayer", Gal::Type::Float); - skyPPC->AddShaderParameter("DayTime", Gal::Type::Float); - skyPPC->AddShaderParameter("projView", Gal::Type::Mat4); skyPPC->AddShaderParameter("model", Gal::Type::Mat4); skyPPC->AddStaticTexture("textureAtlas", AssetManager::GetTextureAtlas()); skyPPC->SetVertexShader(gal->LoadVertexShader(skyVertexSource)); skyPPC->SetPixelShader(gal->LoadPixelShader(skyPixelSource)); auto skyPosUvBB = skyPPC->BindVertexBuffer({ - {"position", Gal::Type::Vec3}, + {"pos", Gal::Type::Vec3}, {"", Gal::Type::Vec2}, }); diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp index e645b30..438c022 100644 --- a/src/RendererWorld.hpp +++ b/src/RendererWorld.hpp @@ -55,14 +55,15 @@ class RendererWorld { std::shared_ptr<Gal::PipelineInstance> skyPipelineInstance; std::shared_ptr<Gal::Buffer> skyBuffer; public: - RendererWorld(std::shared_ptr<Gal::Framebuffer> target); + RendererWorld(std::shared_ptr<Gal::Framebuffer> target, bool defferedShading, bool smoothLighting); ~RendererWorld(); void Render(float screenRatio); - void PrepareRender(std::shared_ptr<Gal::Framebuffer> target); + void PrepareRender(std::shared_ptr<Gal::Framebuffer> target, bool defferedShading); double MaxRenderingDistance; void Update(double timeToUpdate); + bool smoothLighting; }; diff --git a/src/Rml.cpp b/src/Rml.cpp index fa2d4e7..f6fff44 100644 --- a/src/Rml.cpp +++ b/src/Rml.cpp @@ -64,15 +64,15 @@ RmlRenderInterface::RmlRenderInterface() { { auto pipelineConfig = gal->CreatePipelineConfig(); - pipelineConfig->AddShaderParameter("viewportSize", Gal::Type::Vec2u32); pipelineConfig->AddShaderParameter("translation", Gal::Type::Vec2); pipelineConfig->SetTarget(gal->GetDefaultFramebuffer()); pipelineConfig->SetVertexShader(gal->LoadVertexShader(vertexSource)); pipelineConfig->SetPixelShader(gal->LoadPixelShader(pixelSource)); + pipelineConfig->SetBlending(Gal::Blending::Additive); auto vertBuffBind = pipelineConfig->BindVertexBuffer({ {"pos", Gal::Type::Vec2}, - {"color", Gal::Type::Vec4u8}, + {"col", Gal::Type::Vec4u8}, {"", Gal::Type::Vec2}, //it's not used in shader, so driver optimizes it away }); @@ -88,17 +88,17 @@ RmlRenderInterface::RmlRenderInterface() { { auto texPipelineConfig = gal->CreatePipelineConfig(); - texPipelineConfig->AddShaderParameter("viewportSize", Gal::Type::Vec2u32); texPipelineConfig->AddShaderParameter("translation", Gal::Type::Vec2); texPipelineConfig->AddShaderParameter("fontTexture", Gal::Type::Int32); texPipelineConfig->SetTarget(gal->GetDefaultFramebuffer()); texPipelineConfig->SetVertexShader(gal->LoadVertexShader(vertexSource)); texPipelineConfig->SetPixelShader(gal->LoadPixelShader(texPixelSource)); + texPipelineConfig->SetBlending(Gal::Blending::Additive); auto texVertBuffBind = texPipelineConfig->BindVertexBuffer({ {"pos", Gal::Type::Vec2}, - {"color", Gal::Type::Vec4u8}, - {"tex_coord", Gal::Type::Vec2}, + {"col", Gal::Type::Vec4u8}, + {"uvPos", Gal::Type::Vec2}, }); auto texIndexBuffBind = texPipelineConfig->BindIndexBuffer(); @@ -165,9 +165,6 @@ void RmlRenderInterface::ReleaseTexture(Rml::TextureHandle texture) { } void RmlRenderInterface::Update(unsigned int windowWidth, unsigned int windowHeight) { - pipeline->SetShaderParameter("viewportSize", glm::uvec2(windowWidth, windowHeight)); - texPipeline->SetShaderParameter("viewportSize", glm::uvec2(windowWidth, windowHeight)); - vpWidth = windowWidth; vpHeight = windowHeight; } diff --git a/src/TextureAtlas.cpp b/src/TextureAtlas.cpp index 7e44a86..9ad018e 100644 --- a/src/TextureAtlas.cpp +++ b/src/TextureAtlas.cpp @@ -89,6 +89,7 @@ TextureAtlas::TextureAtlas(std::vector<TextureData> &textures) { texConfig->SetWrapping(Gal::Wrapping::Clamp); texConfig->SetMinFilter(Gal::Filtering::Nearest); texConfig->SetMaxFilter(Gal::Filtering::Nearest); + texConfig->SetLinear(false); texture = gal->BuildTexture(texConfig); |