diff --git a/res/shaders/background.glslf b/res/shaders/background.glslf index 6915e41c..b6807a2f 100644 --- a/res/shaders/background.glslf +++ b/res/shaders/background.glslf @@ -7,7 +7,7 @@ uniform samplerCube u_cubemap; void main(){ vec3 dir = normalize(v_coord); - f_position = vec4(100000.0); + f_position = vec4(0.0, 0.0, 0.0, 1e9); f_normal = vec4(0.0); f_color = texture(u_cubemap, dir); } diff --git a/res/shaders/effect.glslf b/res/shaders/effect.glslf index 3f7782c6..32f69048 100644 --- a/res/shaders/effect.glslf +++ b/res/shaders/effect.glslf @@ -10,6 +10,7 @@ uniform sampler2D u_shadows; uniform ivec2 u_screenSize; uniform float u_intensity; uniform float u_timer; +uniform bool u_enableShadows; uniform mat4 u_projection; #include <__effect__> diff --git a/res/shaders/effects/default.glsl b/res/shaders/effects/default.glsl index 1059d29b..c2f9effa 100644 --- a/res/shaders/effects/default.glsl +++ b/res/shaders/effects/default.glsl @@ -1,50 +1,3 @@ -uniform vec3 samples[64]; - -int kernelSize = 32; -float radius = 0.25; -float bias = 0.025; - -float near_plane = 0.5f; -float far_plane = 200.0f; - -// required when using a perspective projection matrix -float linearize_depth(float depth) { - float z = depth * 2.0 - 1.0; // Back to NDC - return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane)); -} - -float fmod(float x, float y) { - return x - y * floor(x/y); -} - vec4 effect() { - vec2 noiseScale = u_screenSize / 4.0; - - vec3 position = texture(u_position, v_uv).xyz; - vec3 color = texture(u_screen, v_uv).rgb; - vec3 normal = texture(u_normal, v_uv).xyz; - vec3 randomVec = normalize(texture(u_noise, v_uv * noiseScale).xyz); - - vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); - vec3 bitangent = cross(normal, tangent); - mat3 TBN = mat3(tangent, bitangent, normal); - - float occlusion = 0.0; - for(int i = 0; i < kernelSize; ++i) - { - vec3 samplePos = TBN * samples[i]; - samplePos = position + samplePos * radius; - - vec4 offset = vec4(samplePos, 1.0); - offset = u_projection * offset; - offset.xyz /= offset.w; - offset.xyz = offset.xyz * 0.5 + 0.5; - - float sampleDepth = texture(u_position, offset.xy).z; - float rangeCheck = smoothstep(0.0, 1.0, radius / abs(position.z - sampleDepth)); - occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck; - } - occlusion = 1.1 - (occlusion / kernelSize); - float d = texture(u_shadows, v_uv).r; - return vec4(color * occlusion, 1.0); + return texture(u_screen, v_uv); } diff --git a/res/shaders/effects/ssao.glsl b/res/shaders/effects/ssao.glsl index f7add4f9..f0f65eb6 100644 --- a/res/shaders/effects/ssao.glsl +++ b/res/shaders/effects/ssao.glsl @@ -1,11 +1,39 @@ -uniform vec3 samples[64]; +uniform vec3 u_ssaoSamples[64]; + +int kernelSize = 32; +float radius = 0.25; +float bias = 0.025; vec4 effect() { - vec2 noiseScale = u_screenSize / 4.0; + vec2 noiseScale = u_screenSize / 4.0; vec3 position = texture(u_position, v_uv).xyz; vec3 color = texture(u_screen, v_uv).rgb; vec3 normal = texture(u_normal, v_uv).xyz; - vec3 randomVec = texture(u_noise, v_uv * noiseScale).xyz; - return vec4(randomVec, 1.0); + vec3 randomVec = normalize(texture(u_noise, v_uv * noiseScale).xyz); + + vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); + vec3 bitangent = cross(normal, tangent); + mat3 tbn = mat3(tangent, bitangent, normal); + + float occlusion = 1.0; + if (u_enableShadows) { + occlusion = 0.0; + for (int i = 0; i < kernelSize; i++) { + vec3 samplePos = tbn * u_ssaoSamples[i]; + samplePos = position + samplePos * radius; + + vec4 offset = vec4(samplePos, 1.0); + offset = u_projection * offset; + offset.xyz /= offset.w; + offset.xyz = offset.xyz * 0.5 + 0.5; + + float sampleDepth = texture(u_position, offset.xy).z; + float rangeCheck = smoothstep(0.0, 1.0, radius / abs(position.z - sampleDepth)); + occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck; + } + occlusion = 1.1 - (occlusion / kernelSize); + } + + return vec4(color * occlusion, 1.0); } diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index 837ffaf1..db8b8982 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -37,18 +37,17 @@ void main() { for (int i = 0; i < BLUR_SAMPLES; i++) { shadow += texture(u_shadows, projCoords.xyz + vec3( - -0.002*(i%2==0?1:0)*i/BLUR_SAMPLES, - -0.002*(i%2==0?0:1)*i/BLUR_SAMPLES, + -0.002*(i%2==0?1:0)*i/BLUR_SAMPLES / 4.0, + -0.002*(i%2==0?0:1)*i/BLUR_SAMPLES / 4.0, -0.0005 * i/BLUR_SAMPLES)); } shadow /= BLUR_SAMPLES; - shadow += 0.5; - shadow = shadow * 0.7 + 0.3; + shadow = shadow * 0.5 + 0.5; } vec3 fogColor = texture(u_cubemap, a_dir).rgb; - vec4 tex_color = texture(u_texture0, a_texCoord); - float alpha = a_color.a * tex_color.a; + vec4 texColor = texture(u_texture0, a_texCoord); + float alpha = a_color.a * texColor.a; if (u_alphaClip) { if (alpha < 0.2f) discard; @@ -58,12 +57,13 @@ void main() { discard; } if (u_debugLights) - tex_color.rgb = u_debugNormals ? (a_normal * 0.5 + 0.5) : vec3(1.0); + texColor.rgb = u_debugNormals ? (a_normal * 0.5 + 0.5) : vec3(1.0); else if (u_debugNormals) { - tex_color.rgb *= a_normal * 0.5 + 0.5; + texColor.rgb *= a_normal * 0.5 + 0.5; } - f_color = mix(a_color * tex_color, vec4(fogColor,1.0), a_fog); + f_color = a_color * texColor; f_color.rgb *= shadow; + f_color = mix(f_color, vec4(fogColor,1.0), a_fog); f_color.a = alpha; f_position = vec4(a_position, 1.0); f_normal = vec4(a_normal, 1.0); diff --git a/src/graphics/core/Framebuffer.cpp b/src/graphics/core/Framebuffer.cpp index c8ed0c42..7f86dd20 100644 --- a/src/graphics/core/Framebuffer.cpp +++ b/src/graphics/core/Framebuffer.cpp @@ -42,22 +42,8 @@ Framebuffer::Framebuffer(uint width, uint height, bool alpha) // Setup color attachment (texture) texture = create_texture(width, height, format); - glGenTextures(1, &positions); - glBindTexture(GL_TEXTURE_2D, positions); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positions, 0); - - glGenTextures(1, &normals); - glBindTexture(GL_TEXTURE_2D, normals); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normals, 0); - - unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; - glDrawBuffers(3, attachments); + unsigned int attachments[1] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, attachments); // Setup depth attachment glGenRenderbuffers(1, &depth); @@ -74,7 +60,6 @@ Framebuffer::Framebuffer(uint width, uint height, bool alpha) Framebuffer::~Framebuffer() { glDeleteFramebuffers(1, &fbo); - glDeleteTextures(1, &normals); glDeleteTextures(1, &depth); } @@ -86,19 +71,6 @@ void Framebuffer::unbind() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } -void Framebuffer::bindBuffers() { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->getId()); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, positions); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, normals); - - glActiveTexture(GL_TEXTURE0); -} - void Framebuffer::resize(uint width, uint height) { if (this->width == width && this->height == height) { return; @@ -112,16 +84,6 @@ void Framebuffer::resize(uint width, uint height) { glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); glBindRenderbuffer(GL_RENDERBUFFER, 0); - glBindTexture(GL_TEXTURE_2D, positions); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positions, 0); - - glBindTexture(GL_TEXTURE_2D, normals); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normals, 0); - - glBindTexture(GL_TEXTURE_2D, 0); - texture = create_texture(width, height, format); glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/src/graphics/core/Framebuffer.hpp b/src/graphics/core/Framebuffer.hpp index 35df9ffa..2392ac43 100644 --- a/src/graphics/core/Framebuffer.hpp +++ b/src/graphics/core/Framebuffer.hpp @@ -10,8 +10,6 @@ class Texture; class Framebuffer : public Bindable { uint fbo; uint depth; - uint positions; - uint normals; uint width; uint height; uint format; @@ -27,8 +25,6 @@ public: /// @brief Stop using framebuffer void unbind() override; - void bindBuffers(); - /// @brief Update framebuffer texture size /// @param width new width /// @param height new height diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index f504287e..901b6a57 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -117,7 +117,7 @@ void GBuffer::unbind() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } -void GBuffer::bindBuffers() { +void GBuffer::bindBuffers() const { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, normalsBuffer); @@ -177,6 +177,16 @@ void GBuffer::resize(uint width, uint height) { glBindFramebuffer(GL_FRAMEBUFFER, 0); } +std::unique_ptr GBuffer::toImage() const { + auto data = std::make_unique(width * height * 3); + glBindTexture(GL_TEXTURE_2D, colorBuffer); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, data.get()); + glBindTexture(GL_TEXTURE_2D, 0); + return std::make_unique( + ImageFormat::rgb888, width, height, std::move(data) + ); +} + uint GBuffer::getWidth() const { return width; } diff --git a/src/graphics/core/GBuffer.hpp b/src/graphics/core/GBuffer.hpp index 6269c542..c5e51d4a 100644 --- a/src/graphics/core/GBuffer.hpp +++ b/src/graphics/core/GBuffer.hpp @@ -2,21 +2,24 @@ #include "typedefs.hpp" #include "commons.hpp" +#include "ImageData.hpp" -class GBuffer : public Bindable{ +class GBuffer : public Bindable { public: GBuffer(uint width, uint height); - ~GBuffer(); + ~GBuffer() override; void bind() override; void unbind() override; - void bindBuffers(); + void bindBuffers() const; void resize(uint width, uint height); uint getWidth() const; uint getHeight() const; + + std::unique_ptr toImage() const; private: uint width; uint height; diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index c1b6dc96..e090783a 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -1,6 +1,7 @@ #include "PostProcessing.hpp" #include "Mesh.hpp" #include "Shader.hpp" +#include "GBuffer.hpp" #include "Texture.hpp" #include "Framebuffer.hpp" #include "DrawContext.hpp" @@ -60,22 +61,65 @@ PostProcessing::PostProcessing(size_t effectSlotsCount) PostProcessing::~PostProcessing() = default; -void PostProcessing::use(DrawContext& context) { +void PostProcessing::use(DrawContext& context, bool gbufferPipeline) { const auto& vp = context.getViewport(); - if (fbo) { - fbo->resize(vp.x, vp.y); - fboSecond->resize(vp.x, vp.y); + + if (gbufferPipeline) { + if (gbuffer == nullptr) { + gbuffer = std::make_unique(vp.x, vp.y); + } else { + gbuffer->resize(vp.x, vp.y); + } + context.setFramebuffer(gbuffer.get()); } else { - fbo = std::make_unique(vp.x, vp.y); - fboSecond = std::make_unique(vp.x, vp.y); + if (fbo) { + fbo->resize(vp.x, vp.y); + fboSecond->resize(vp.x, vp.y); + } else { + fbo = std::make_unique(vp.x, vp.y); + fboSecond = std::make_unique(vp.x, vp.y); + } + context.setFramebuffer(fbo.get()); } - context.setFramebuffer(fbo.get()); +} + +void PostProcessing::configureEffect( + const DrawContext& context, + Shader& shader, + float timer, + const Camera& camera, + uint shadowMap +) { + const auto& viewport = context.getViewport(); + + if (!ssaoConfigured) { + for (unsigned int i = 0; i < 64; ++i) { + auto name = "u_ssaoSamples["+ std::to_string(i) + "]"; + shader.uniform3f(name, ssaoKernel[i]); + } + ssaoConfigured = true; + } + shader.uniform1i("u_screen", 0); + if (gbuffer) { + shader.uniform1i("u_position", 1); + shader.uniform1i("u_normal", 2); + } + shader.uniform1i("u_noise", 3); + shader.uniform1i("u_shadows", 4); + shader.uniform2i("u_screenSize", viewport); + shader.uniform1f("u_timer", timer); + shader.uniform1i("u_enableShadows", shadowMap != 0); + shader.uniformMatrix("u_projection", camera.getProjection()); } void PostProcessing::render( - const DrawContext& context, const Assets& assets, float timer, const Camera& camera, uint depthMap + const DrawContext& context, + const Assets& assets, + float timer, + const Camera& camera, + uint shadowMap ) { - if (fbo == nullptr) { + if (fbo == nullptr && gbuffer == nullptr) { throw std::runtime_error("'use(...)' was never called"); } int totalPasses = 0; @@ -83,40 +127,24 @@ void PostProcessing::render( totalPasses += (effect != nullptr && effect->isActive()); } - if (totalPasses == 0) { - auto& effect = assets.require("default"); - fbo->getTexture()->bind(); - fbo->bindBuffers(); + if (gbuffer) { + gbuffer->bindBuffers(); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, noiseTexture); - glActiveTexture(GL_TEXTURE0); - + glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, depthMap); - glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, shadowMap); + } else { + fbo->getTexture()->bind(); + } - const auto& viewport = context.getViewport(); + glActiveTexture(GL_TEXTURE0); + if (totalPasses == 0) { + auto& effect = assets.require("default"); auto& shader = effect.use(); - if (!ssaoConfigured) { - for (unsigned int i = 0; i < 64; ++i) { - auto name = "samples["+ std::to_string(i) + "]"; - shader.uniform3f(name, ssaoKernel[i]); - } - ssaoConfigured = true; - } - shader.uniform1i("u_screen", 0); - shader.uniform1i("u_position", 1); - shader.uniform1i("u_normal", 2); - shader.uniform1i("u_noise", 3); - shader.uniform1i("u_shadows", 4); - shader.uniform2i("u_screenSize", viewport); - shader.uniform1f("u_timer", timer); - shader.uniform1f("near_plane", camera.near); - shader.uniform1f("far_plane", camera.far); - shader.uniformMatrix("u_projection", camera.getProjection()); - + configureEffect(context, shader, timer, camera, shadowMap); quadMesh->draw(); return; } @@ -127,21 +155,9 @@ void PostProcessing::render( continue; } auto& shader = effect->use(); + configureEffect(context, shader, timer, camera, shadowMap); - for (unsigned int i = 0; i < 64; ++i) { - shader.uniform3f("samples["+ std::to_string(i) + "]", ssaoKernel[i]); - } - - const auto& viewport = context.getViewport(); - shader.uniform1i("u_screen", 0); - shader.uniform1i("u_position", 1); - shader.uniform1i("u_normal", 2); - shader.uniform1i("u_noise", 3); - shader.uniform2i("u_screenSize", viewport); - shader.uniform1f("u_timer", timer); - shader.uniformMatrix("u_projection", camera.getProjView(false)); fbo->getTexture()->bind(); - fbo->bindBuffers(); if (currentPass < totalPasses) { fboSecond->bind(); @@ -165,6 +181,9 @@ PostEffect* PostProcessing::getEffect(size_t slot) { } std::unique_ptr PostProcessing::toImage() { + if (gbuffer) { + return gbuffer->toImage(); + } return fbo->getTexture()->readData(); } diff --git a/src/graphics/core/PostProcessing.hpp b/src/graphics/core/PostProcessing.hpp index a90d8abc..0ab31a49 100644 --- a/src/graphics/core/PostProcessing.hpp +++ b/src/graphics/core/PostProcessing.hpp @@ -12,6 +12,8 @@ class DrawContext; class ImageData; class PostEffect; class Camera; +class GBuffer; +class Shader; struct PostProcessingVertex { glm::vec2 position; @@ -25,29 +27,25 @@ struct PostProcessingVertex { /// @attention Current implementation does not support multiple render passes /// for multiple effects. Will be implemented in v0.21 class PostProcessing { - /// @brief Main framebuffer (lasy field) - std::unique_ptr fbo; - std::unique_ptr fboSecond; - /// @brief Fullscreen quad mesh as the post-processing canvas - std::unique_ptr> quadMesh; - std::vector> effectSlots; - - std::vector ssaoKernel; - uint noiseTexture; - bool ssaoConfigured = false; public: PostProcessing(size_t effectSlotsCount); ~PostProcessing(); /// @brief Prepare and bind framebuffer /// @param context graphics context will be modified - void use(DrawContext& context); + void use(DrawContext& context, bool gbufferPipeline); /// @brief Render fullscreen quad using the passed shader /// with framebuffer texture bound /// @param context graphics context /// @throws std::runtime_error if use(...) wasn't called before - void render(const DrawContext& context, const Assets& assets, float timer, const Camera& camera, uint depthMap); + void render( + const DrawContext& context, + const Assets& assets, + float timer, + const Camera& camera, + uint shadowMap + ); void setEffect(size_t slot, std::shared_ptr effect); @@ -57,4 +55,24 @@ public: std::unique_ptr toImage(); Framebuffer* getFramebuffer() const; +private: + void configureEffect( + const DrawContext& context, + Shader& shader, + float timer, + const Camera& camera, + uint shadowMap + ); + + /// @brief Main framebuffer (lasy field) + std::unique_ptr fbo; + std::unique_ptr fboSecond; + /// @brief Fullscreen quad mesh as the post-processing canvas + std::unique_ptr> quadMesh; + std::vector> effectSlots; + std::unique_ptr gbuffer; + + std::vector ssaoKernel; + uint noiseTexture; + bool ssaoConfigured = false; }; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index c74ff31b..b3826cf4 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -103,7 +103,7 @@ WorldRenderer::WorldRenderer( assets->require("skybox_gen") ); - shadowMap = std::make_unique(1024); + shadowMap = std::make_unique(1024 * 4); shadowCamera = std::make_unique(); } @@ -373,18 +373,18 @@ void WorldRenderer::draw( auto& shadowsShader = assets.require("shadows"); if (gbufferPipeline) { - float shadowMapScale = 0.05f; + float shadowMapScale = 0.05f * 2; float shadowMapSize = shadowMap->getResolution() * shadowMapScale; *shadowCamera = Camera(camera.position, shadowMapSize); shadowCamera->near = 0.5f; shadowCamera->far = 600.0f; shadowCamera->perspective = false; shadowCamera->setAspectRatio(1.0f); - shadowCamera->rotate(glm::radians(-65.0f), glm::radians(-35.0f), glm::radians(-35.0f)); + shadowCamera->rotate(glm::radians(-64.0f), glm::radians(-35.0f), glm::radians(-35.0f)); //shadowCamera.perspective = false; - /*shadowCamera.rotation = //glm::inverse( - glm::lookAt({}, glm::normalize(shadowCamera.position-camera.position), glm::vec3(0, 1, 0)); - //);*/ + // shadowCamera->rotation = glm::inverse( + // glm::lookAt({}, glm::normalize(camera.position-shadowCamera->position), glm::vec3(0, 1, 0)) + // ); shadowCamera->updateVectors(); //shadowCamera->position += camera.dir * shadowMapSize * 0.5f; shadowCamera->position -= shadowCamera->front * 100.0f; @@ -406,16 +406,7 @@ void WorldRenderer::draw( /* World render scope with diegetic HUD included */ { DrawContext wctx = pctx.sub(); - if (gbufferPipeline) { - if (gbuffer == nullptr) { - gbuffer = std::make_unique(vp.x, vp.y); - } else { - gbuffer->resize(vp.x, vp.y); - } - wctx.setFramebuffer(gbuffer.get()); - } else { - postProcessing.use(wctx); - } + postProcessing.use(wctx, gbufferPipeline); display::clearDepth(); @@ -446,7 +437,13 @@ void WorldRenderer::draw( //renderBlockOverlay(wctx); } - postProcessing.render(pctx, assets, timer, camera, shadowMap->getDepthMap()); + postProcessing.render( + pctx, + assets, + timer, + camera, + gbufferPipeline ? shadowMap->getDepthMap() : 0 + ); } void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 9759dd39..2832fca2 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -54,9 +54,7 @@ class WorldRenderer { float timer = 0.0f; bool debug = false; bool lightsDebug = false; - - std::unique_ptr gbuffer; - bool gbufferPipeline = false; + bool gbufferPipeline = true; /// @brief Render block selection lines void renderBlockSelection();