From ac9772cd67686347fed22c8c35bbedaec884e778 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 17:31:55 +0300 Subject: [PATCH] fix render advanced pipeline issues --- res/shaders/entity.glslf | 12 ++- res/shaders/main.glslf | 8 +- src/coders/GLSLExtension.cpp | 1 - src/graphics/core/Framebuffer.cpp | 4 + src/graphics/core/Framebuffer.hpp | 2 + src/graphics/core/GBuffer.cpp | 4 +- src/graphics/core/GBuffer.hpp | 2 +- src/graphics/core/PostProcessing.cpp | 124 ++++++++++++++++---------- src/graphics/core/PostProcessing.hpp | 12 +++ src/graphics/render/WorldRenderer.cpp | 101 ++++++++++++++------- src/graphics/render/WorldRenderer.hpp | 7 ++ src/window/detail/GLFWWindow.cpp | 1 + 12 files changed, 192 insertions(+), 86 deletions(-) diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index 8cc2f75a..7c916955 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -24,15 +24,19 @@ uniform vec3 u_sunDir; void main() { float shadow = calc_shadow(a_modelpos, a_realnormal, a_distance); - vec3 fogColor = texture(u_skybox, 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; // anyway it's any alpha-test alternative required if (alpha < (u_alphaClip ? 0.5f : 0.15f)) { discard; } - f_color = a_color * tex_color * shadow; + f_color = a_color * texColor * shadow; + +#ifndef ADVANCED_RENDER + vec3 fogColor = texture(u_skybox, a_dir).rgb; f_color = mix(f_color, vec4(fogColor, 1.0), a_fog); +#endif + f_color.a = alpha; f_position = vec4(a_position, 1.0); f_normal = vec4(a_normal, 1.0); diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index 2767390b..ff6816a7 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -25,7 +25,6 @@ uniform bool u_debugNormals; #include void main() { - //vec3 fogColor = texture(u_skybox, a_dir).rgb; vec4 texColor = texture(u_texture0, a_texCoord); float alpha = texColor.a; if (u_alphaClip) { @@ -43,7 +42,12 @@ void main() { } f_color = texColor; f_color.rgb *= min(vec3(1.0), a_torchLight.rgb + a_skyLight); - //f_color = mix(f_color, vec4(fogColor, 1.0), a_fog * 0.0); + +#ifndef ADVANCED_RENDER + vec3 fogColor = texture(u_skybox, a_dir).rgb; + f_color = mix(f_color, vec4(fogColor, 1.0), a_fog); +#endif + f_color.a = alpha; f_position = vec4(a_position, 1.0); f_normal = vec4(a_normal, 1.0); diff --git a/src/coders/GLSLExtension.cpp b/src/coders/GLSLExtension.cpp index f6543092..27ec7b63 100644 --- a/src/coders/GLSLExtension.cpp +++ b/src/coders/GLSLExtension.cpp @@ -158,7 +158,6 @@ public: } bool processVersionDirective() { - parsing_warning(filename, line, "removed #version directive"); source_line(ss, line); skipLine(); return false; diff --git a/src/graphics/core/Framebuffer.cpp b/src/graphics/core/Framebuffer.cpp index e009f747..bb360b54 100644 --- a/src/graphics/core/Framebuffer.cpp +++ b/src/graphics/core/Framebuffer.cpp @@ -96,3 +96,7 @@ uint Framebuffer::getWidth() const { uint Framebuffer::getHeight() const { return height; } + +uint Framebuffer::getFBO() const { + return fbo; +} diff --git a/src/graphics/core/Framebuffer.hpp b/src/graphics/core/Framebuffer.hpp index 2392ac43..e48e97df 100644 --- a/src/graphics/core/Framebuffer.hpp +++ b/src/graphics/core/Framebuffer.hpp @@ -37,4 +37,6 @@ public: uint getWidth() const; /// @brief Get framebuffer height uint getHeight() const; + + uint getFBO() const; }; diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index acb491e4..8b154e91 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -181,9 +181,9 @@ void GBuffer::bindSSAOBuffer() const { glBindTexture(GL_TEXTURE_2D, ssaoBuffer); } -void GBuffer::bindDepthBuffer() { +void GBuffer::bindDepthBuffer(int drawFbo) { glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST); } diff --git a/src/graphics/core/GBuffer.hpp b/src/graphics/core/GBuffer.hpp index 8885db7d..ec3cc045 100644 --- a/src/graphics/core/GBuffer.hpp +++ b/src/graphics/core/GBuffer.hpp @@ -16,7 +16,7 @@ public: void bindBuffers() const; void bindSSAOBuffer() const; - void bindDepthBuffer(); + void bindDepthBuffer(int drawFbo); void resize(uint width, uint height); diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index 652b3b36..c2d24e60 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -77,7 +77,9 @@ void PostProcessing::refreshFbos(uint width, uint height) { } void PostProcessing::bindDepthBuffer() { - gbuffer->bindDepthBuffer(); + if (gbuffer) { + gbuffer->bindDepthBuffer(fbo->getFBO()); + } } void PostProcessing::configureEffect( @@ -118,7 +120,7 @@ void PostProcessing::configureEffect( shader.uniformMatrix("u_inverseView", glm::inverse(camera.getView())); } -void PostProcessing::render( +void PostProcessing::renderDeferredShading( const DrawContext& context, const Assets& assets, float timer, @@ -129,18 +131,9 @@ void PostProcessing::render( const glm::mat4& shadowMatrix2, uint shadowMapResolution ) { - if (fbo == nullptr && gbuffer == nullptr) { - throw std::runtime_error("'use(...)' was never called"); + if (gbuffer == nullptr) { + throw std::runtime_error("gbuffer is not initialized"); } - int totalPasses = 0; - for (const auto& effect : effectSlots) { - totalPasses += - (effect != nullptr && effect->isActive() && - !(effect->isAdvanced() && gbuffer == nullptr)); - } - - const auto& vp = context.getViewport(); - refreshFbos(vp.x, vp.y); glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS0); glBindTexture(GL_TEXTURE_2D, shadowMap); @@ -149,43 +142,47 @@ void PostProcessing::render( glBindTexture(GL_TEXTURE_2D, shadowMap2); // Generating ssao - if (gbuffer) { - gbuffer->bindBuffers(); + gbuffer->bindBuffers(); - glActiveTexture(GL_TEXTURE0 + TARGET_SSAO); - glBindTexture(GL_TEXTURE_2D, noiseTexture); + glActiveTexture(GL_TEXTURE0 + TARGET_SSAO); + glBindTexture(GL_TEXTURE_2D, noiseTexture); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); - auto& ssaoEffect = assets.require("ssao"); - auto& shader = ssaoEffect.use(); - configureEffect( - context, - ssaoEffect, - shader, - timer, - camera, - shadowMap, - shadowMap2, - shadowMatrix, - shadowMatrix2, - shadowMapResolution - ); - gbuffer->bindSSAO(); - quadMesh->draw(); - gbuffer->unbind(); + auto& ssaoEffect = assets.require("ssao"); + auto& shader = ssaoEffect.use(); + configureEffect( + context, + ssaoEffect, + shader, + timer, + camera, + shadowMap, + shadowMap2, + shadowMatrix, + shadowMatrix2, + shadowMapResolution + ); + gbuffer->bindSSAO(); + quadMesh->draw(); + gbuffer->unbind(); + + { + auto viewport = context.getViewport(); + refreshFbos(viewport.x, viewport.y); + + auto ctx = context.sub(); + ctx.setFramebuffer(fbo.get()); glActiveTexture(GL_TEXTURE0 + TARGET_SSAO); gbuffer->bindSSAOBuffer(); - } else { - glActiveTexture(GL_TEXTURE0); - fbo->getTexture()->bind(); - } - if (totalPasses == 0) { - auto& effect = assets.require( - gbuffer ? "deferred_lighting" : "default" - ); + glActiveTexture(GL_TEXTURE0); + + gbuffer->bindBuffers(); + + // TODO: move upper & move skybox->draw(...) here + auto& effect = assets.require("deferred_lighting"); auto& shader = effect.use(); configureEffect( context, @@ -200,6 +197,44 @@ void PostProcessing::render( shadowMapResolution ); quadMesh->draw(); + } +} + +void PostProcessing::render( + const DrawContext& context, + const Assets& assets, + float timer, + const Camera& camera, + uint shadowMap, + uint shadowMap2, + const glm::mat4& shadowMatrix, + const glm::mat4& shadowMatrix2, + uint shadowMapResolution +) { + if (fbo == nullptr) { + throw std::runtime_error("'use(...)' was never called"); + } + int totalPasses = 0; + for (const auto& effect : effectSlots) { + totalPasses += + (effect != nullptr && effect->isActive() && + !(effect->isAdvanced() && gbuffer == nullptr)); + } + + const auto& vp = context.getViewport(); + refreshFbos(vp.x, vp.y); + + glActiveTexture(GL_TEXTURE0); + fbo->getTexture()->bind(); + + if (totalPasses == 0) { + // TODO: move upper & move skybox->draw(...) here + auto& effect = assets.require("default"); + auto& shader = effect.use(); + configureEffect( + context, effect, shader, timer, camera, 0, 0, {}, {}, 0 + ); + quadMesh->draw(); return; } @@ -251,9 +286,6 @@ 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 fc49c950..556699db 100644 --- a/src/graphics/core/PostProcessing.hpp +++ b/src/graphics/core/PostProcessing.hpp @@ -35,6 +35,18 @@ public: /// @param context graphics context will be modified void use(DrawContext& context, bool gbufferPipeline); + void renderDeferredShading( + const DrawContext& context, + const Assets& assets, + float timer, + const Camera& camera, + uint shadowMap, + uint shadowMap2, + const glm::mat4& shadowMatrix, + const glm::mat4& shadowMatrix2, + uint shadowMapResolution + ); + /// @brief Render fullscreen quad using the passed shader /// with framebuffer texture bound /// @param context graphics context diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 390aeb32..053bd222 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -38,6 +38,7 @@ #include "graphics/core/LineBatch.hpp" #include "graphics/core/Mesh.hpp" #include "graphics/core/PostProcessing.hpp" +#include "graphics/core/Framebuffer.hpp" #include "graphics/core/Shader.hpp" #include "graphics/core/Texture.hpp" #include "graphics/core/Font.hpp" @@ -137,6 +138,7 @@ void WorldRenderer::setupWorldShader( if (shadows) { const auto& worldInfo = level.getWorld()->getInfo(); float cloudsIntensity = glm::max(worldInfo.fog, weather.clouds()); + shader.uniform1i("u_screen", 0); shader.uniformMatrix("u_shadowsMatrix[0]", shadowCamera.getProjView()); shader.uniformMatrix("u_shadowsMatrix[1]", wideShadowCamera.getProjView()); shader.uniform3f("u_sunDir", shadowCamera.front); @@ -223,22 +225,6 @@ void WorldRenderer::renderLevel( if (!pause) { scripting::on_frontend_render(); } - - setupWorldShader(entityShader, camera, settings, fogFactor); - - std::array weatherInstances {&weather.a, &weather.b}; - for (const auto& weather : weatherInstances) { - float maxIntensity = weather->fall.maxIntensity; - float zero = weather->fall.minOpacity; - float one = weather->fall.maxOpacity; - float t = (weather->intensity * (one - zero)) * maxIntensity + zero; - entityShader.uniform1i("u_alphaClip", weather->fall.opaque); - entityShader.uniform1f("u_opacity", weather->fall.opaque ? t * t : t); - if (weather->intensity > 1.e-3f && !weather->fall.texture.empty()) { - precipitation->render(camera, pause ? 0.0f : delta, *weather); - } - } - skybox->unbind(); } @@ -430,6 +416,7 @@ void WorldRenderer::draw( float uiDelta, PostProcessing& postProcessing ) { + // TODO: REFACTOR WHOLE RENDER ENGINE float delta = uiDelta * !pause; timer += delta; weather.update(delta); @@ -451,19 +438,37 @@ void WorldRenderer::draw( shadowMap = std::make_unique(resolution); wideShadowMap = std::make_unique(resolution); shadows = true; - Shader::preprocessor->define("ENABLE_SHADOWS", "true"); - mainShader.recompile(); - entityShader.recompile(); - deferredShader.recompile(); } else if (shadowsQuality == 0 && shadows) { shadowMap.reset(); wideShadowMap.reset(); shadows = false; - Shader::preprocessor->undefine("ENABLE_SHADOWS"); + } + + CompileTimeShaderSettings currentSettings { + gbufferPipeline, shadows + }; + if ( + prevCTShaderSettings.advancedRender != currentSettings.advancedRender || + prevCTShaderSettings.shadows != currentSettings.shadows + ) { + if (shadows) { + Shader::preprocessor->define("ENABLE_SHADOWS", "true"); + } else { + Shader::preprocessor->undefine("ENABLE_SHADOWS"); + } + + if (gbufferPipeline) { + Shader::preprocessor->define("ADVANCED_RENDER", "true"); + } else { + Shader::preprocessor->undefine("ADVANCED_RENDER"); + } + mainShader.recompile(); entityShader.recompile(); deferredShader.recompile(); + prevCTShaderSettings = currentSettings; } + if (shadows && shadowMap->getResolution() != resolution) { shadowMap = std::make_unique(resolution); wideShadowMap = std::make_unique(resolution); @@ -513,10 +518,52 @@ void WorldRenderer::draw( texts->render(pctx, camera, settings, hudVisible, true); } skybox->bind(); - deferredShader.use(); float fogFactor = 15.0f / static_cast(settings.chunks.loadDistance.get() - 2); - setupWorldShader(deferredShader, camera, settings, fogFactor); + if (gbufferPipeline) { + deferredShader.use(); + setupWorldShader(deferredShader, camera, settings, fogFactor); + postProcessing.renderDeferredShading( + pctx, + assets, + timer, + camera, + shadows ? shadowMap->getDepthMap() : 0, + shadows ? wideShadowMap->getDepthMap() : 0, + shadowCamera.getProjView(), + wideShadowCamera.getProjView(), + shadows ? shadowMap->getResolution() : 0 + ); + } + { + DrawContext ctx = pctx.sub(); + ctx.setDepthTest(true); + if (gbufferPipeline) { + postProcessing.bindDepthBuffer(); + } else { + postProcessing.getFramebuffer()->bind(); + } + // Drawing background sky plane + skybox->draw(ctx, camera, assets, worldInfo.daytime, clouds); + + entityShader.use(); + setupWorldShader(entityShader, camera, settings, fogFactor); + + std::array weatherInstances {&weather.a, &weather.b}; + for (const auto& weather : weatherInstances) { + float maxIntensity = weather->fall.maxIntensity; + float zero = weather->fall.minOpacity; + float one = weather->fall.maxOpacity; + float t = (weather->intensity * (one - zero)) * maxIntensity + zero; + entityShader.uniform1i("u_alphaClip", weather->fall.opaque); + entityShader.uniform1f("u_opacity", weather->fall.opaque ? t * t : t); + if (weather->intensity > 1.e-3f && !weather->fall.texture.empty()) { + precipitation->render(camera, pause ? 0.0f : delta, *weather); + } + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } postProcessing.render( pctx, assets, @@ -528,13 +575,7 @@ void WorldRenderer::draw( wideShadowCamera.getProjView(), shadows ? shadowMap->getResolution() : 0 ); - { - DrawContext ctx = pctx.sub(); - ctx.setDepthTest(true); - postProcessing.bindDepthBuffer(); - // Drawing background sky plane - skybox->draw(ctx, camera, assets, worldInfo.daytime, clouds); - } + skybox->unbind(); if (player.currentCamera == player.fpCamera) { DrawContext ctx = pctx.sub(); diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 59c959b7..ec159012 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -35,6 +35,11 @@ class ShadowMap; class GBuffer; struct EngineSettings; +struct CompileTimeShaderSettings { + bool advancedRender = false; + bool shadows = false; +}; + class WorldRenderer { Engine& engine; const Level& level; @@ -59,6 +64,8 @@ class WorldRenderer { bool gbufferPipeline = false; bool shadows = false; + CompileTimeShaderSettings prevCTShaderSettings {}; + /// @brief Render block selection lines void renderBlockSelection(); diff --git a/src/window/detail/GLFWWindow.cpp b/src/window/detail/GLFWWindow.cpp index 3d7ac26e..9a99405d 100644 --- a/src/window/detail/GLFWWindow.cpp +++ b/src/window/detail/GLFWWindow.cpp @@ -519,6 +519,7 @@ public: } std::unique_ptr takeScreenshot() override { + glBindFramebuffer(GL_FRAMEBUFFER, 0); auto data = std::make_unique(size.x * size.y * 3); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0, 0, size.x, size.y, GL_RGB, GL_UNSIGNED_BYTE, data.get());