From fc46b7c43431e0b5edd2b132081aeb9271a2d3f3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 7 May 2025 20:42:50 +0300 Subject: [PATCH 01/47] initial commit --- res/preload.json | 6 +- res/resources.json | 3 + res/scripts/hud.lua | 4 + res/shaders/background.glslf | 6 +- res/shaders/effect.glslf | 7 + res/shaders/effects/default.glsl | 51 ++++++- res/shaders/effects/ssao.glsl | 11 ++ res/shaders/entity.glslf | 9 +- res/shaders/entity.glslv | 6 + res/shaders/main.glslf | 48 ++++++- res/shaders/main.glslv | 15 ++ res/shaders/shadows.glslf | 11 ++ res/shaders/shadows.glslv | 17 +++ src/frontend/hud.cpp | 2 + src/frontend/screens/MenuScreen.cpp | 2 + src/graphics/core/DrawContext.cpp | 2 +- src/graphics/core/DrawContext.hpp | 4 +- src/graphics/core/Framebuffer.cpp | 56 +++++++- src/graphics/core/Framebuffer.hpp | 11 +- src/graphics/core/GBuffer.cpp | 186 +++++++++++++++++++++++++ src/graphics/core/GBuffer.hpp | 34 +++++ src/graphics/core/PostProcessing.cpp | 94 +++++++++++-- src/graphics/core/PostProcessing.hpp | 7 +- src/graphics/core/ShadowMap.cpp | 47 +++++++ src/graphics/core/ShadowMap.hpp | 18 +++ src/graphics/core/commons.hpp | 8 ++ src/graphics/render/BlocksRenderer.cpp | 38 ++--- src/graphics/render/BlocksRenderer.hpp | 2 +- src/graphics/render/ChunksRenderer.cpp | 4 +- src/graphics/render/ChunksRenderer.hpp | 2 +- src/graphics/render/Skybox.cpp | 4 +- src/graphics/render/WorldRenderer.cpp | 92 +++++++++--- src/graphics/render/WorldRenderer.hpp | 8 ++ src/graphics/render/commons.hpp | 2 + src/graphics/ui/GUI.cpp | 2 + src/window/Camera.cpp | 7 +- 36 files changed, 755 insertions(+), 71 deletions(-) create mode 100644 res/shaders/effects/ssao.glsl create mode 100644 res/shaders/shadows.glslf create mode 100644 res/shaders/shadows.glslv create mode 100644 src/graphics/core/GBuffer.cpp create mode 100644 src/graphics/core/GBuffer.hpp create mode 100644 src/graphics/core/ShadowMap.cpp create mode 100644 src/graphics/core/ShadowMap.hpp diff --git a/res/preload.json b/res/preload.json index cac23425..e10d1b68 100644 --- a/res/preload.json +++ b/res/preload.json @@ -6,10 +6,12 @@ "lines", "entity", "background", - "skybox_gen" + "skybox_gen", + "shadows" ], "post-effects": [ - "default" + "default", + "ssao" ], "textures": [ "gui/menubg", diff --git a/res/resources.json b/res/resources.json index 93922266..0311f790 100644 --- a/res/resources.json +++ b/res/resources.json @@ -4,5 +4,8 @@ "third-person-front", "third-person-back", "cinematic" + ], + "post-effect-slot": [ + "default" ] } diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua index 093d43c3..f415cf39 100644 --- a/res/scripts/hud.lua +++ b/res/scripts/hud.lua @@ -55,4 +55,8 @@ function on_hud_open() player.set_vel(pid, 0, 1, 0) end end) + + local slot = gfx.posteffects.index("core:default") + gfx.posteffects.set_effect(slot, "ssao") + --gfx.posteffects.set_intensity(slot, 1.0) end diff --git a/res/shaders/background.glslf b/res/shaders/background.glslf index f7ff07c8..6915e41c 100644 --- a/res/shaders/background.glslf +++ b/res/shaders/background.glslf @@ -1,9 +1,13 @@ in vec3 v_coord; -out vec4 f_color; +layout (location = 0) out vec4 f_color; +layout (location = 1) out vec4 f_position; +layout (location = 2) out vec4 f_normal; uniform samplerCube u_cubemap; void main(){ vec3 dir = normalize(v_coord); + f_position = vec4(100000.0); + f_normal = vec4(0.0); f_color = texture(u_cubemap, dir); } diff --git a/res/shaders/effect.glslf b/res/shaders/effect.glslf index a6325cca..3f7782c6 100644 --- a/res/shaders/effect.glslf +++ b/res/shaders/effect.glslf @@ -2,8 +2,15 @@ in vec2 v_uv; out vec4 f_color; uniform sampler2D u_screen; +uniform sampler2D u_position; +uniform sampler2D u_normal; +uniform sampler2D u_noise; +uniform sampler2D u_shadows; + uniform ivec2 u_screenSize; uniform float u_intensity; +uniform float u_timer; +uniform mat4 u_projection; #include <__effect__> diff --git a/res/shaders/effects/default.glsl b/res/shaders/effects/default.glsl index c2f9effa..1059d29b 100644 --- a/res/shaders/effects/default.glsl +++ b/res/shaders/effects/default.glsl @@ -1,3 +1,50 @@ -vec4 effect() { - return texture(u_screen, v_uv); +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); } diff --git a/res/shaders/effects/ssao.glsl b/res/shaders/effects/ssao.glsl new file mode 100644 index 00000000..f7add4f9 --- /dev/null +++ b/res/shaders/effects/ssao.glsl @@ -0,0 +1,11 @@ +uniform vec3 samples[64]; + +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 = texture(u_noise, v_uv * noiseScale).xyz; + return vec4(randomVec, 1.0); +} diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index e7a8a754..3d2a251a 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -1,8 +1,13 @@ in vec4 a_color; in vec2 a_texCoord; +in vec3 a_position; in vec3 a_dir; +in vec3 a_normal; in float a_fog; -out vec4 f_color; + +layout (location = 0) out vec4 f_color; +layout (location = 1) out vec4 f_position; +layout (location = 2) out vec4 f_normal; uniform sampler2D u_texture0; uniform samplerCube u_cubemap; @@ -20,4 +25,6 @@ void main() { discard; f_color = mix(a_color * tex_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/res/shaders/entity.glslv b/res/shaders/entity.glslv index 3d916e9a..57ed9866 100644 --- a/res/shaders/entity.glslv +++ b/res/shaders/entity.glslv @@ -7,7 +7,9 @@ layout (location = 3) in vec4 v_light; out vec4 a_color; out vec2 a_texCoord; +out vec3 a_normal; out float a_fog; +out vec3 a_position; out vec3 a_dir; uniform mat4 u_model; @@ -31,6 +33,8 @@ void main() { vec3 pos3d = modelpos.xyz - u_cameraPos; modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d); + a_normal = vec3(0.0, 1.0, 0.0);//v_normal.xyz * 2.0 - 1.0; + vec3 light = v_light.rgb; float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) / u_torchlightDistance); @@ -48,4 +52,6 @@ void main() { a_fog = min(1.0, max(pow(depth * u_fogFactor, u_fogCurve), min(pow(depth * u_weatherFogDencity, u_weatherFogCurve), u_weatherFogOpacity))); gl_Position = u_proj * u_view * modelpos; + + a_position = (u_view * modelpos).xyz; } diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index d856acc2..837ffaf1 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -1,19 +1,53 @@ +layout (location = 0) out vec4 f_color; +layout (location = 1) out vec4 f_position; +layout (location = 2) out vec4 f_normal; + in vec4 a_color; in vec2 a_texCoord; in float a_fog; +in vec3 a_position; in vec3 a_dir; -out vec4 f_color; +in vec3 a_normal; +in vec3 a_realnormal; +in vec4 a_modelpos; uniform sampler2D u_texture0; uniform samplerCube u_cubemap; +uniform sampler2DShadow u_shadows; + +// flags uniform bool u_alphaClip; uniform bool u_debugLights; +uniform bool u_debugNormals; +uniform bool u_enableShadows; + +uniform mat4 u_shadowsMatrix; + +const int BLUR_SAMPLES = 6; void main() { + float shadow = 1.0; + if (u_enableShadows) { + vec4 mpos = u_shadowsMatrix * vec4(a_modelpos.xyz, 1.0); + vec3 projCoords = mpos.xyz / mpos.w; + projCoords = projCoords * 0.5 + 0.5; + projCoords.z -= 0.0001; + + shadow = 0.0; + + 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.0005 * i/BLUR_SAMPLES)); + } + shadow /= BLUR_SAMPLES; + shadow += 0.5; + shadow = shadow * 0.7 + 0.3; + } + vec3 fogColor = texture(u_cubemap, a_dir).rgb; vec4 tex_color = texture(u_texture0, a_texCoord); - if (u_debugLights) - tex_color.rgb = vec3(1.0); float alpha = a_color.a * tex_color.a; if (u_alphaClip) { if (alpha < 0.2f) @@ -23,6 +57,14 @@ void main() { if (alpha < 0.002f) discard; } + if (u_debugLights) + tex_color.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; + } f_color = mix(a_color * tex_color, vec4(fogColor,1.0), a_fog); + f_color.rgb *= shadow; f_color.a = alpha; + f_position = vec4(a_position, 1.0); + f_normal = vec4(a_normal, 1.0); } diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index 24ec6cae..ab77d17b 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -3,12 +3,17 @@ layout (location = 0) in vec3 v_position; layout (location = 1) in vec2 v_texCoord; layout (location = 2) in vec4 v_light; +layout (location = 3) in vec4 v_normal; out vec4 a_color; out vec2 a_texCoord; +out vec3 a_normal; out float a_distance; out float a_fog; +out vec3 a_position; +out vec4 a_modelpos; out vec3 a_dir; +out vec3 a_realnormal; uniform mat4 u_model; uniform mat4 u_proj; @@ -25,12 +30,19 @@ uniform samplerCube u_cubemap; uniform vec3 u_torchlightColor; uniform float u_torchlightDistance; +uniform bool u_enableShadows; void main() { vec4 modelpos = u_model * vec4(v_position, 1.0f); vec3 pos3d = modelpos.xyz-u_cameraPos; modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d); + a_realnormal = v_normal.xyz; + mat3 normalMatrix = transpose(inverse(mat3(u_view * u_model))); + a_normal = v_normal.xyz * 2.0 - 1.0; + a_normal = normalMatrix * (false ? -a_normal : a_normal); + //a_normal = v_normal.xyz * 2.0 - 1.0; + vec3 light = v_light.rgb; float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) / u_torchlightDistance); @@ -47,4 +59,7 @@ void main() { a_fog = min(1.0, max(pow(depth * u_fogFactor, u_fogCurve), min(pow(depth * u_weatherFogDencity, u_weatherFogCurve), u_weatherFogOpacity))); gl_Position = u_proj * u_view * modelpos; + + a_position = (u_view * modelpos).xyz; + a_modelpos = modelpos; } diff --git a/res/shaders/shadows.glslf b/res/shaders/shadows.glslf new file mode 100644 index 00000000..53d6f5d2 --- /dev/null +++ b/res/shaders/shadows.glslf @@ -0,0 +1,11 @@ +in vec2 a_texCoord; + +uniform sampler2D u_texture0; + +void main() { + vec4 tex_color = texture(u_texture0, a_texCoord); + if (tex_color.a < 0.5) { + discard; + } + // depth will be written anyway +} diff --git a/res/shaders/shadows.glslv b/res/shaders/shadows.glslv new file mode 100644 index 00000000..4d4094ac --- /dev/null +++ b/res/shaders/shadows.glslv @@ -0,0 +1,17 @@ +#include + +layout (location = 0) in vec3 v_position; +layout (location = 1) in vec2 v_texCoord; +layout (location = 2) in vec4 v_light; +layout (location = 3) in vec4 v_normal; + +out vec2 a_texCoord; + +uniform mat4 u_model; +uniform mat4 u_proj; +uniform mat4 u_view; + +void main() { + a_texCoord = v_texCoord; + gl_Position = u_proj * u_view * u_model * vec4(v_position, 1.0f); +} diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index ced38093..74003b2b 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -178,6 +178,8 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player) uicamera = std::make_unique(glm::vec3(), 1); uicamera->perspective = false; uicamera->flipped = true; + uicamera->near = -1.0f; + uicamera->far = 1.0f; debugPanel = create_debug_panel( engine, frontend.getLevel(), player, allowDebugCheats diff --git a/src/frontend/screens/MenuScreen.cpp b/src/frontend/screens/MenuScreen.cpp index f7e091ba..be114ed3 100644 --- a/src/frontend/screens/MenuScreen.cpp +++ b/src/frontend/screens/MenuScreen.cpp @@ -22,6 +22,8 @@ MenuScreen::MenuScreen(Engine& engine) : Screen(engine) { uicamera = std::make_unique(glm::vec3(), engine.getWindow().getSize().y); uicamera->perspective = false; + uicamera->near = -1.0f; + uicamera->far = 1.0f; uicamera->flipped = true; } diff --git a/src/graphics/core/DrawContext.cpp b/src/graphics/core/DrawContext.cpp index 6bb0115d..fc37fd46 100644 --- a/src/graphics/core/DrawContext.cpp +++ b/src/graphics/core/DrawContext.cpp @@ -100,7 +100,7 @@ void DrawContext::setViewport(const glm::uvec2& viewport) { glViewport(0, 0, viewport.x, viewport.y); } -void DrawContext::setFramebuffer(Framebuffer* fbo) { +void DrawContext::setFramebuffer(Bindable* fbo) { if (this->fbo == fbo) return; this->fbo = fbo; diff --git a/src/graphics/core/DrawContext.hpp b/src/graphics/core/DrawContext.hpp index 7e1e18d5..ce52b99a 100644 --- a/src/graphics/core/DrawContext.hpp +++ b/src/graphics/core/DrawContext.hpp @@ -16,7 +16,7 @@ class DrawContext { glm::uvec2 viewport; Batch2D* g2d; Flushable* flushable = nullptr; - Framebuffer* fbo = nullptr; + Bindable* fbo = nullptr; bool depthMask = true; bool depthTest = false; bool cullFace = false; @@ -37,7 +37,7 @@ public: DrawContext sub(Flushable* flushable=nullptr) const; void setViewport(const glm::uvec2& viewport); - void setFramebuffer(Framebuffer* fbo); + void setFramebuffer(Bindable* fbo); void setDepthMask(bool flag); void setDepthTest(bool flag); void setCullFace(bool flag); diff --git a/src/graphics/core/Framebuffer.cpp b/src/graphics/core/Framebuffer.cpp index b0a452f4..c8ed0c42 100644 --- a/src/graphics/core/Framebuffer.cpp +++ b/src/graphics/core/Framebuffer.cpp @@ -2,6 +2,9 @@ #include #include "Texture.hpp" +#include "debug/Logger.hpp" + +static debug::Logger logger("gl-framebuffer"); Framebuffer::Framebuffer(uint fbo, uint depth, std::unique_ptr texture) : fbo(fbo), depth(depth), texture(std::move(texture)) @@ -38,18 +41,41 @@ 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); + // Setup depth attachment glGenRenderbuffers(1, &depth); glBindRenderbuffer(GL_RENDERBUFFER, depth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + logger.error() << "framebuffer is not complete!"; + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); } Framebuffer::~Framebuffer() { glDeleteFramebuffers(1, &fbo); - glDeleteRenderbuffers(1, &depth); + glDeleteTextures(1, &normals); + glDeleteTextures(1, &depth); } void Framebuffer::bind() { @@ -60,6 +86,19 @@ 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; @@ -67,11 +106,22 @@ void Framebuffer::resize(uint width, uint height) { this->width = width; this->height = height; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, depth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); glBindRenderbuffer(GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + 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 795ca2c4..35df9ffa 100644 --- a/src/graphics/core/Framebuffer.hpp +++ b/src/graphics/core/Framebuffer.hpp @@ -1,14 +1,17 @@ #pragma once #include "typedefs.hpp" +#include "commons.hpp" #include class Texture; -class Framebuffer { +class Framebuffer : public Bindable { uint fbo; uint depth; + uint positions; + uint normals; uint width; uint height; uint format; @@ -19,10 +22,12 @@ public: ~Framebuffer(); /// @brief Use framebuffer - void bind(); + void bind() override; /// @brief Stop using framebuffer - void unbind(); + void unbind() override; + + void bindBuffers(); /// @brief Update framebuffer texture size /// @param width new width diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp new file mode 100644 index 00000000..f504287e --- /dev/null +++ b/src/graphics/core/GBuffer.cpp @@ -0,0 +1,186 @@ +#include "GBuffer.hpp" + +#include + +#include "debug/Logger.hpp" + +static debug::Logger logger("gl-gbuffer"); + +void GBuffer::createColorBuffer() { + glGenTextures(1, &colorBuffer); + glBindTexture(GL_TEXTURE_2D, colorBuffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGB, + width, + height, + 0, + GL_RGB, + GL_UNSIGNED_BYTE, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0 + ); +} + +void GBuffer::createPositionsBuffer() { + glGenTextures(1, &positionsBuffer); + glBindTexture(GL_TEXTURE_2D, positionsBuffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA16F, + width, + height, + 0, + GL_RGBA, + GL_FLOAT, + nullptr + ); + 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, positionsBuffer, 0 + ); +} + +void GBuffer::createNormalsBuffer() { + glGenTextures(1, &normalsBuffer); + glBindTexture(GL_TEXTURE_2D, normalsBuffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA16F, + width, + height, + 0, + GL_RGBA, + GL_FLOAT, + nullptr + ); + 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, normalsBuffer, 0 + ); +} + +void GBuffer::createDepthBuffer() { + glGenRenderbuffers(1, &depthBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); + glFramebufferRenderbuffer( + GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer + ); +} + +GBuffer::GBuffer(uint width, uint height) : width(width), height(height) { + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + createColorBuffer(); + createPositionsBuffer(); + createNormalsBuffer(); + + GLenum attachments[3] = { + GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 + }; + glDrawBuffers(3, attachments); + + createDepthBuffer(); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + logger.error() << "framebuffer is not complete!"; + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +GBuffer::~GBuffer() { + glDeleteTextures(1, &colorBuffer); + glDeleteTextures(1, &positionsBuffer); + glDeleteTextures(1, &normalsBuffer); + glDeleteRenderbuffers(1, &depthBuffer); + glDeleteFramebuffers(1, &fbo); +} + +void GBuffer::bind() { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); +} + +void GBuffer::unbind() { + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void GBuffer::bindBuffers() { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, normalsBuffer); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, positionsBuffer); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, colorBuffer); +} + +void GBuffer::resize(uint width, uint height) { + if (this->width == width && this->height == height) { + return; + } + this->width = width; + this->height = height; + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + glBindTexture(GL_TEXTURE_2D, colorBuffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGB, + width, + height, + 0, + GL_RGB, + GL_UNSIGNED_BYTE, + nullptr + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0 + ); + + glBindTexture(GL_TEXTURE_2D, positionsBuffer); + glTexImage2D( + GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positionsBuffer, 0 + ); + + glBindTexture(GL_TEXTURE_2D, normalsBuffer); + glTexImage2D( + GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normalsBuffer, 0 + ); + + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +uint GBuffer::getWidth() const { + return width; +} + +uint GBuffer::getHeight() const { + return height; +} diff --git a/src/graphics/core/GBuffer.hpp b/src/graphics/core/GBuffer.hpp new file mode 100644 index 00000000..6269c542 --- /dev/null +++ b/src/graphics/core/GBuffer.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "typedefs.hpp" +#include "commons.hpp" + +class GBuffer : public Bindable{ +public: + GBuffer(uint width, uint height); + ~GBuffer(); + + void bind() override; + void unbind() override; + + void bindBuffers(); + + void resize(uint width, uint height); + + uint getWidth() const; + uint getHeight() const; +private: + uint width; + uint height; + + uint fbo; + uint colorBuffer; + uint positionsBuffer; + uint normalsBuffer; + uint depthBuffer; + + void createColorBuffer(); + void createPositionsBuffer(); + void createNormalsBuffer(); + void createDepthBuffer(); +}; diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index 2968cb4d..c1b6dc96 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -6,22 +6,56 @@ #include "DrawContext.hpp" #include "PostEffect.hpp" #include "assets/Assets.hpp" +#include "window/Camera.hpp" #include +#include PostProcessing::PostProcessing(size_t effectSlotsCount) : effectSlots(effectSlotsCount) { // Fullscreen quad mesh bulding - PostProcessingVertex meshData[]{ - {{-1.0f, -1.0f}}, - {{-1.0f, 1.0f}}, - {{1.0f, 1.0f}}, - {{-1.0f, -1.0f}}, - {{1.0f, 1.0f}}, - {{1.0f, -1.0f}}, + PostProcessingVertex meshData[] { + {{-1.0f, -1.0f}}, + {{-1.0f, 1.0f}}, + {{1.0f, 1.0f}}, + {{-1.0f, -1.0f}}, + {{1.0f, 1.0f}}, + {{1.0f, -1.0f}}, }; quadMesh = std::make_unique>(meshData, 6); + + std::vector ssaoNoise; + for (unsigned int i = 0; i < 16; i++) + { + glm::vec3 noise( + (rand() / static_cast(RAND_MAX)) * 2.0 - 1.0, + (rand() / static_cast(RAND_MAX)) * 2.0 - 1.0, + 0.0f); + ssaoNoise.push_back(noise); + } + glGenTextures(1, &noiseTexture); + glBindTexture(GL_TEXTURE_2D, noiseTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, ssaoNoise.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glBindTexture(GL_TEXTURE_2D, 0); + + std::uniform_real_distribution randomFloats(0.0, 1.0); + std::default_random_engine generator; + for (unsigned int i = 0; i < 64; ++i) + { + glm::vec3 sample( + randomFloats(generator) * 2.0 - 1.0, + randomFloats(generator) * 2.0 - 1.0, + randomFloats(generator) + ); + sample = glm::normalize(sample); + sample *= randomFloats(generator); + ssaoKernel.push_back(sample); + } } PostProcessing::~PostProcessing() = default; @@ -39,7 +73,7 @@ void PostProcessing::use(DrawContext& context) { } void PostProcessing::render( - const DrawContext& context, const Assets& assets, float timer + const DrawContext& context, const Assets& assets, float timer, const Camera& camera, uint depthMap ) { if (fbo == nullptr) { throw std::runtime_error("'use(...)' was never called"); @@ -51,8 +85,38 @@ void PostProcessing::render( if (totalPasses == 0) { auto& effect = assets.require("default"); - effect.use(); fbo->getTexture()->bind(); + fbo->bindBuffers(); + + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, noiseTexture); + glActiveTexture(GL_TEXTURE0); + + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, depthMap); + glActiveTexture(GL_TEXTURE0); + + const auto& viewport = context.getViewport(); + + 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()); + quadMesh->draw(); return; } @@ -64,15 +128,25 @@ void PostProcessing::render( } auto& shader = effect->use(); + 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(); } + quadMesh->draw(); if (currentPass < totalPasses) { fboSecond->unbind(); diff --git a/src/graphics/core/PostProcessing.hpp b/src/graphics/core/PostProcessing.hpp index c6b3ae14..a90d8abc 100644 --- a/src/graphics/core/PostProcessing.hpp +++ b/src/graphics/core/PostProcessing.hpp @@ -11,6 +11,7 @@ class Framebuffer; class DrawContext; class ImageData; class PostEffect; +class Camera; struct PostProcessingVertex { glm::vec2 position; @@ -30,6 +31,10 @@ class PostProcessing { /// @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(); @@ -42,7 +47,7 @@ public: /// 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); + void render(const DrawContext& context, const Assets& assets, float timer, const Camera& camera, uint depthMap); void setEffect(size_t slot, std::shared_ptr effect); diff --git a/src/graphics/core/ShadowMap.cpp b/src/graphics/core/ShadowMap.cpp new file mode 100644 index 00000000..e5032d8b --- /dev/null +++ b/src/graphics/core/ShadowMap.cpp @@ -0,0 +1,47 @@ +#include "ShadowMap.hpp" + +#include + +ShadowMap::ShadowMap(int resolution) : resolution(resolution) { + glGenTextures(1, &depthMap); + glBindTexture(GL_TEXTURE_2D, depthMap); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, + resolution, resolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + float border[4] {1.0f, 1.0f, 1.0f, 1.0f}; + glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR, border); + + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +ShadowMap::~ShadowMap() { + glDeleteFramebuffers(1, &fbo); + glDeleteTextures(1, &depthMap); +} + +void ShadowMap::bind() { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glClear(GL_DEPTH_BUFFER_BIT); +} + +void ShadowMap::unbind() { + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +uint ShadowMap::getDepthMap() const { + return depthMap; +} + +int ShadowMap::getResolution() const { + return resolution; +} diff --git a/src/graphics/core/ShadowMap.hpp b/src/graphics/core/ShadowMap.hpp new file mode 100644 index 00000000..828c51aa --- /dev/null +++ b/src/graphics/core/ShadowMap.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "typedefs.hpp" + +class ShadowMap { +public: + ShadowMap(int resolution); + ~ShadowMap(); + + void bind(); + void unbind(); + uint getDepthMap() const; + int getResolution() const; +private: + uint fbo; + uint depthMap; + int resolution; +}; diff --git a/src/graphics/core/commons.hpp b/src/graphics/core/commons.hpp index 7c26b75b..2ed03db1 100644 --- a/src/graphics/core/commons.hpp +++ b/src/graphics/core/commons.hpp @@ -69,3 +69,11 @@ public: virtual void flush() = 0; }; + +class Bindable { +public: + virtual ~Bindable() = default; + + virtual void bind() = 0; + virtual void unbind() = 0; +}; diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 3baeb0e4..2ed50ce1 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -10,7 +10,7 @@ #include "frontend/ContentGfxCache.hpp" const glm::vec3 BlocksRenderer::SUN_VECTOR(0.528265f, 0.833149f, -0.163704f); -const float DIRECTIONAL_LIGHT_FACTOR = 0.3f; +const float DIRECTIONAL_LIGHT_FACTOR = 0.2f; BlocksRenderer::BlocksRenderer( size_t capacity, @@ -39,13 +39,17 @@ BlocksRenderer::~BlocksRenderer() { /// Basic vertex add method void BlocksRenderer::vertex( - const glm::vec3& coord, float u, float v, const glm::vec4& light + const glm::vec3& coord, float u, float v, const glm::vec4& light, const glm::vec3& normal ) { vertexBuffer[vertexCount].position = coord; vertexBuffer[vertexCount].uv = {u,v}; + vertexBuffer[vertexCount].normal[0] = static_cast(normal.r * 127 + 128); + vertexBuffer[vertexCount].normal[1] = static_cast(normal.g * 127 + 128); + vertexBuffer[vertexCount].normal[2] = static_cast(normal.b * 127 + 128); + vertexBuffer[vertexCount].color[0] = static_cast(light.r * 255); vertexBuffer[vertexCount].color[1] = static_cast(light.g * 255); vertexBuffer[vertexCount].color[2] = static_cast(light.b * 255); @@ -82,10 +86,10 @@ void BlocksRenderer::face( auto Y = axisY * h; auto Z = axisZ * d; float s = 0.5f; - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, lights[0] * tint); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, lights[1] * tint); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, lights[2] * tint); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, lights[3] * tint); + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, lights[0] * tint, axisZ); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, lights[1] * tint, axisZ); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, lights[2] * tint, axisZ); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, lights[3] * tint, axisZ); index(0, 1, 3, 1, 2, 3); } @@ -103,7 +107,7 @@ void BlocksRenderer::vertexAO( axisX, axisY ); - vertex(coord, u, v, light * tint); + vertex(coord, u, v, light * tint, axisZ); } void BlocksRenderer::faceAO( @@ -134,11 +138,12 @@ void BlocksRenderer::faceAO( vertexAO(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, axisX, axisY, axisZ); vertexAO(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, axisX, axisY, axisZ); } else { + auto axisZ = glm::normalize(Z); glm::vec4 tint(1.0f); - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint); + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, axisZ); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, axisZ); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, axisZ); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, axisZ); } index(0, 1, 2, 0, 2, 3); } @@ -163,10 +168,10 @@ void BlocksRenderer::face( d = (1.0f - DIRECTIONAL_LIGHT_FACTOR) + d * DIRECTIONAL_LIGHT_FACTOR; tint *= d; } - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint); + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, Z); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, Z); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, Z); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, Z); index(0, 1, 2, 0, 2, 3); } @@ -337,7 +342,8 @@ void BlocksRenderer::blockCustomModel( coord + vcoord.x * X + vcoord.y * Y + vcoord.z * Z, vertex.uv.x, vertex.uv.y, - glm::vec4(d, d, d, d) * aoColor + glm::vec4(d, d, d, d) * aoColor, + n ); indexBuffer[indexCount++] = vertexOffset++; } diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 1edcbfcc..0bb9b31d 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -44,7 +44,7 @@ class BlocksRenderer { SortingMeshData sortingMesh; - void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light); + void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light, const glm::vec3& normal); void index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f); void vertexAO( diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index 199d818b..5cc7e81c 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -143,7 +143,7 @@ void ChunksRenderer::update() { } const Mesh* ChunksRenderer::retrieveChunk( - size_t index, const Camera& camera, Shader& shader, bool culling + size_t index, const Camera& camera, bool culling ) { auto chunk = chunks.getChunks()[index]; if (chunk == nullptr) { @@ -219,7 +219,7 @@ void ChunksRenderer::drawChunks( // TODO: minimize draw calls number for (int i = indices.size()-1; i >= 0; i--) { auto& chunk = chunks.getChunks()[indices[i].index]; - auto mesh = retrieveChunk(indices[i].index, camera, shader, culling); + auto mesh = retrieveChunk(indices[i].index, camera, culling); if (mesh) { glm::vec3 coord( diff --git a/src/graphics/render/ChunksRenderer.hpp b/src/graphics/render/ChunksRenderer.hpp index aa9833af..4efb9792 100644 --- a/src/graphics/render/ChunksRenderer.hpp +++ b/src/graphics/render/ChunksRenderer.hpp @@ -50,7 +50,7 @@ class ChunksRenderer { std::vector indices; util::ThreadPool, RendererResult> threadPool; const Mesh* retrieveChunk( - size_t index, const Camera& camera, Shader& shader, bool culling + size_t index, const Camera& camera, bool culling ); public: ChunksRenderer( diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index d78b3917..67b4efec 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -136,8 +136,8 @@ void Skybox::draw( batch3d->sprite(pos, glm::vec3(0, 0, 1), up, 1, 1, UVRegion(), tint); } - - drawStars(angle, opacity); + batch3d->flush(); + //drawStars(angle, opacity); } void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality) { diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 20640a78..c74ff31b 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -41,6 +41,8 @@ #include "graphics/core/Shader.hpp" #include "graphics/core/Texture.hpp" #include "graphics/core/Font.hpp" +#include "graphics/core/ShadowMap.hpp" +#include "graphics/core/GBuffer.hpp" #include "BlockWrapsRenderer.hpp" #include "ParticlesRenderer.hpp" #include "PrecipitationRenderer.hpp" @@ -100,6 +102,10 @@ WorldRenderer::WorldRenderer( settings.graphics.skyboxResolution.get(), assets->require("skybox_gen") ); + + shadowMap = std::make_unique(1024); + + shadowCamera = std::make_unique(); } WorldRenderer::~WorldRenderer() = default; @@ -119,6 +125,7 @@ void WorldRenderer::setupWorldShader( shader.uniform1f("u_fogFactor", fogFactor); shader.uniform1f("u_fogCurve", settings.graphics.fogCurve.get()); shader.uniform1i("u_debugLights", lightsDebug); + shader.uniform1i("u_debugNormals", false); shader.uniform1f("u_weatherFogOpacity", weather.fogOpacity()); shader.uniform1f("u_weatherFogDencity", weather.fogDencity()); shader.uniform1f("u_weatherFogCurve", weather.fogCurve()); @@ -126,6 +133,15 @@ void WorldRenderer::setupWorldShader( shader.uniform2f("u_lightDir", skybox->getLightDir()); shader.uniform3f("u_cameraPos", camera.position); shader.uniform1i("u_cubemap", 1); + shader.uniform1i("u_enableShadows", gbufferPipeline); + + if (gbufferPipeline) { + shader.uniformMatrix("u_shadowsMatrix", shadowCamera->getProjView()); + glActiveTexture(GL_TEXTURE4); + shader.uniform1i("u_shadows", 4); + glBindTexture(GL_TEXTURE_2D, shadowMap->getDepthMap()); + glActiveTexture(GL_TEXTURE0); + } auto indices = level.content.getIndices(); // Light emission when an emissive item is chosen @@ -354,10 +370,52 @@ void WorldRenderer::draw( const auto& assets = *engine.getAssets(); auto& linesShader = assets.require("lines"); + auto& shadowsShader = assets.require("shadows"); + + if (gbufferPipeline) { + float shadowMapScale = 0.05f; + 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.perspective = false; + /*shadowCamera.rotation = //glm::inverse( + glm::lookAt({}, glm::normalize(shadowCamera.position-camera.position), glm::vec3(0, 1, 0)); + //);*/ + shadowCamera->updateVectors(); + //shadowCamera->position += camera.dir * shadowMapSize * 0.5f; + shadowCamera->position -= shadowCamera->front * 100.0f; + shadowCamera->position -= shadowCamera->right * (shadowMap->getResolution() * shadowMapScale) * 0.5f; + shadowCamera->position -= shadowCamera->up * (shadowMap->getResolution() * shadowMapScale) * 0.5f; + shadowCamera->position = glm::floor(shadowCamera->position); + { + frustumCulling->update(shadowCamera->getProjView()); + auto sctx = pctx.sub(); + sctx.setDepthTest(true); + sctx.setCullFace(true); + sctx.setViewport({shadowMap->getResolution(), shadowMap->getResolution()}); + shadowMap->bind(); + setupWorldShader(shadowsShader, *shadowCamera, settings, 0.0f); + chunks->drawChunks(*shadowCamera, shadowsShader); + shadowMap->unbind(); + } + } /* World render scope with diegetic HUD included */ { DrawContext wctx = pctx.sub(); - postProcessing.use(wctx); + 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); + } display::clearDepth(); @@ -370,25 +428,25 @@ void WorldRenderer::draw( ctx.setCullFace(true); renderLevel(ctx, camera, settings, uiDelta, pause, hudVisible); // Debug lines - if (hudVisible) { - if (debug) { - guides->renderDebugLines( - ctx, camera, *lineBatch, linesShader, showChunkBorders - ); - } - if (player.currentCamera == player.fpCamera) { - renderHands(camera, delta); - } - } + // if (hudVisible) { + // if (debug) { + // guides->renderDebugLines( + // ctx, camera, *lineBatch, linesShader, showChunkBorders + // ); + // } + // if (player.currentCamera == player.fpCamera) { + // renderHands(camera, delta); + // } + // } } - { - DrawContext ctx = wctx.sub(); - texts->render(ctx, camera, settings, hudVisible, true); - } - renderBlockOverlay(wctx); + // { + // DrawContext ctx = wctx.sub(); + // texts->render(ctx, camera, settings, hudVisible, true); + // } + //renderBlockOverlay(wctx); } - postProcessing.render(pctx, assets, timer); + postProcessing.render(pctx, assets, timer, camera, shadowMap->getDepthMap()); } void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index fbfd4998..9759dd39 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -30,6 +30,8 @@ class PostProcessing; class DrawContext; class ModelBatch; class Assets; +class ShadowMap; +class GBuffer; struct EngineSettings; class WorldRenderer { @@ -44,12 +46,18 @@ class WorldRenderer { std::unique_ptr guides; std::unique_ptr chunks; std::unique_ptr skybox; + std::unique_ptr shadowMap; Weather weather {}; + + std::unique_ptr shadowCamera; float timer = 0.0f; bool debug = false; bool lightsDebug = false; + std::unique_ptr gbuffer; + bool gbufferPipeline = false; + /// @brief Render block selection lines void renderBlockSelection(); diff --git a/src/graphics/render/commons.hpp b/src/graphics/render/commons.hpp index cfc2f16c..905e34cc 100644 --- a/src/graphics/render/commons.hpp +++ b/src/graphics/render/commons.hpp @@ -14,11 +14,13 @@ struct ChunkVertex { glm::vec3 position; glm::vec2 uv; std::array color; + std::array normal; static constexpr VertexAttribute ATTRIBUTES[] = { {VertexAttribute::Type::FLOAT, false, 3}, {VertexAttribute::Type::FLOAT, false, 2}, {VertexAttribute::Type::UNSIGNED_BYTE, true, 4}, + {VertexAttribute::Type::UNSIGNED_BYTE, true, 4}, {{}, 0}}; }; diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index dc379a68..0cea8a66 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -38,6 +38,8 @@ GUI::GUI(Engine& engine) std::make_unique(glm::vec3(), engine.getWindow().getSize().y); uicamera->perspective = false; uicamera->flipped = true; + uicamera->near = -1.0f; + uicamera->far = 1.0f; menu = std::make_shared(*this); menu->setId("menu"); diff --git a/src/window/Camera.cpp b/src/window/Camera.cpp index 14939740..1854ff0e 100644 --- a/src/window/Camera.cpp +++ b/src/window/Camera.cpp @@ -31,9 +31,9 @@ glm::mat4 Camera::getProjection() const { if (perspective) { return glm::perspective(fov * zoom, ar, near, far); } else if (flipped) { - return glm::ortho(0.0f, fov * ar, fov, 0.0f); + return glm::ortho(0.0f, fov * ar, fov, 0.0f, near, far); } else { - return glm::ortho(0.0f, fov * ar, 0.0f, fov); + return glm::ortho(0.0f, fov * ar, 0.0f, fov, near, far); } } @@ -45,7 +45,8 @@ glm::mat4 Camera::getView(bool pos) const { if (perspective) { return glm::lookAt(camera_pos, camera_pos + front, up); } else { - return glm::translate(glm::mat4(1.0f), camera_pos); + return glm::lookAt(camera_pos, camera_pos + front, up); + //return glm::translate(glm::mat4(1.0f), camera_pos); } } From c1608fe8e2b3568933f822303a73c5c47846795e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 9 May 2025 15:31:04 +0300 Subject: [PATCH 02/47] split render pipelines --- res/shaders/background.glslf | 2 +- res/shaders/effect.glslf | 1 + res/shaders/effects/default.glsl | 49 +---------- res/shaders/effects/ssao.glsl | 36 +++++++- res/shaders/main.glslf | 18 ++-- src/graphics/core/Framebuffer.cpp | 42 +-------- src/graphics/core/Framebuffer.hpp | 4 - src/graphics/core/GBuffer.cpp | 12 ++- src/graphics/core/GBuffer.hpp | 9 +- src/graphics/core/PostProcessing.cpp | 117 +++++++++++++++----------- src/graphics/core/PostProcessing.hpp | 42 ++++++--- src/graphics/render/WorldRenderer.cpp | 31 +++---- src/graphics/render/WorldRenderer.hpp | 4 +- 13 files changed, 176 insertions(+), 191 deletions(-) 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(); From 657b4304b4197f7a637eed85f2bbe6573fc28e86 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 9 May 2025 21:52:29 +0300 Subject: [PATCH 03/47] improve shading & enable disabled elements --- res/scripts/hud.lua | 2 +- res/shaders/background.glslf | 2 +- res/shaders/effects/ssao.glsl | 8 +++-- res/shaders/main.glslf | 26 ++++++++++------ res/shaders/main.glslv | 6 ++-- src/graphics/core/GBuffer.cpp | 1 + src/graphics/core/PostProcessing.cpp | 25 +++++++++++----- src/graphics/core/PostProcessing.hpp | 2 ++ src/graphics/render/WorldRenderer.cpp | 43 ++++++++++++++------------- 9 files changed, 70 insertions(+), 45 deletions(-) diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua index f415cf39..79fe0e42 100644 --- a/res/scripts/hud.lua +++ b/res/scripts/hud.lua @@ -58,5 +58,5 @@ function on_hud_open() local slot = gfx.posteffects.index("core:default") gfx.posteffects.set_effect(slot, "ssao") - --gfx.posteffects.set_intensity(slot, 1.0) + gfx.posteffects.set_intensity(slot, 1.0) end diff --git a/res/shaders/background.glslf b/res/shaders/background.glslf index b6807a2f..9f588ba5 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(0.0, 0.0, 0.0, 1e9); + f_position = vec4(0.0, 0.0, 0.0, 0.0); f_normal = vec4(0.0); f_color = texture(u_cubemap, dir); } diff --git a/res/shaders/effects/ssao.glsl b/res/shaders/effects/ssao.glsl index f0f65eb6..854b9673 100644 --- a/res/shaders/effects/ssao.glsl +++ b/res/shaders/effects/ssao.glsl @@ -1,6 +1,6 @@ uniform vec3 u_ssaoSamples[64]; -int kernelSize = 32; +int kernelSize = 16; float radius = 0.25; float bias = 0.025; @@ -32,8 +32,10 @@ vec4 effect() { 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); + occlusion = min(1.0, 1.05 - (occlusion / kernelSize)); } - return vec4(color * occlusion, 1.0); + float z = -position.z * 0.02; + z = max(0.0, 1.0 - z); + return vec4(color * mix(1.0, occlusion, z), 1.0); } diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index db8b8982..55ecfe2f 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -14,6 +14,8 @@ in vec4 a_modelpos; uniform sampler2D u_texture0; uniform samplerCube u_cubemap; uniform sampler2DShadow u_shadows; +uniform vec3 u_sunDir; +uniform int u_shadowsRes; // flags uniform bool u_alphaClip; @@ -28,21 +30,27 @@ const int BLUR_SAMPLES = 6; void main() { float shadow = 1.0; if (u_enableShadows) { - vec4 mpos = u_shadowsMatrix * vec4(a_modelpos.xyz, 1.0); + vec4 mpos = u_shadowsMatrix * vec4(a_modelpos.xyz + a_realnormal * 0.08, 1.0); vec3 projCoords = mpos.xyz / mpos.w; projCoords = projCoords * 0.5 + 0.5; projCoords.z -= 0.0001; shadow = 0.0; - 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 / 4.0, - -0.002*(i%2==0?0:1)*i/BLUR_SAMPLES / 4.0, - -0.0005 * i/BLUR_SAMPLES)); + if (dot(a_realnormal, u_sunDir) < 0.0) { + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + shadow += texture(u_shadows, projCoords.xyz + vec3( + x * (1.0 / u_shadowsRes), + y * (1.0 / u_shadowsRes), 0.0 + )); + } + } + shadow /= 9; + shadow = shadow * 0.5 + 0.5; + } else { + shadow = 0.5; } - shadow /= BLUR_SAMPLES; - shadow = shadow * 0.5 + 0.5; } vec3 fogColor = texture(u_cubemap, a_dir).rgb; @@ -63,7 +71,7 @@ void main() { } f_color = a_color * texColor; f_color.rgb *= shadow; - f_color = mix(f_color, vec4(fogColor,1.0), a_fog); + 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/res/shaders/main.glslv b/res/shaders/main.glslv index ab77d17b..8df0b81e 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -37,11 +37,11 @@ void main() { vec3 pos3d = modelpos.xyz-u_cameraPos; modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d); - a_realnormal = v_normal.xyz; + a_realnormal = v_normal.xyz * 2.0 - 1.0; mat3 normalMatrix = transpose(inverse(mat3(u_view * u_model))); - a_normal = v_normal.xyz * 2.0 - 1.0; + a_normal = a_realnormal; a_normal = normalMatrix * (false ? -a_normal : a_normal); - //a_normal = v_normal.xyz * 2.0 - 1.0; + //a_normal = a_realnormal; vec3 light = v_light.rgb; float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) / diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index 901b6a57..574f7a9b 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -111,6 +111,7 @@ GBuffer::~GBuffer() { void GBuffer::bind() { glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glClear(GL_COLOR_BUFFER_BIT); } void GBuffer::unbind() { diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index e090783a..ceab2c1d 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -72,17 +72,21 @@ void PostProcessing::use(DrawContext& context, bool gbufferPipeline) { } context.setFramebuffer(gbuffer.get()); } else { - 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); - } + refreshFbos(vp.x, vp.y); context.setFramebuffer(fbo.get()); } } +void PostProcessing::refreshFbos(uint width, uint height) { + if (fbo) { + fbo->resize(width, height); + fboSecond->resize(width, height); + } else { + fbo = std::make_unique(width, height); + fboSecond = std::make_unique(width, height); + } +} + void PostProcessing::configureEffect( const DrawContext& context, Shader& shader, @@ -127,6 +131,9 @@ void PostProcessing::render( totalPasses += (effect != nullptr && effect->isActive()); } + const auto& vp = context.getViewport(); + refreshFbos(vp.x, vp.y); + if (gbuffer) { gbuffer->bindBuffers(); @@ -157,7 +164,9 @@ void PostProcessing::render( auto& shader = effect->use(); configureEffect(context, shader, timer, camera, shadowMap); - fbo->getTexture()->bind(); + if (currentPass > 1) { + fbo->getTexture()->bind(); + } if (currentPass < totalPasses) { fboSecond->bind(); diff --git a/src/graphics/core/PostProcessing.hpp b/src/graphics/core/PostProcessing.hpp index 0ab31a49..41597a4f 100644 --- a/src/graphics/core/PostProcessing.hpp +++ b/src/graphics/core/PostProcessing.hpp @@ -64,6 +64,8 @@ private: uint shadowMap ); + void refreshFbos(uint width, uint height); + /// @brief Main framebuffer (lasy field) std::unique_ptr fbo; std::unique_ptr fboSecond; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index b3826cf4..31f94803 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -137,6 +137,8 @@ void WorldRenderer::setupWorldShader( if (gbufferPipeline) { shader.uniformMatrix("u_shadowsMatrix", shadowCamera->getProjView()); + shader.uniform3f("u_sunDir", shadowCamera->front); + shader.uniform1i("u_shadowsRes", shadowMap->getResolution()); glActiveTexture(GL_TEXTURE4); shader.uniform1i("u_shadows", 4); glBindTexture(GL_TEXTURE_2D, shadowMap->getDepthMap()); @@ -373,11 +375,11 @@ void WorldRenderer::draw( auto& shadowsShader = assets.require("shadows"); if (gbufferPipeline) { - float shadowMapScale = 0.05f * 2; + float shadowMapScale = 0.05f; float shadowMapSize = shadowMap->getResolution() * shadowMapScale; *shadowCamera = Camera(camera.position, shadowMapSize); - shadowCamera->near = 0.5f; - shadowCamera->far = 600.0f; + shadowCamera->near = 0.1f; + shadowCamera->far = 800.0f; shadowCamera->perspective = false; shadowCamera->setAspectRatio(1.0f); shadowCamera->rotate(glm::radians(-64.0f), glm::radians(-35.0f), glm::radians(-35.0f)); @@ -387,10 +389,10 @@ void WorldRenderer::draw( // ); shadowCamera->updateVectors(); //shadowCamera->position += camera.dir * shadowMapSize * 0.5f; - shadowCamera->position -= shadowCamera->front * 100.0f; + shadowCamera->position -= shadowCamera->front * 200.0f; shadowCamera->position -= shadowCamera->right * (shadowMap->getResolution() * shadowMapScale) * 0.5f; shadowCamera->position -= shadowCamera->up * (shadowMap->getResolution() * shadowMapScale) * 0.5f; - shadowCamera->position = glm::floor(shadowCamera->position); + shadowCamera->position = glm::floor(shadowCamera->position * 0.25f) * 4.0f; { frustumCulling->update(shadowCamera->getProjView()); auto sctx = pctx.sub(); @@ -419,22 +421,22 @@ void WorldRenderer::draw( ctx.setCullFace(true); renderLevel(ctx, camera, settings, uiDelta, pause, hudVisible); // Debug lines - // if (hudVisible) { - // if (debug) { - // guides->renderDebugLines( - // ctx, camera, *lineBatch, linesShader, showChunkBorders - // ); - // } - // if (player.currentCamera == player.fpCamera) { - // renderHands(camera, delta); - // } - // } + if (hudVisible) { + if (debug) { + guides->renderDebugLines( + ctx, camera, *lineBatch, linesShader, showChunkBorders + ); + } + if (player.currentCamera == player.fpCamera) { + renderHands(camera, delta); + } + } } - // { - // DrawContext ctx = wctx.sub(); - // texts->render(ctx, camera, settings, hudVisible, true); - // } - //renderBlockOverlay(wctx); + { + DrawContext ctx = wctx.sub(); + texts->render(ctx, camera, settings, hudVisible, true); + } + renderBlockOverlay(wctx); } postProcessing.render( @@ -444,6 +446,7 @@ void WorldRenderer::draw( camera, gbufferPipeline ? shadowMap->getDepthMap() : 0 ); + glBindTexture(GL_TEXTURE_2D, 0); } void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) { From 36e5ff24724bb011a24aeb1b7bc1be7886380194 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 9 May 2025 22:46:07 +0300 Subject: [PATCH 04/47] update skybox & fix block overlay --- res/shaders/skybox_gen.glslf | 2 +- src/graphics/render/WorldRenderer.cpp | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/res/shaders/skybox_gen.glslf b/res/shaders/skybox_gen.glslf index a3e2cdeb..481203f3 100644 --- a/res/shaders/skybox_gen.glslf +++ b/res/shaders/skybox_gen.glslf @@ -268,7 +268,7 @@ void main() { camera_vector, // the camera vector (ray direction of this pixel) 1e12f, // max dist, essentially the scene depth vec3(0.0f), // scene color, the color of the current pixel being rendered - u_lightDir, // light direction + vec3(u_lightDir.x, pow(u_lightDir.y, 3.0), u_lightDir.z), // light direction vec3(40.0*fog), // light intensity, 40 looks nice PLANET_POS, // position of the planet PLANET_RADIUS, // radius of the planet in meters diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 31f94803..1a740fa5 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -375,30 +375,31 @@ void WorldRenderer::draw( auto& shadowsShader = assets.require("shadows"); if (gbufferPipeline) { + int resolution = shadowMap->getResolution(); float shadowMapScale = 0.05f; - float shadowMapSize = shadowMap->getResolution() * shadowMapScale; + float shadowMapSize = resolution * shadowMapScale; *shadowCamera = Camera(camera.position, shadowMapSize); shadowCamera->near = 0.1f; shadowCamera->far = 800.0f; shadowCamera->perspective = false; shadowCamera->setAspectRatio(1.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(camera.position-shadowCamera->position), glm::vec3(0, 1, 0)) - // ); + shadowCamera->rotate( + glm::radians(90.0f - worldInfo.daytime * 360.0f), + glm::radians(-40.0f), + glm::radians(-0.0f) + ); shadowCamera->updateVectors(); //shadowCamera->position += camera.dir * shadowMapSize * 0.5f; shadowCamera->position -= shadowCamera->front * 200.0f; - shadowCamera->position -= shadowCamera->right * (shadowMap->getResolution() * shadowMapScale) * 0.5f; - shadowCamera->position -= shadowCamera->up * (shadowMap->getResolution() * shadowMapScale) * 0.5f; + shadowCamera->position -= shadowCamera->right * (resolution * shadowMapScale) * 0.5f; + shadowCamera->position -= shadowCamera->up * (resolution * shadowMapScale) * 0.5f; shadowCamera->position = glm::floor(shadowCamera->position * 0.25f) * 4.0f; { frustumCulling->update(shadowCamera->getProjView()); auto sctx = pctx.sub(); sctx.setDepthTest(true); sctx.setCullFace(true); - sctx.setViewport({shadowMap->getResolution(), shadowMap->getResolution()}); + sctx.setViewport({resolution, resolution}); shadowMap->bind(); setupWorldShader(shadowsShader, *shadowCamera, settings, 0.0f); chunks->drawChunks(*shadowCamera, shadowsShader); @@ -436,7 +437,6 @@ void WorldRenderer::draw( DrawContext ctx = wctx.sub(); texts->render(ctx, camera, settings, hudVisible, true); } - renderBlockOverlay(wctx); } postProcessing.render( @@ -446,7 +446,10 @@ void WorldRenderer::draw( camera, gbufferPipeline ? shadowMap->getDepthMap() : 0 ); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); + + renderBlockOverlay(pctx); } void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) { From 30a0b816806f88384ae66603deb8aca87fac56c3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 9 May 2025 23:51:34 +0300 Subject: [PATCH 05/47] refactor shaders --- res/shaders/background.glslf | 4 +-- res/shaders/entity.glslf | 23 ++++++++++--- res/shaders/entity.glslv | 46 ++++++++++++------------- res/shaders/lib/lighting.glsl | 27 +++++++++++++++ res/shaders/lib/shadows.glsl | 32 ++++++++++++++++++ res/shaders/main.glslf | 32 +++--------------- res/shaders/main.glslv | 48 +++++++++++---------------- src/graphics/render/Skybox.cpp | 2 +- src/graphics/render/WorldRenderer.cpp | 2 +- 9 files changed, 128 insertions(+), 88 deletions(-) create mode 100644 res/shaders/lib/lighting.glsl create mode 100644 res/shaders/lib/shadows.glsl diff --git a/res/shaders/background.glslf b/res/shaders/background.glslf index 9f588ba5..c442bb06 100644 --- a/res/shaders/background.glslf +++ b/res/shaders/background.glslf @@ -3,11 +3,11 @@ layout (location = 0) out vec4 f_color; layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; -uniform samplerCube u_cubemap; +uniform samplerCube u_skybox; void main(){ vec3 dir = normalize(v_coord); f_position = vec4(0.0, 0.0, 0.0, 0.0); f_normal = vec4(0.0); - f_color = texture(u_cubemap, dir); + f_color = texture(u_skybox, dir); } diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index 3d2a251a..b9369874 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -3,6 +3,8 @@ in vec2 a_texCoord; in vec3 a_position; in vec3 a_dir; in vec3 a_normal; +in vec3 a_realnormal; +in vec4 a_modelpos; in float a_fog; layout (location = 0) out vec4 f_color; @@ -10,20 +12,33 @@ layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; uniform sampler2D u_texture0; -uniform samplerCube u_cubemap; +uniform samplerCube u_skybox; uniform vec3 u_fogColor; uniform float u_fogFactor; uniform float u_fogCurve; uniform bool u_alphaClip; +uniform sampler2DShadow u_shadows; +uniform vec3 u_sunDir; +uniform int u_shadowsRes; + +uniform bool u_enableShadows; +uniform mat4 u_shadowsMatrix; + +#include + void main() { - vec3 fogColor = texture(u_cubemap, a_dir).rgb; + float shadow = calc_shadow(); + vec3 fogColor = texture(u_skybox, a_dir).rgb; vec4 tex_color = texture(u_texture0, a_texCoord); float alpha = a_color.a * tex_color.a; // anyway it's any alpha-test alternative required - if (alpha < (u_alphaClip ? 0.5f : 0.15f)) + if (alpha < (u_alphaClip ? 0.5f : 0.15f)) { discard; - f_color = mix(a_color * tex_color, vec4(fogColor,1.0), a_fog); + } + f_color = a_color * tex_color; + 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/res/shaders/entity.glslv b/res/shaders/entity.glslv index 57ed9866..607c4721 100644 --- a/res/shaders/entity.glslv +++ b/res/shaders/entity.glslv @@ -5,12 +5,15 @@ layout (location = 1) in vec2 v_texCoord; layout (location = 2) in vec3 v_color; layout (location = 3) in vec4 v_light; -out vec4 a_color; -out vec2 a_texCoord; -out vec3 a_normal; +out float a_distance; out float a_fog; -out vec3 a_position; +out vec2 a_texCoord; out vec3 a_dir; +out vec3 a_normal; +out vec3 a_position; +out vec3 a_realnormal; +out vec4 a_color; +out vec4 a_modelpos; uniform mat4 u_model; uniform mat4 u_proj; @@ -18,40 +21,37 @@ uniform mat4 u_view; uniform vec3 u_cameraPos; uniform float u_gamma; uniform float u_opacity; -uniform float u_fogFactor; -uniform float u_fogCurve; -uniform float u_weatherFogOpacity; -uniform float u_weatherFogDencity; -uniform float u_weatherFogCurve; -uniform samplerCube u_cubemap; +uniform float u_timer; +uniform samplerCube u_skybox; uniform vec3 u_torchlightColor; uniform float u_torchlightDistance; +#include + void main() { - vec4 modelpos = u_model * vec4(v_position, 1.0); - vec3 pos3d = modelpos.xyz - u_cameraPos; - modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d); + a_modelpos = u_model * vec4(v_position, 1.0); + vec3 pos3d = a_modelpos.xyz - u_cameraPos; + a_modelpos.xyz = apply_planet_curvature(a_modelpos.xyz, pos3d); a_normal = vec3(0.0, 1.0, 0.0);//v_normal.xyz * 2.0 - 1.0; + a_realnormal = a_normal; vec3 light = v_light.rgb; - float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) / - u_torchlightDistance); + float torchlight = calc_torch_light(a_modelpos.xyz); light += torchlight * u_torchlightColor; a_color = vec4(pow(light, vec3(u_gamma)),1.0f); a_texCoord = v_texCoord; - a_dir = modelpos.xyz - u_cameraPos; - vec3 skyLightColor = pick_sky_color(u_cubemap); + a_dir = a_modelpos.xyz - u_cameraPos; + vec3 skyLightColor = pick_sky_color(u_skybox); a_color.rgb = max(a_color.rgb, skyLightColor.rgb*v_light.a) * v_color; a_color.a = u_opacity; - float dist = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0)); - float depth = (dist / 256.0); - a_fog = min(1.0, max(pow(depth * u_fogFactor, u_fogCurve), - min(pow(depth * u_weatherFogDencity, u_weatherFogCurve), u_weatherFogOpacity))); - gl_Position = u_proj * u_view * modelpos; + a_distance = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0)); + a_fog = calc_fog(a_distance / 256.0); - a_position = (u_view * modelpos).xyz; + vec4 viewmodelpos = u_view * a_modelpos; + a_position = viewmodelpos.xyz; + gl_Position = u_proj * viewmodelpos; } diff --git a/res/shaders/lib/lighting.glsl b/res/shaders/lib/lighting.glsl new file mode 100644 index 00000000..d2c4f896 --- /dev/null +++ b/res/shaders/lib/lighting.glsl @@ -0,0 +1,27 @@ +#ifndef LIGHTING_GLSL_ +#define LIGHTING_GLSL_ + +uniform float u_fogFactor; +uniform float u_fogCurve; +uniform float u_weatherFogOpacity; +uniform float u_weatherFogDencity; +uniform float u_weatherFogCurve; + +float calc_torch_light(vec3 modelpos) { + return max(0.0, 1.0 - distance(u_cameraPos, modelpos.xyz) / u_torchlightDistance); +} + +vec3 calc_screen_normal(vec3 normal) { + return transpose(inverse(mat3(u_view * u_model))) * normal; +} + +float calc_fog(float depth) { + return min( + 1.0, + max(pow(depth * u_fogFactor, u_fogCurve), + min(pow(depth * u_weatherFogDencity, u_weatherFogCurve), + u_weatherFogOpacity)) + ); +} + +#endif // LIGHTING_GLSL_ diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl new file mode 100644 index 00000000..db94e9dc --- /dev/null +++ b/res/shaders/lib/shadows.glsl @@ -0,0 +1,32 @@ +#ifndef SHADOWS_GLSL_ +#define SHADOWS_GLSL_ + +float calc_shadow() { + float shadow = 1.0; + if (u_enableShadows) { + vec4 mpos = u_shadowsMatrix * vec4(a_modelpos.xyz + a_realnormal * 0.08, 1.0); + vec3 projCoords = mpos.xyz / mpos.w; + projCoords = projCoords * 0.5 + 0.5; + projCoords.z -= 0.0001; + + shadow = 0.0; + + if (dot(a_realnormal, u_sunDir) < 0.0) { + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + shadow += texture(u_shadows, projCoords.xyz + vec3( + x * (1.0 / u_shadowsRes), + y * (1.0 / u_shadowsRes), 0.0 + )); + } + } + shadow /= 9; + shadow = shadow * 0.5 + 0.5; + } else { + shadow = 0.5; + } + } + return shadow; +} + +#endif // SHADOWS_GLSL_ diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index 55ecfe2f..89e83bbf 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -12,7 +12,7 @@ in vec3 a_realnormal; in vec4 a_modelpos; uniform sampler2D u_texture0; -uniform samplerCube u_cubemap; +uniform samplerCube u_skybox; uniform sampler2DShadow u_shadows; uniform vec3 u_sunDir; uniform int u_shadowsRes; @@ -25,35 +25,11 @@ uniform bool u_enableShadows; uniform mat4 u_shadowsMatrix; -const int BLUR_SAMPLES = 6; +#include void main() { - float shadow = 1.0; - if (u_enableShadows) { - vec4 mpos = u_shadowsMatrix * vec4(a_modelpos.xyz + a_realnormal * 0.08, 1.0); - vec3 projCoords = mpos.xyz / mpos.w; - projCoords = projCoords * 0.5 + 0.5; - projCoords.z -= 0.0001; - - shadow = 0.0; - - if (dot(a_realnormal, u_sunDir) < 0.0) { - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { - shadow += texture(u_shadows, projCoords.xyz + vec3( - x * (1.0 / u_shadowsRes), - y * (1.0 / u_shadowsRes), 0.0 - )); - } - } - shadow /= 9; - shadow = shadow * 0.5 + 0.5; - } else { - shadow = 0.5; - } - } - - vec3 fogColor = texture(u_cubemap, a_dir).rgb; + float shadow = calc_shadow(); + vec3 fogColor = texture(u_skybox, a_dir).rgb; vec4 texColor = texture(u_texture0, a_texCoord); float alpha = a_color.a * texColor.a; if (u_alphaClip) { diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index 8df0b81e..032a6d8e 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -5,61 +5,51 @@ layout (location = 1) in vec2 v_texCoord; layout (location = 2) in vec4 v_light; layout (location = 3) in vec4 v_normal; -out vec4 a_color; -out vec2 a_texCoord; -out vec3 a_normal; out float a_distance; out float a_fog; -out vec3 a_position; -out vec4 a_modelpos; +out vec2 a_texCoord; out vec3 a_dir; +out vec3 a_normal; +out vec3 a_position; out vec3 a_realnormal; +out vec4 a_color; +out vec4 a_modelpos; uniform mat4 u_model; uniform mat4 u_proj; uniform mat4 u_view; uniform vec3 u_cameraPos; uniform float u_gamma; -uniform float u_fogFactor; -uniform float u_fogCurve; -uniform float u_weatherFogOpacity; -uniform float u_weatherFogDencity; -uniform float u_weatherFogCurve; uniform float u_timer; -uniform samplerCube u_cubemap; +uniform samplerCube u_skybox; uniform vec3 u_torchlightColor; uniform float u_torchlightDistance; -uniform bool u_enableShadows; + +#include void main() { - vec4 modelpos = u_model * vec4(v_position, 1.0f); - vec3 pos3d = modelpos.xyz-u_cameraPos; - modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d); + a_modelpos = u_model * vec4(v_position, 1.0f); + vec3 pos3d = a_modelpos.xyz - u_cameraPos; + a_modelpos.xyz = apply_planet_curvature(a_modelpos.xyz, pos3d); a_realnormal = v_normal.xyz * 2.0 - 1.0; - mat3 normalMatrix = transpose(inverse(mat3(u_view * u_model))); - a_normal = a_realnormal; - a_normal = normalMatrix * (false ? -a_normal : a_normal); - //a_normal = a_realnormal; + a_normal = calc_screen_normal(a_realnormal); vec3 light = v_light.rgb; - float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) / - u_torchlightDistance); + float torchlight = calc_torch_light(a_modelpos.xyz); light += torchlight * u_torchlightColor; a_color = vec4(pow(light, vec3(u_gamma)),1.0f); a_texCoord = v_texCoord; - a_dir = modelpos.xyz - u_cameraPos; - vec3 skyLightColor = pick_sky_color(u_cubemap); + a_dir = a_modelpos.xyz - u_cameraPos; + vec3 skyLightColor = pick_sky_color(u_skybox); a_color.rgb = max(a_color.rgb, skyLightColor.rgb*v_light.a); a_distance = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0)); - float depth = (a_distance / 256.0); - a_fog = min(1.0, max(pow(depth * u_fogFactor, u_fogCurve), - min(pow(depth * u_weatherFogDencity, u_weatherFogCurve), u_weatherFogOpacity))); - gl_Position = u_proj * u_view * modelpos; + a_fog = calc_fog(a_distance / 256.0); - a_position = (u_view * modelpos).xyz; - a_modelpos = modelpos; + vec4 viewmodelpos = u_view * a_modelpos; + a_position = viewmodelpos.xyz; + gl_Position = u_proj * viewmodelpos; } diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index 67b4efec..bf6eedc1 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -71,7 +71,7 @@ void Skybox::drawBackground( backShader->uniformMatrix("u_view", camera.getView(false)); backShader->uniform1f("u_zoom", camera.zoom*camera.getFov()/(M_PI*0.5f)); backShader->uniform1f("u_ar", float(width)/float(height)); - backShader->uniform1i("u_cubemap", 1); + backShader->uniform1i("u_skybox", 1); bind(); mesh->draw(); unbind(); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 1a740fa5..b886c300 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -132,7 +132,7 @@ void WorldRenderer::setupWorldShader( shader.uniform1f("u_dayTime", level.getWorld()->getInfo().daytime); shader.uniform2f("u_lightDir", skybox->getLightDir()); shader.uniform3f("u_cameraPos", camera.position); - shader.uniform1i("u_cubemap", 1); + shader.uniform1i("u_skybox", 1); shader.uniform1i("u_enableShadows", gbufferPipeline); if (gbufferPipeline) { From e158b384fa7374ef0ca58e42d8aba67a430f834f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 10 May 2025 14:12:52 +0300 Subject: [PATCH 06/47] feat: shadows in fast pipeline & improve lights mix --- res/scripts/hud.lua | 2 +- res/shaders/lib/shadows.glsl | 17 ++++++++-------- res/shaders/main.glslf | 9 +++++---- res/shaders/main.glslv | 10 +++++---- src/graphics/core/PostProcessing.cpp | 1 + src/graphics/render/ChunksRenderer.cpp | 28 ++++++++++++++++++++++++++ src/graphics/render/ChunksRenderer.hpp | 3 +++ src/graphics/render/WorldRenderer.cpp | 14 ++++++------- src/graphics/render/WorldRenderer.hpp | 3 ++- 9 files changed, 62 insertions(+), 25 deletions(-) diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua index 79fe0e42..f415cf39 100644 --- a/res/scripts/hud.lua +++ b/res/scripts/hud.lua @@ -58,5 +58,5 @@ function on_hud_open() local slot = gfx.posteffects.index("core:default") gfx.posteffects.set_effect(slot, "ssao") - gfx.posteffects.set_intensity(slot, 1.0) + --gfx.posteffects.set_intensity(slot, 1.0) end diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index db94e9dc..9e96d3ea 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -12,15 +12,16 @@ float calc_shadow() { shadow = 0.0; if (dot(a_realnormal, u_sunDir) < 0.0) { - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { - shadow += texture(u_shadows, projCoords.xyz + vec3( - x * (1.0 / u_shadowsRes), - y * (1.0 / u_shadowsRes), 0.0 - )); - } + const vec3 offsets[4] = vec3[4]( + vec3(0.5, 0.5, 0.0), + vec3(-0.5, 0.5, 0.0), + vec3(0.5, -0.5, 0.0), + vec3(-0.5, -0.5, 0.0) + ); + for (int i = 0; i < 4; i++) { + shadow += texture(u_shadows, projCoords.xyz + offsets[i] / u_shadowsRes); } - shadow /= 9; + shadow /= 4; shadow = shadow * 0.5 + 0.5; } else { shadow = 0.5; diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index 89e83bbf..cbb29de6 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -2,7 +2,8 @@ layout (location = 0) out vec4 f_color; layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; -in vec4 a_color; +in vec4 a_torchLight; +in vec3 a_skyLight; in vec2 a_texCoord; in float a_fog; in vec3 a_position; @@ -31,7 +32,7 @@ void main() { float shadow = calc_shadow(); vec3 fogColor = texture(u_skybox, a_dir).rgb; vec4 texColor = texture(u_texture0, a_texCoord); - float alpha = a_color.a * texColor.a; + float alpha = texColor.a; if (u_alphaClip) { if (alpha < 0.2f) discard; @@ -45,8 +46,8 @@ void main() { else if (u_debugNormals) { texColor.rgb *= a_normal * 0.5 + 0.5; } - f_color = a_color * texColor; - f_color.rgb *= shadow; + f_color = texColor; + f_color.rgb *= min(vec3(1.0), a_torchLight.rgb + a_skyLight * shadow); f_color = mix(f_color, vec4(fogColor, 1.0), a_fog); f_color.a = alpha; f_position = vec4(a_position, 1.0); diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index 032a6d8e..d7e5b4fc 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -12,7 +12,8 @@ out vec3 a_dir; out vec3 a_normal; out vec3 a_position; out vec3 a_realnormal; -out vec4 a_color; +out vec4 a_torchLight; +out vec3 a_skyLight; out vec4 a_modelpos; uniform mat4 u_model; @@ -38,13 +39,14 @@ void main() { vec3 light = v_light.rgb; float torchlight = calc_torch_light(a_modelpos.xyz); - light += torchlight * u_torchlightColor; - a_color = vec4(pow(light, vec3(u_gamma)),1.0f); + a_torchLight = vec4(pow(light + torchlight * u_torchlightColor, vec3(u_gamma)), 1.0f); + a_texCoord = v_texCoord; a_dir = a_modelpos.xyz - u_cameraPos; vec3 skyLightColor = pick_sky_color(u_skybox); - a_color.rgb = max(a_color.rgb, skyLightColor.rgb*v_light.a); + a_skyLight = skyLightColor.rgb*v_light.a; + //a_color.rgb = max(a_color.rgb, skyLightColor.rgb*v_light.a); a_distance = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0)); a_fog = calc_fog(a_distance / 256.0); diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index ceab2c1d..498782d4 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -72,6 +72,7 @@ void PostProcessing::use(DrawContext& context, bool gbufferPipeline) { } context.setFramebuffer(gbuffer.get()); } else { + gbuffer.reset(); refreshFbos(vp.x, vp.y); context.setFramebuffer(fbo.get()); } diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index 5cc7e81c..8c88931b 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -182,6 +182,34 @@ const Mesh* ChunksRenderer::retrieveChunk( return mesh; } +void ChunksRenderer::drawChunksShadowsPass( + const Camera& camera, Shader& shader +) { + const auto& atlas = assets.require("blocks"); + + atlas.getTexture()->bind(); + + for (int i = indices.size()-1; i >= 0; i--) { + auto& chunk = chunks.getChunks()[indices[i].index]; + if (chunk == nullptr) { + continue; + } + const auto& found = meshes.find({chunk->x, chunk->z}); + if (found == meshes.end()) { + continue; + } + auto mesh = found->second.mesh.get(); + if (mesh) { + glm::vec3 coord( + chunk->x * CHUNK_W + 0.5f, 0.5f, chunk->z * CHUNK_D + 0.5f + ); + glm::mat4 model = glm::translate(glm::mat4(1.0f), coord); + shader.uniformMatrix("u_model", model); + mesh->draw(); + } + } +} + void ChunksRenderer::drawChunks( const Camera& camera, Shader& shader ) { diff --git a/src/graphics/render/ChunksRenderer.hpp b/src/graphics/render/ChunksRenderer.hpp index 4efb9792..fcc8b07d 100644 --- a/src/graphics/render/ChunksRenderer.hpp +++ b/src/graphics/render/ChunksRenderer.hpp @@ -72,6 +72,9 @@ public: const Mesh* getOrRender( const std::shared_ptr& chunk, bool important ); + + void drawChunksShadowsPass(const Camera& camera, Shader& shader); + void drawChunks(const Camera& camera, Shader& shader); void drawSortedMeshes(const Camera& camera, Shader& shader); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index b886c300..71f14a48 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 * 4); + shadowMap = std::make_unique(1024 * 8); shadowCamera = std::make_unique(); } @@ -133,9 +133,9 @@ void WorldRenderer::setupWorldShader( shader.uniform2f("u_lightDir", skybox->getLightDir()); shader.uniform3f("u_cameraPos", camera.position); shader.uniform1i("u_skybox", 1); - shader.uniform1i("u_enableShadows", gbufferPipeline); + shader.uniform1i("u_enableShadows", shadows); - if (gbufferPipeline) { + if (shadows) { shader.uniformMatrix("u_shadowsMatrix", shadowCamera->getProjView()); shader.uniform3f("u_sunDir", shadowCamera->front); shader.uniform1i("u_shadowsRes", shadowMap->getResolution()); @@ -374,7 +374,7 @@ void WorldRenderer::draw( auto& linesShader = assets.require("lines"); auto& shadowsShader = assets.require("shadows"); - if (gbufferPipeline) { + if (shadows) { int resolution = shadowMap->getResolution(); float shadowMapScale = 0.05f; float shadowMapSize = resolution * shadowMapScale; @@ -384,7 +384,7 @@ void WorldRenderer::draw( shadowCamera->perspective = false; shadowCamera->setAspectRatio(1.0f); shadowCamera->rotate( - glm::radians(90.0f - worldInfo.daytime * 360.0f), + glm::radians(fmod(90.0f - worldInfo.daytime * 360.0f, 180.0f)), glm::radians(-40.0f), glm::radians(-0.0f) ); @@ -402,7 +402,7 @@ void WorldRenderer::draw( sctx.setViewport({resolution, resolution}); shadowMap->bind(); setupWorldShader(shadowsShader, *shadowCamera, settings, 0.0f); - chunks->drawChunks(*shadowCamera, shadowsShader); + chunks->drawChunksShadowsPass(*shadowCamera, shadowsShader); shadowMap->unbind(); } } @@ -444,7 +444,7 @@ void WorldRenderer::draw( assets, timer, camera, - gbufferPipeline ? shadowMap->getDepthMap() : 0 + shadows ? shadowMap->getDepthMap() : 0 ); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 2832fca2..8e9d4d01 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -54,7 +54,8 @@ class WorldRenderer { float timer = 0.0f; bool debug = false; bool lightsDebug = false; - bool gbufferPipeline = true; + bool gbufferPipeline = false; + bool shadows = true; /// @brief Render block selection lines void renderBlockSelection(); From 8bb03a004fef3f9459fc332d8c0c062ffc561f23 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 10 May 2025 16:13:06 +0300 Subject: [PATCH 07/47] refactor & fix random deleting texture --- src/graphics/core/Batch2D.cpp | 10 +-- src/graphics/core/Batch3D.cpp | 2 - src/graphics/core/Framebuffer.cpp | 5 +- src/graphics/core/PostProcessing.cpp | 11 ++-- src/graphics/render/BlocksRenderer.cpp | 2 +- src/graphics/render/WorldRenderer.cpp | 91 +++++++++++++------------- src/graphics/render/WorldRenderer.hpp | 8 ++- 7 files changed, 65 insertions(+), 64 deletions(-) diff --git a/src/graphics/core/Batch2D.cpp b/src/graphics/core/Batch2D.cpp index 38224a3f..0db15c4b 100644 --- a/src/graphics/core/Batch2D.cpp +++ b/src/graphics/core/Batch2D.cpp @@ -60,17 +60,17 @@ void Batch2D::vertex( index++; } -void Batch2D::texture(const Texture* new_texture){ - if (currentTexture == new_texture) { +void Batch2D::texture(const Texture* newTexture){ + if (currentTexture == newTexture) { return; } flush(); - currentTexture = new_texture; - if (new_texture == nullptr) { + currentTexture = newTexture; + if (newTexture == nullptr) { blank->bind(); region = blank->getUVRegion(); } else { - new_texture->bind(); + newTexture->bind(); region = currentTexture->getUVRegion(); } } diff --git a/src/graphics/core/Batch3D.cpp b/src/graphics/core/Batch3D.cpp index 43d161f6..6230fc40 100644 --- a/src/graphics/core/Batch3D.cpp +++ b/src/graphics/core/Batch3D.cpp @@ -8,8 +8,6 @@ Batch3D::Batch3D(size_t capacity) : capacity(capacity) { - - buffer = std::make_unique(capacity); mesh = std::make_unique>(buffer.get(), 0); index = 0; diff --git a/src/graphics/core/Framebuffer.cpp b/src/graphics/core/Framebuffer.cpp index 7f86dd20..e009f747 100644 --- a/src/graphics/core/Framebuffer.cpp +++ b/src/graphics/core/Framebuffer.cpp @@ -42,9 +42,6 @@ Framebuffer::Framebuffer(uint width, uint height, bool alpha) // Setup color attachment (texture) texture = create_texture(width, height, format); - unsigned int attachments[1] = { GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, attachments); - // Setup depth attachment glGenRenderbuffers(1, &depth); glBindRenderbuffer(GL_RENDERBUFFER, depth); @@ -60,7 +57,7 @@ Framebuffer::Framebuffer(uint width, uint height, bool alpha) Framebuffer::~Framebuffer() { glDeleteFramebuffers(1, &fbo); - glDeleteTextures(1, &depth); + glDeleteRenderbuffers(1, &depth); } void Framebuffer::bind() { diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index 498782d4..acebd519 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -135,20 +135,21 @@ void PostProcessing::render( const auto& vp = context.getViewport(); refreshFbos(vp.x, vp.y); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, shadowMap); + if (gbuffer) { gbuffer->bindBuffers(); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, noiseTexture); - - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, shadowMap); + + glActiveTexture(GL_TEXTURE0); } else { + glActiveTexture(GL_TEXTURE0); fbo->getTexture()->bind(); } - glActiveTexture(GL_TEXTURE0); - if (totalPasses == 0) { auto& effect = assets.require("default"); auto& shader = effect.use(); diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 2ed50ce1..1bc499fb 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -10,7 +10,7 @@ #include "frontend/ContentGfxCache.hpp" const glm::vec3 BlocksRenderer::SUN_VECTOR(0.528265f, 0.833149f, -0.163704f); -const float DIRECTIONAL_LIGHT_FACTOR = 0.2f; +const float DIRECTIONAL_LIGHT_FACTOR = 0.3f; BlocksRenderer::BlocksRenderer( size_t capacity, diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 71f14a48..c30093bd 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -26,7 +26,6 @@ #include "voxels/Block.hpp" #include "voxels/Chunk.hpp" #include "voxels/Chunks.hpp" -#include "window/Camera.hpp" #include "window/Window.hpp" #include "world/Level.hpp" #include "world/LevelEvents.hpp" @@ -102,10 +101,6 @@ WorldRenderer::WorldRenderer( settings.graphics.skyboxResolution.get(), assets->require("skybox_gen") ); - - shadowMap = std::make_unique(1024 * 8); - - shadowCamera = std::make_unique(); } WorldRenderer::~WorldRenderer() = default; @@ -136,8 +131,11 @@ void WorldRenderer::setupWorldShader( shader.uniform1i("u_enableShadows", shadows); if (shadows) { - shader.uniformMatrix("u_shadowsMatrix", shadowCamera->getProjView()); - shader.uniform3f("u_sunDir", shadowCamera->front); + if (shadowMap == nullptr) { + shadowMap = std::make_unique(1024 * 8); + } + shader.uniformMatrix("u_shadowsMatrix", shadowCamera.getProjView()); + shader.uniform3f("u_sunDir", shadowCamera.front); shader.uniform1i("u_shadowsRes", shadowMap->getResolution()); glActiveTexture(GL_TEXTURE4); shader.uniform1i("u_shadows", 4); @@ -342,6 +340,44 @@ void WorldRenderer::renderHands( skybox->unbind(); } +void WorldRenderer::generateShadowsMap(const Camera& camera, const DrawContext& pctx) { + auto& shadowsShader = assets.require("shadows"); + + auto world = level.getWorld(); + const auto& worldInfo = world->getInfo(); + + const auto& settings = engine.getSettings(); + int resolution = shadowMap->getResolution(); + float shadowMapScale = 0.05f; + float shadowMapSize = resolution * shadowMapScale; + shadowCamera = Camera(camera.position, shadowMapSize); + shadowCamera.near = 0.1f; + shadowCamera.far = 800.0f; + shadowCamera.perspective = false; + shadowCamera.setAspectRatio(1.0f); + shadowCamera.rotate( + glm::radians(fmod(90.0f - worldInfo.daytime * 360.0f, 180.0f)), + glm::radians(-40.0f), + glm::radians(-0.0f) + ); + shadowCamera.updateVectors(); + shadowCamera.position -= shadowCamera.front * 200.0f; + shadowCamera.position -= shadowCamera.right * (resolution * shadowMapScale) * 0.5f; + shadowCamera.position -= shadowCamera.up * (resolution * shadowMapScale) * 0.5f; + shadowCamera.position = glm::floor(shadowCamera.position * 0.25f) * 4.0f; + { + frustumCulling->update(shadowCamera.getProjView()); + auto sctx = pctx.sub(); + sctx.setDepthTest(true); + sctx.setCullFace(true); + sctx.setViewport({resolution, resolution}); + shadowMap->bind(); + setupWorldShader(shadowsShader, shadowCamera, settings, 0.0f); + chunks->drawChunksShadowsPass(shadowCamera, shadowsShader); + shadowMap->unbind(); + } +} + void WorldRenderer::draw( const DrawContext& pctx, Camera& camera, @@ -370,43 +406,11 @@ void WorldRenderer::draw( skybox->refresh(pctx, worldInfo.daytime, mie, 4); - const auto& assets = *engine.getAssets(); - auto& linesShader = assets.require("lines"); - auto& shadowsShader = assets.require("shadows"); - if (shadows) { - int resolution = shadowMap->getResolution(); - float shadowMapScale = 0.05f; - float shadowMapSize = resolution * shadowMapScale; - *shadowCamera = Camera(camera.position, shadowMapSize); - shadowCamera->near = 0.1f; - shadowCamera->far = 800.0f; - shadowCamera->perspective = false; - shadowCamera->setAspectRatio(1.0f); - shadowCamera->rotate( - glm::radians(fmod(90.0f - worldInfo.daytime * 360.0f, 180.0f)), - glm::radians(-40.0f), - glm::radians(-0.0f) - ); - shadowCamera->updateVectors(); - //shadowCamera->position += camera.dir * shadowMapSize * 0.5f; - shadowCamera->position -= shadowCamera->front * 200.0f; - shadowCamera->position -= shadowCamera->right * (resolution * shadowMapScale) * 0.5f; - shadowCamera->position -= shadowCamera->up * (resolution * shadowMapScale) * 0.5f; - shadowCamera->position = glm::floor(shadowCamera->position * 0.25f) * 4.0f; - { - frustumCulling->update(shadowCamera->getProjView()); - auto sctx = pctx.sub(); - sctx.setDepthTest(true); - sctx.setCullFace(true); - sctx.setViewport({resolution, resolution}); - shadowMap->bind(); - setupWorldShader(shadowsShader, *shadowCamera, settings, 0.0f); - chunks->drawChunksShadowsPass(*shadowCamera, shadowsShader); - shadowMap->unbind(); - } + generateShadowsMap(camera, pctx); } + auto& linesShader = assets.require("lines"); /* World render scope with diegetic HUD included */ { DrawContext wctx = pctx.sub(); postProcessing.use(wctx, gbufferPipeline); @@ -446,10 +450,9 @@ void WorldRenderer::draw( camera, shadows ? shadowMap->getDepthMap() : 0 ); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, 0); - renderBlockOverlay(pctx); + + glActiveTexture(GL_TEXTURE0); } void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 8e9d4d01..7db4e44a 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -9,6 +9,7 @@ #include "presets/WeatherPreset.hpp" #include "world/Weather.hpp" +#include "window/Camera.hpp" class Level; class Player; @@ -48,14 +49,13 @@ class WorldRenderer { std::unique_ptr skybox; std::unique_ptr shadowMap; Weather weather {}; - - std::unique_ptr shadowCamera; + Camera shadowCamera; float timer = 0.0f; bool debug = false; bool lightsDebug = false; bool gbufferPipeline = false; - bool shadows = true; + bool shadows = false; /// @brief Render block selection lines void renderBlockSelection(); @@ -77,6 +77,8 @@ class WorldRenderer { const EngineSettings& settings, float fogFactor ); + + void generateShadowsMap(const Camera& camera, const DrawContext& pctx); public: std::unique_ptr particles; std::unique_ptr texts; From b5253bff9986a79ceb15360886a0c3f9aee2e89b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 10 May 2025 16:29:30 +0300 Subject: [PATCH 08/47] fix segfault --- res/shaders/main.glslv | 1 - src/graphics/render/WorldRenderer.cpp | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index d7e5b4fc..cd0fa79c 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -46,7 +46,6 @@ void main() { a_dir = a_modelpos.xyz - u_cameraPos; vec3 skyLightColor = pick_sky_color(u_skybox); a_skyLight = skyLightColor.rgb*v_light.a; - //a_color.rgb = max(a_color.rgb, skyLightColor.rgb*v_light.a); a_distance = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0)); a_fog = calc_fog(a_distance / 256.0); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index c30093bd..f6eded82 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -131,9 +131,6 @@ void WorldRenderer::setupWorldShader( shader.uniform1i("u_enableShadows", shadows); if (shadows) { - if (shadowMap == nullptr) { - shadowMap = std::make_unique(1024 * 8); - } shader.uniformMatrix("u_shadowsMatrix", shadowCamera.getProjView()); shader.uniform3f("u_sunDir", shadowCamera.front); shader.uniform1i("u_shadowsRes", shadowMap->getResolution()); @@ -407,6 +404,9 @@ void WorldRenderer::draw( skybox->refresh(pctx, worldInfo.daytime, mie, 4); if (shadows) { + if (shadowMap == nullptr) { + shadowMap = std::make_unique(1024 * 8); + } generateShadowsMap(camera, pctx); } From b272d8661934bc185225b06fd3f9bf7f0bdadc67 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 11 May 2025 01:09:41 +0300 Subject: [PATCH 09/47] add 'grahics.advanced-render' and 'graphics.shadows-quality' settings --- res/layouts/pages/settings_graphics.xml.lua | 2 ++ res/texts/ru_RU.txt | 2 ++ src/graphics/render/ChunksRenderer.cpp | 4 +--- src/graphics/render/WorldRenderer.cpp | 21 +++++++++++++++++---- src/io/settings_io.cpp | 2 ++ src/settings.hpp | 4 ++++ 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/res/layouts/pages/settings_graphics.xml.lua b/res/layouts/pages/settings_graphics.xml.lua index c4503e52..32c26fd5 100644 --- a/res/layouts/pages/settings_graphics.xml.lua +++ b/res/layouts/pages/settings_graphics.xml.lua @@ -42,4 +42,6 @@ function on_open() create_setting("graphics.gamma", "Gamma", 0.05, "", "graphics.gamma.tooltip") create_checkbox("graphics.backlight", "Backlight", "graphics.backlight.tooltip") create_checkbox("graphics.dense-render", "Dense blocks render", "graphics.dense-render.tooltip") + create_checkbox("graphics.advanced-render", "Advanced render", "graphics.advanced-render.tooltip") + create_setting("graphics.shadows-quality", "Shadows quality", 1) end diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt index 1836981d..d2d7c63e 100644 --- a/res/texts/ru_RU.txt +++ b/res/texts/ru_RU.txt @@ -98,6 +98,8 @@ settings.V-Sync=Вертикальная Синхронизация settings.Key=Кнопка settings.Controls Search Mode=Поиск по привязанной кнопки управления settings.Limit Background FPS=Ограничить фоновую частоту кадров +settings.Advanced render=Продвинутый рендер +settings.Shadows quality=Качество теней # Управление chunks.reload=Перезагрузить Чанки diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index 8c88931b..284ebb43 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -189,8 +189,7 @@ void ChunksRenderer::drawChunksShadowsPass( atlas.getTexture()->bind(); - for (int i = indices.size()-1; i >= 0; i--) { - auto& chunk = chunks.getChunks()[indices[i].index]; + for (const auto& chunk : chunks.getChunks()) { if (chunk == nullptr) { continue; } @@ -216,7 +215,6 @@ void ChunksRenderer::drawChunks( const auto& atlas = assets.require("blocks"); atlas.getTexture()->bind(); - update(); // [warning] this whole method is not thread-safe for chunks diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index f6eded82..1fec6a47 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -345,7 +345,7 @@ void WorldRenderer::generateShadowsMap(const Camera& camera, const DrawContext& const auto& settings = engine.getSettings(); int resolution = shadowMap->getResolution(); - float shadowMapScale = 0.05f; + float shadowMapScale = 0.2f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())); float shadowMapSize = resolution * shadowMapScale; shadowCamera = Camera(camera.position, shadowMapSize); shadowCamera.near = 0.1f; @@ -393,6 +393,20 @@ void WorldRenderer::draw( camera.setAspectRatio(vp.x / static_cast(vp.y)); const auto& settings = engine.getSettings(); + gbufferPipeline = settings.graphics.advancedRender.get(); + int shadowsQuality = settings.graphics.shadowsQuality.get(); + int resolution = 1024 << shadowsQuality; + if (shadowsQuality > 0 && !shadows) { + shadowMap = std::make_unique(resolution); + shadows = true; + } else if (shadowsQuality == 0) { + shadowMap.reset(); + shadows = false; + } + if (shadows && shadowMap->getResolution() != resolution) { + shadowMap = std::make_unique(resolution); + } + const auto& worldInfo = world->getInfo(); float sqrtT = glm::sqrt(weather.t); @@ -403,10 +417,9 @@ void WorldRenderer::draw( skybox->refresh(pctx, worldInfo.daytime, mie, 4); + chunks->update(); + if (shadows) { - if (shadowMap == nullptr) { - shadowMap = std::make_unique(1024 * 8); - } generateShadowsMap(camera, pctx); } diff --git a/src/io/settings_io.cpp b/src/io/settings_io.cpp index 39df07f0..a968d9e0 100644 --- a/src/io/settings_io.cpp +++ b/src/io/settings_io.cpp @@ -74,6 +74,8 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) { builder.add("chunk-max-vertices", &settings.graphics.chunkMaxVertices); builder.add("chunk-max-vertices-dense", &settings.graphics.chunkMaxVerticesDense); builder.add("chunk-max-renderers", &settings.graphics.chunkMaxRenderers); + builder.add("advanced-render", &settings.graphics.advancedRender); + builder.add("shadows-quality", &settings.graphics.shadowsQuality); builder.section("ui"); builder.add("language", &settings.ui.language); diff --git a/src/settings.hpp b/src/settings.hpp index 53ebf5f9..714372fe 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -75,6 +75,10 @@ struct GraphicsSettings { IntegerSetting chunkMaxVerticesDense {800'000, 0, 8'000'000}; /// @brief Limit of chunk renderers count IntegerSetting chunkMaxRenderers {6, -4, 32}; + /// @brief Advanced render pipeline + FlagSetting advancedRender {true}; + /// @brief Shadows quality + IntegerSetting shadowsQuality {0, 0, 2}; }; struct DebugSettings { From ad0396b31e730a98ed8176686ef2eebcfc98bd0b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 11 May 2025 20:55:35 +0300 Subject: [PATCH 10/47] improve shadow map stability --- res/shaders/effects/default.glsl | 1 + res/shaders/lib/shadows.glsl | 15 ++++++++++- src/graphics/render/BlocksRenderer.cpp | 15 ++++++++--- src/graphics/render/WorldRenderer.cpp | 36 ++++++++++++++++++++------ src/settings.hpp | 2 +- src/window/Camera.cpp | 8 ++++++ src/window/Camera.hpp | 5 ++++ 7 files changed, 68 insertions(+), 14 deletions(-) diff --git a/res/shaders/effects/default.glsl b/res/shaders/effects/default.glsl index c2f9effa..f7a94851 100644 --- a/res/shaders/effects/default.glsl +++ b/res/shaders/effects/default.glsl @@ -1,3 +1,4 @@ vec4 effect() { + //return vec4(vec3(pow(texture(u_shadows, v_uv).r, 5.0) * 1000.0), 1.0); return texture(u_screen, v_uv); } diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index 9e96d3ea..4ba3ea6e 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -1,10 +1,22 @@ #ifndef SHADOWS_GLSL_ #define SHADOWS_GLSL_ +float sample_shadow(vec3 uv, vec3 xy) { + float color = 0.0; + vec3 off1 = vec3(1.3846153846) * xy; + vec3 off2 = vec3(3.2307692308) * xy; + color += texture(u_shadows, uv) * 0.2270270270; + color += texture(u_shadows, uv + (off1 / u_shadowsRes)) * 0.3162162162; + color += texture(u_shadows, uv - (off1 / u_shadowsRes)) * 0.3162162162; + color += texture(u_shadows, uv + (off2 / u_shadowsRes)) * 0.0702702703; + color += texture(u_shadows, uv - (off2 / u_shadowsRes)) * 0.0702702703; + return color; +} + float calc_shadow() { float shadow = 1.0; if (u_enableShadows) { - vec4 mpos = u_shadowsMatrix * vec4(a_modelpos.xyz + a_realnormal * 0.08, 1.0); + vec4 mpos = u_shadowsMatrix * vec4(a_modelpos.xyz + a_realnormal * 0.04, 1.0); vec3 projCoords = mpos.xyz / mpos.w; projCoords = projCoords * 0.5 + 0.5; projCoords.z -= 0.0001; @@ -22,6 +34,7 @@ float calc_shadow() { shadow += texture(u_shadows, projCoords.xyz + offsets[i] / u_shadowsRes); } shadow /= 4; + //shadow = sample_shadow(projCoords, normalize(vec3(1.0, 1.0, 0.0)) * 0.5); shadow = shadow * 0.5 + 0.5; } else { shadow = 0.5; diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 1bc499fb..8480bd72 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -203,14 +203,21 @@ void BlocksRenderer::blockXSprite( const float w = size.x / 1.41f; const glm::vec4 tint (0.8f); - face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, 1}, {0, 1, 0}, glm::vec3(), + glm::vec3 n; + float bias = 0.05f; + + n = glm::vec3(-0.7f, 0, -0.7f); + face(glm::vec3(x + xs, y, z + zs) + n * bias, w, size.y, 0, {-1, 0, 1}, {0, 1, 0}, n, texface1, lights2, tint); - face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, 1}, {0, 1, 0}, glm::vec3(), + n = glm::vec3(-0.7f, 0, 0.7f); + face(glm::vec3(x + xs, y, z + zs) + n * bias, w, size.y, 0, {1, 0, 1}, {0, 1, 0}, n, texface1, lights1, tint); - face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, -1}, {0, 1, 0}, glm::vec3(), + n = glm::vec3(0.7f, 0, -0.7f); + face(glm::vec3(x + xs, y, z + zs) + n * bias, w, size.y, 0, {-1, 0, -1}, {0, 1, 0}, n, texface2, lights2, tint); - face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, -1}, {0, 1, 0}, glm::vec3(), + n = glm::vec3(0.7f, 0, 0.7f); + face(glm::vec3(x + xs, y, z + zs) + n * bias, w, size.y, 0, {1, 0, -1}, {0, 1, 0}, n, texface2, lights1, tint); } diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 1fec6a47..501d39b9 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -345,23 +345,41 @@ void WorldRenderer::generateShadowsMap(const Camera& camera, const DrawContext& const auto& settings = engine.getSettings(); int resolution = shadowMap->getResolution(); - float shadowMapScale = 0.2f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())); + float shadowMapScale = 0.1f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())); float shadowMapSize = resolution * shadowMapScale; - shadowCamera = Camera(camera.position, shadowMapSize); + + glm::vec3 basePos = glm::floor(camera.position / 500.0f) * 500.0f; + shadowCamera = Camera(basePos + glm::mod(camera.position, 500.0f), shadowMapSize); shadowCamera.near = 0.1f; shadowCamera.far = 800.0f; shadowCamera.perspective = false; shadowCamera.setAspectRatio(1.0f); + + float sunAngle = glm::radians(fmod(90.0f - worldInfo.daytime * 360.0f, 180.0f)); shadowCamera.rotate( - glm::radians(fmod(90.0f - worldInfo.daytime * 360.0f, 180.0f)), - glm::radians(-40.0f), + sunAngle, + glm::radians(-45.0f), glm::radians(-0.0f) ); shadowCamera.updateVectors(); + shadowCamera.position -= shadowCamera.front * 200.0f; - shadowCamera.position -= shadowCamera.right * (resolution * shadowMapScale) * 0.5f; - shadowCamera.position -= shadowCamera.up * (resolution * shadowMapScale) * 0.5f; - shadowCamera.position = glm::floor(shadowCamera.position * 0.25f) * 4.0f; + shadowCamera.position += shadowCamera.up * 10.0f; + + auto view = shadowCamera.getView(); + + auto currentPos = shadowCamera.position; + auto min = view * glm::dvec4(currentPos - (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); + auto max = view * glm::dvec4(currentPos + (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); + + float texelSize = (max.x - min.x) / shadowMapSize; + float snappedLeft = glm::round(min.x / texelSize) * texelSize; + float snappedBottom = glm::round(min.y / texelSize) * texelSize; + float snappedRight = snappedLeft + shadowMapSize * texelSize; + float snappedTop = snappedBottom + shadowMapSize * texelSize; + + shadowCamera.setProjection(glm::ortho(snappedLeft, snappedRight, snappedBottom, snappedTop, 0.1f, 800.0f)); + { frustumCulling->update(shadowCamera.getProjView()); auto sctx = pctx.sub(); @@ -419,9 +437,11 @@ void WorldRenderer::draw( chunks->update(); - if (shadows) { + static int frameid = 0; + if (shadows && frameid % 2 == 0) { generateShadowsMap(camera, pctx); } + frameid++; auto& linesShader = assets.require("lines"); /* World render scope with diegetic HUD included */ { diff --git a/src/settings.hpp b/src/settings.hpp index 714372fe..699d2b28 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -78,7 +78,7 @@ struct GraphicsSettings { /// @brief Advanced render pipeline FlagSetting advancedRender {true}; /// @brief Shadows quality - IntegerSetting shadowsQuality {0, 0, 2}; + IntegerSetting shadowsQuality {0, 0, 3}; }; struct DebugSettings { diff --git a/src/window/Camera.cpp b/src/window/Camera.cpp index 1854ff0e..fb23676d 100644 --- a/src/window/Camera.cpp +++ b/src/window/Camera.cpp @@ -28,6 +28,9 @@ void Camera::rotate(float x, float y, float z) { } glm::mat4 Camera::getProjection() const { + if (projset) { + return projection; + } if (perspective) { return glm::perspective(fov * zoom, ar, near, far); } else if (flipped) { @@ -62,6 +65,11 @@ float Camera::getFov() const { return fov; } +void Camera::setProjection(const glm::mat4& matrix) { + projection = matrix; + projset = true; +} + float Camera::getAspectRatio() const { return ar; } diff --git a/src/window/Camera.hpp b/src/window/Camera.hpp index ba4a5331..11838234 100644 --- a/src/window/Camera.hpp +++ b/src/window/Camera.hpp @@ -21,6 +21,9 @@ public: float near = 0.05f; float far = 1500.0f; + bool projset = false; + glm::mat4 projection; + Camera() { updateVectors(); } @@ -36,6 +39,8 @@ public: void setFov(float fov); float getFov() const; + void setProjection(const glm::mat4& matrix); + float getAspectRatio() const; void setAspectRatio(float ar); }; From 9e05f6dbb6909dd969b3c359ef1fd716de1b8d89 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 12 May 2025 00:25:39 +0300 Subject: [PATCH 11/47] simple cascade shadows test --- res/shaders/entity.glslf | 5 +-- res/shaders/lib/shadows.glsl | 49 +++++++++++++++------------ res/shaders/main.glslf | 5 +-- src/graphics/render/WorldRenderer.cpp | 36 +++++++++++++++----- src/graphics/render/WorldRenderer.hpp | 10 +++++- 5 files changed, 67 insertions(+), 38 deletions(-) diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index b9369874..4348c60f 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -1,3 +1,4 @@ +in float a_distance; in vec4 a_color; in vec2 a_texCoord; in vec3 a_position; @@ -17,13 +18,9 @@ uniform vec3 u_fogColor; uniform float u_fogFactor; uniform float u_fogCurve; uniform bool u_alphaClip; - -uniform sampler2DShadow u_shadows; uniform vec3 u_sunDir; -uniform int u_shadowsRes; uniform bool u_enableShadows; -uniform mat4 u_shadowsMatrix; #include diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index 4ba3ea6e..062584e1 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -1,17 +1,12 @@ #ifndef SHADOWS_GLSL_ #define SHADOWS_GLSL_ -float sample_shadow(vec3 uv, vec3 xy) { - float color = 0.0; - vec3 off1 = vec3(1.3846153846) * xy; - vec3 off2 = vec3(3.2307692308) * xy; - color += texture(u_shadows, uv) * 0.2270270270; - color += texture(u_shadows, uv + (off1 / u_shadowsRes)) * 0.3162162162; - color += texture(u_shadows, uv - (off1 / u_shadowsRes)) * 0.3162162162; - color += texture(u_shadows, uv + (off2 / u_shadowsRes)) * 0.0702702703; - color += texture(u_shadows, uv - (off2 / u_shadowsRes)) * 0.0702702703; - return color; -} +uniform sampler2DShadow u_shadows; +uniform sampler2DShadow u_wideShadows; +uniform int u_shadowsRes; +uniform bool u_blurShadows; +uniform mat4 u_shadowsMatrix; +uniform mat4 u_wideShadowsMatrix; float calc_shadow() { float shadow = 1.0; @@ -21,20 +16,32 @@ float calc_shadow() { projCoords = projCoords * 0.5 + 0.5; projCoords.z -= 0.0001; + vec4 wmpos = u_wideShadowsMatrix * vec4(a_modelpos.xyz + a_realnormal * 0.2, 1.0); + vec3 wprojCoords = wmpos.xyz / wmpos.w; + wprojCoords = wprojCoords * 0.5 + 0.5; + wprojCoords.z -= 0.0001; + shadow = 0.0; if (dot(a_realnormal, u_sunDir) < 0.0) { - const vec3 offsets[4] = vec3[4]( - vec3(0.5, 0.5, 0.0), - vec3(-0.5, 0.5, 0.0), - vec3(0.5, -0.5, 0.0), - vec3(-0.5, -0.5, 0.0) - ); - for (int i = 0; i < 4; i++) { - shadow += texture(u_shadows, projCoords.xyz + offsets[i] / u_shadowsRes); + if (u_blurShadows) { + const vec3 offsets[4] = vec3[4]( + vec3(0.5, 0.5, 0.0), + vec3(-0.5, 0.5, 0.0), + vec3(0.5, -0.5, 0.0), + vec3(-0.5, -0.5, 0.0) + ); + for (int i = 0; i < 4; i++) { + shadow += texture(u_shadows, projCoords.xyz + offsets[i] / u_shadowsRes); + } + shadow /= 4; + } else { + if (a_distance > 32.0) { + shadow = texture(u_wideShadows, wprojCoords.xyz); + } else { + shadow = texture(u_shadows, projCoords.xyz); + } } - shadow /= 4; - //shadow = sample_shadow(projCoords, normalize(vec3(1.0, 1.0, 0.0)) * 0.5); shadow = shadow * 0.5 + 0.5; } else { shadow = 0.5; diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index cbb29de6..f1a4a549 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -2,6 +2,7 @@ layout (location = 0) out vec4 f_color; layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; +in float a_distance; in vec4 a_torchLight; in vec3 a_skyLight; in vec2 a_texCoord; @@ -14,9 +15,7 @@ in vec4 a_modelpos; uniform sampler2D u_texture0; uniform samplerCube u_skybox; -uniform sampler2DShadow u_shadows; uniform vec3 u_sunDir; -uniform int u_shadowsRes; // flags uniform bool u_alphaClip; @@ -24,8 +23,6 @@ uniform bool u_debugLights; uniform bool u_debugNormals; uniform bool u_enableShadows; -uniform mat4 u_shadowsMatrix; - #include void main() { diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 501d39b9..6b94309b 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -132,11 +132,18 @@ void WorldRenderer::setupWorldShader( if (shadows) { shader.uniformMatrix("u_shadowsMatrix", shadowCamera.getProjView()); + shader.uniformMatrix("u_wideShadowsMatrix", wideShadowCamera.getProjView()); shader.uniform3f("u_sunDir", shadowCamera.front); shader.uniform1i("u_shadowsRes", shadowMap->getResolution()); + glActiveTexture(GL_TEXTURE4); shader.uniform1i("u_shadows", 4); glBindTexture(GL_TEXTURE_2D, shadowMap->getDepthMap()); + + glActiveTexture(GL_TEXTURE5); + shader.uniform1i("u_wideShadows", 5); + glBindTexture(GL_TEXTURE_2D, wideShadowMap->getDepthMap()); + glActiveTexture(GL_TEXTURE0); } @@ -337,15 +344,21 @@ void WorldRenderer::renderHands( skybox->unbind(); } -void WorldRenderer::generateShadowsMap(const Camera& camera, const DrawContext& pctx) { +void WorldRenderer::generateShadowsMap( + const Camera& camera, + const DrawContext& pctx, + ShadowMap& shadowMap, + Camera& shadowCamera, + float scale +) { auto& shadowsShader = assets.require("shadows"); auto world = level.getWorld(); const auto& worldInfo = world->getInfo(); const auto& settings = engine.getSettings(); - int resolution = shadowMap->getResolution(); - float shadowMapScale = 0.1f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())); + int resolution = shadowMap.getResolution(); + float shadowMapScale = 0.1f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) * scale; float shadowMapSize = resolution * shadowMapScale; glm::vec3 basePos = glm::floor(camera.position / 500.0f) * 500.0f; @@ -386,10 +399,10 @@ void WorldRenderer::generateShadowsMap(const Camera& camera, const DrawContext& sctx.setDepthTest(true); sctx.setCullFace(true); sctx.setViewport({resolution, resolution}); - shadowMap->bind(); + shadowMap.bind(); setupWorldShader(shadowsShader, shadowCamera, settings, 0.0f); chunks->drawChunksShadowsPass(shadowCamera, shadowsShader); - shadowMap->unbind(); + shadowMap.unbind(); } } @@ -413,16 +426,19 @@ void WorldRenderer::draw( const auto& settings = engine.getSettings(); gbufferPipeline = settings.graphics.advancedRender.get(); int shadowsQuality = settings.graphics.shadowsQuality.get(); - int resolution = 1024 << shadowsQuality; + int resolution = 512 << shadowsQuality; if (shadowsQuality > 0 && !shadows) { shadowMap = std::make_unique(resolution); + wideShadowMap = std::make_unique(resolution); shadows = true; } else if (shadowsQuality == 0) { shadowMap.reset(); + wideShadowMap.reset(); shadows = false; } if (shadows && shadowMap->getResolution() != resolution) { shadowMap = std::make_unique(resolution); + wideShadowMap = std::make_unique(resolution); } const auto& worldInfo = world->getInfo(); @@ -438,8 +454,12 @@ void WorldRenderer::draw( chunks->update(); static int frameid = 0; - if (shadows && frameid % 2 == 0) { - generateShadowsMap(camera, pctx); + if (shadows) { + if (frameid % 2 == 0) { + generateShadowsMap(camera, pctx, *shadowMap, shadowCamera, 1.0f); + } else { + generateShadowsMap(camera, pctx, *wideShadowMap, wideShadowCamera, 8.0f); + } } frameid++; diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 7db4e44a..59c959b7 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -48,8 +48,10 @@ class WorldRenderer { std::unique_ptr chunks; std::unique_ptr skybox; std::unique_ptr shadowMap; + std::unique_ptr wideShadowMap; Weather weather {}; Camera shadowCamera; + Camera wideShadowCamera; float timer = 0.0f; bool debug = false; @@ -78,7 +80,13 @@ class WorldRenderer { float fogFactor ); - void generateShadowsMap(const Camera& camera, const DrawContext& pctx); + void generateShadowsMap( + const Camera& camera, + const DrawContext& pctx, + ShadowMap& shadowMap, + Camera& shadowCamera, + float scale + ); public: std::unique_ptr particles; std::unique_ptr texts; From 44f7051a949b6ba32e8babd5870166ebcb1d20ac Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 12 May 2025 07:04:08 +0300 Subject: [PATCH 12/47] fix a_distance --- res/shaders/entity.glslv | 5 +++-- res/shaders/main.glslv | 5 +++-- src/graphics/render/WorldRenderer.cpp | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/res/shaders/entity.glslv b/res/shaders/entity.glslv index 607c4721..ee5b9538 100644 --- a/res/shaders/entity.glslv +++ b/res/shaders/entity.glslv @@ -48,8 +48,9 @@ void main() { a_color.rgb = max(a_color.rgb, skyLightColor.rgb*v_light.a) * v_color; a_color.a = u_opacity; - a_distance = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0)); - a_fog = calc_fog(a_distance / 256.0); + mat4 viewmodel = u_view * u_model; + a_distance = length(viewmodel * vec4(pos3d, 0.0)); + a_fog = calc_fog(length(viewmodel * vec4(pos3d * FOG_POS_SCALE, 0.0)) / 256.0); vec4 viewmodelpos = u_view * a_modelpos; a_position = viewmodelpos.xyz; diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index cd0fa79c..fa28b8e3 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -47,8 +47,9 @@ void main() { vec3 skyLightColor = pick_sky_color(u_skybox); a_skyLight = skyLightColor.rgb*v_light.a; - a_distance = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0)); - a_fog = calc_fog(a_distance / 256.0); + mat4 viewmodel = u_view * u_model; + a_distance = length(viewmodel * vec4(pos3d, 0.0)); + a_fog = calc_fog(length(viewmodel * vec4(pos3d * FOG_POS_SCALE, 0.0)) / 256.0); vec4 viewmodelpos = u_view * a_modelpos; a_position = viewmodelpos.xyz; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 6b94309b..90895c46 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -358,7 +358,7 @@ void WorldRenderer::generateShadowsMap( const auto& settings = engine.getSettings(); int resolution = shadowMap.getResolution(); - float shadowMapScale = 0.1f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) * scale; + float shadowMapScale = 0.2f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) * scale; float shadowMapSize = resolution * shadowMapScale; glm::vec3 basePos = glm::floor(camera.position / 500.0f) * 500.0f; From ed5efd9c3aa3733c24eab8718c589c86bca2cb6f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 21 May 2025 21:41:01 +0300 Subject: [PATCH 13/47] improve shadows --- res/scripts/hud.lua | 2 +- res/shaders/effects/ssao.glsl | 31 ++++++++-------- res/shaders/lib/shadows.glsl | 50 ++++++++++++++++---------- src/graphics/render/BlocksRenderer.cpp | 15 +++----- src/graphics/render/WorldRenderer.cpp | 35 +++++++++--------- 5 files changed, 68 insertions(+), 65 deletions(-) diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua index f415cf39..79fe0e42 100644 --- a/res/scripts/hud.lua +++ b/res/scripts/hud.lua @@ -58,5 +58,5 @@ function on_hud_open() local slot = gfx.posteffects.index("core:default") gfx.posteffects.set_effect(slot, "ssao") - --gfx.posteffects.set_intensity(slot, 1.0) + gfx.posteffects.set_intensity(slot, 1.0) end diff --git a/res/shaders/effects/ssao.glsl b/res/shaders/effects/ssao.glsl index 854b9673..f0894b49 100644 --- a/res/shaders/effects/ssao.glsl +++ b/res/shaders/effects/ssao.glsl @@ -16,24 +16,21 @@ vec4 effect() { 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 = min(1.0, 1.05 - (occlusion / kernelSize)); + float 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 = min(1.0, 1.05 - (occlusion / kernelSize)); float z = -position.z * 0.02; z = max(0.0, 1.0 - z); diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index 062584e1..7da8d564 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -1,22 +1,21 @@ #ifndef SHADOWS_GLSL_ #define SHADOWS_GLSL_ -uniform sampler2DShadow u_shadows; -uniform sampler2DShadow u_wideShadows; +uniform sampler2DShadow u_shadows[2]; +uniform mat4 u_shadowsMatrix[2]; + uniform int u_shadowsRes; uniform bool u_blurShadows; -uniform mat4 u_shadowsMatrix; -uniform mat4 u_wideShadowsMatrix; float calc_shadow() { float shadow = 1.0; if (u_enableShadows) { - vec4 mpos = u_shadowsMatrix * vec4(a_modelpos.xyz + a_realnormal * 0.04, 1.0); + vec4 mpos = u_shadowsMatrix[0] * vec4(a_modelpos.xyz + a_realnormal * 0.04, 1.0); vec3 projCoords = mpos.xyz / mpos.w; projCoords = projCoords * 0.5 + 0.5; projCoords.z -= 0.0001; - vec4 wmpos = u_wideShadowsMatrix * vec4(a_modelpos.xyz + a_realnormal * 0.2, 1.0); + vec4 wmpos = u_shadowsMatrix[1] * vec4(a_modelpos.xyz + a_realnormal * 0.2, 1.0); vec3 wprojCoords = wmpos.xyz / wmpos.w; wprojCoords = wprojCoords * 0.5 + 0.5; wprojCoords.z -= 0.0001; @@ -24,22 +23,37 @@ float calc_shadow() { shadow = 0.0; if (dot(a_realnormal, u_sunDir) < 0.0) { - if (u_blurShadows) { - const vec3 offsets[4] = vec3[4]( - vec3(0.5, 0.5, 0.0), - vec3(-0.5, 0.5, 0.0), - vec3(0.5, -0.5, 0.0), - vec3(-0.5, -0.5, 0.0) - ); - for (int i = 0; i < 4; i++) { - shadow += texture(u_shadows, projCoords.xyz + offsets[i] / u_shadowsRes); + if (u_blurShadows || true) { + if (a_distance > 64) { + for (int y = -1; y <= 1; y++) { + for (int x = -1; x <= 1; x++) { + shadow += texture( + u_shadows[1], + wprojCoords.xyz + + vec3(x, y, -(abs(x) + abs(y))) / + u_shadowsRes + ); + } + } + shadow /= 9; + } else { + for (int y = -2; y <= 2; y++) { + for (int x = -2; x <= 2; x++) { + shadow += texture( + u_shadows[0], + projCoords.xyz + + vec3(x, y, -(abs(x) + abs(y))) / + u_shadowsRes * 1.0 + ); + } + } + shadow /= 25; } - shadow /= 4; } else { if (a_distance > 32.0) { - shadow = texture(u_wideShadows, wprojCoords.xyz); + shadow = texture(u_shadows[1], wprojCoords.xyz); } else { - shadow = texture(u_shadows, projCoords.xyz); + shadow = texture(u_shadows[0], projCoords.xyz); } } shadow = shadow * 0.5 + 0.5; diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 8480bd72..f7b1abe1 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -203,21 +203,16 @@ void BlocksRenderer::blockXSprite( const float w = size.x / 1.41f; const glm::vec4 tint (0.8f); - glm::vec3 n; - float bias = 0.05f; + glm::vec3 n(0.0f, 1.0f, 0.0f); - n = glm::vec3(-0.7f, 0, -0.7f); - face(glm::vec3(x + xs, y, z + zs) + n * bias, w, size.y, 0, {-1, 0, 1}, {0, 1, 0}, n, + face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, 1}, {0, 1, 0}, n, texface1, lights2, tint); - n = glm::vec3(-0.7f, 0, 0.7f); - face(glm::vec3(x + xs, y, z + zs) + n * bias, w, size.y, 0, {1, 0, 1}, {0, 1, 0}, n, + face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, 1}, {0, 1, 0}, n, texface1, lights1, tint); - n = glm::vec3(0.7f, 0, -0.7f); - face(glm::vec3(x + xs, y, z + zs) + n * bias, w, size.y, 0, {-1, 0, -1}, {0, 1, 0}, n, + face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, -1}, {0, 1, 0}, n, texface2, lights2, tint); - n = glm::vec3(0.7f, 0, 0.7f); - face(glm::vec3(x + xs, y, z + zs) + n * bias, w, size.y, 0, {1, 0, -1}, {0, 1, 0}, n, + face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, -1}, {0, 1, 0}, n, texface2, lights1, tint); } diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 90895c46..c7196298 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -131,17 +131,17 @@ void WorldRenderer::setupWorldShader( shader.uniform1i("u_enableShadows", shadows); if (shadows) { - shader.uniformMatrix("u_shadowsMatrix", shadowCamera.getProjView()); - shader.uniformMatrix("u_wideShadowsMatrix", wideShadowCamera.getProjView()); + shader.uniformMatrix("u_shadowsMatrix[0]", shadowCamera.getProjView()); + shader.uniformMatrix("u_shadowsMatrix[1]", wideShadowCamera.getProjView()); shader.uniform3f("u_sunDir", shadowCamera.front); shader.uniform1i("u_shadowsRes", shadowMap->getResolution()); glActiveTexture(GL_TEXTURE4); - shader.uniform1i("u_shadows", 4); + shader.uniform1i("u_shadows[0]", 4); glBindTexture(GL_TEXTURE_2D, shadowMap->getDepthMap()); glActiveTexture(GL_TEXTURE5); - shader.uniform1i("u_wideShadows", 5); + shader.uniform1i("u_shadows[1]", 5); glBindTexture(GL_TEXTURE_2D, wideShadowMap->getDepthMap()); glActiveTexture(GL_TEXTURE0); @@ -358,11 +358,13 @@ void WorldRenderer::generateShadowsMap( const auto& settings = engine.getSettings(); int resolution = shadowMap.getResolution(); - float shadowMapScale = 0.2f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) * scale; + float shadowMapScale = + 0.2f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) * + scale; float shadowMapSize = resolution * shadowMapScale; - glm::vec3 basePos = glm::floor(camera.position / 500.0f) * 500.0f; - shadowCamera = Camera(basePos + glm::mod(camera.position, 500.0f), shadowMapSize); + glm::vec3 basePos = glm::floor(camera.position); + shadowCamera = Camera(basePos, shadowMapSize); shadowCamera.near = 0.1f; shadowCamera.far = 800.0f; shadowCamera.perspective = false; @@ -378,20 +380,15 @@ void WorldRenderer::generateShadowsMap( shadowCamera.position -= shadowCamera.front * 200.0f; shadowCamera.position += shadowCamera.up * 10.0f; + shadowCamera.position += camera.front * 100.0f; auto view = shadowCamera.getView(); auto currentPos = shadowCamera.position; - auto min = view * glm::dvec4(currentPos - (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); - auto max = view * glm::dvec4(currentPos + (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); + auto min = view * glm::vec4(currentPos - (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); + auto max = view * glm::vec4(currentPos + (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); - float texelSize = (max.x - min.x) / shadowMapSize; - float snappedLeft = glm::round(min.x / texelSize) * texelSize; - float snappedBottom = glm::round(min.y / texelSize) * texelSize; - float snappedRight = snappedLeft + shadowMapSize * texelSize; - float snappedTop = snappedBottom + shadowMapSize * texelSize; - - shadowCamera.setProjection(glm::ortho(snappedLeft, snappedRight, snappedBottom, snappedTop, 0.1f, 800.0f)); + shadowCamera.setProjection(glm::ortho(min.x, max.x, min.y, max.y, 0.1f, 800.0f)); { frustumCulling->update(shadowCamera.getProjView()); @@ -426,7 +423,7 @@ void WorldRenderer::draw( const auto& settings = engine.getSettings(); gbufferPipeline = settings.graphics.advancedRender.get(); int shadowsQuality = settings.graphics.shadowsQuality.get(); - int resolution = 512 << shadowsQuality; + int resolution = 1024 << shadowsQuality; if (shadowsQuality > 0 && !shadows) { shadowMap = std::make_unique(resolution); wideShadowMap = std::make_unique(resolution); @@ -454,11 +451,11 @@ void WorldRenderer::draw( chunks->update(); static int frameid = 0; - if (shadows) { + if (shadows && frameid % 3 == 0) { if (frameid % 2 == 0) { generateShadowsMap(camera, pctx, *shadowMap, shadowCamera, 1.0f); } else { - generateShadowsMap(camera, pctx, *wideShadowMap, wideShadowCamera, 8.0f); + generateShadowsMap(camera, pctx, *wideShadowMap, wideShadowCamera, 4.0f); } } frameid++; From d030fbc3d597f3c1464fd9e8cc5170f0be8e77e4 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 10 Jun 2025 20:29:32 +0300 Subject: [PATCH 14/47] fix in-hand item render --- src/graphics/render/WorldRenderer.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index c7196298..e9a0d4fe 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -482,9 +482,6 @@ void WorldRenderer::draw( ctx, camera, *lineBatch, linesShader, showChunkBorders ); } - if (player.currentCamera == player.fpCamera) { - renderHands(camera, delta); - } } } { @@ -500,6 +497,12 @@ void WorldRenderer::draw( camera, shadows ? shadowMap->getDepthMap() : 0 ); + if (player.currentCamera == player.fpCamera) { + DrawContext ctx = pctx.sub(); + ctx.setDepthTest(true); + ctx.setCullFace(true); + renderHands(camera, delta); + } renderBlockOverlay(pctx); glActiveTexture(GL_TEXTURE0); From 11283f9a33f1c16b3c2956ff353fffd427ce9e0e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 10 Jun 2025 22:50:04 +0300 Subject: [PATCH 15/47] cleanup --- res/shaders/lib/shadows.glsl | 50 +++++++++++++++--------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index 7da8d564..aa1ca09b 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -5,7 +5,6 @@ uniform sampler2DShadow u_shadows[2]; uniform mat4 u_shadowsMatrix[2]; uniform int u_shadowsRes; -uniform bool u_blurShadows; float calc_shadow() { float shadow = 1.0; @@ -22,39 +21,32 @@ float calc_shadow() { shadow = 0.0; + // TODO: optimize if (dot(a_realnormal, u_sunDir) < 0.0) { - if (u_blurShadows || true) { - if (a_distance > 64) { - for (int y = -1; y <= 1; y++) { - for (int x = -1; x <= 1; x++) { - shadow += texture( - u_shadows[1], - wprojCoords.xyz + - vec3(x, y, -(abs(x) + abs(y))) / - u_shadowsRes - ); - } + if (a_distance > 128) { + for (int y = -1; y <= 1; y++) { + for (int x = -1; x <= 1; x++) { + shadow += texture( + u_shadows[1], + wprojCoords.xyz + + vec3(x, y, -(abs(x) + abs(y))) / + u_shadowsRes + ); } - shadow /= 9; - } else { - for (int y = -2; y <= 2; y++) { - for (int x = -2; x <= 2; x++) { - shadow += texture( - u_shadows[0], - projCoords.xyz + - vec3(x, y, -(abs(x) + abs(y))) / - u_shadowsRes * 1.0 - ); - } - } - shadow /= 25; } + shadow /= 9; } else { - if (a_distance > 32.0) { - shadow = texture(u_shadows[1], wprojCoords.xyz); - } else { - shadow = texture(u_shadows[0], projCoords.xyz); + for (int y = -2; y <= 2; y++) { + for (int x = -2; x <= 2; x++) { + shadow += texture( + u_shadows[0], + projCoords.xyz + + vec3(x, y, -(abs(x) + abs(y))) / + u_shadowsRes * 1.0 + ); + } } + shadow /= 25; } shadow = shadow * 0.5 + 0.5; } else { From 1a3fb9f5b3a78fcfc7f89305101a43890aa1de48 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 11 Jun 2025 00:51:42 +0300 Subject: [PATCH 16/47] fix night shadows --- res/shaders/lib/shadows.glsl | 7 +++++-- src/graphics/render/WorldRenderer.cpp | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index aa1ca09b..6056427f 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -3,6 +3,7 @@ uniform sampler2DShadow u_shadows[2]; uniform mat4 u_shadowsMatrix[2]; +uniform float u_dayTime; uniform int u_shadowsRes; @@ -22,7 +23,7 @@ float calc_shadow() { shadow = 0.0; // TODO: optimize - if (dot(a_realnormal, u_sunDir) < 0.0) { + if (dot(a_realnormal, u_sunDir) < 0.0 || true) { if (a_distance > 128) { for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { @@ -48,7 +49,9 @@ float calc_shadow() { } shadow /= 25; } - shadow = shadow * 0.5 + 0.5; + float s = abs(cos(u_dayTime * 3.141592 * 2.0)); + s = pow(s, 0.7); + shadow = mix(0.5, shadow * 0.5 + 0.5, s); } else { shadow = 0.5; } diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index e9a0d4fe..dce8caec 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -370,7 +370,12 @@ void WorldRenderer::generateShadowsMap( shadowCamera.perspective = false; shadowCamera.setAspectRatio(1.0f); - float sunAngle = glm::radians(fmod(90.0f - worldInfo.daytime * 360.0f, 180.0f)); + float t = worldInfo.daytime - 0.25f; + if (t < 0.0f) { + t += 1.0f; + } + t = fmod(t, 0.5f); + float sunAngle = glm::radians(90.0f - (t + 0.25f) * 360.0f); shadowCamera.rotate( sunAngle, glm::radians(-45.0f), From 9cc59c8848513e231d92ef2bdbd21255b88ae0ef Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 11 Jun 2025 19:44:33 +0300 Subject: [PATCH 17/47] refactor shadows.glsl --- res/shaders/lib/shadows.glsl | 75 +++++++++++++----------------------- 1 file changed, 26 insertions(+), 49 deletions(-) diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index 6056427f..00ba8197 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -4,59 +4,36 @@ uniform sampler2DShadow u_shadows[2]; uniform mat4 u_shadowsMatrix[2]; uniform float u_dayTime; - uniform int u_shadowsRes; float calc_shadow() { - float shadow = 1.0; - if (u_enableShadows) { - vec4 mpos = u_shadowsMatrix[0] * vec4(a_modelpos.xyz + a_realnormal * 0.04, 1.0); - vec3 projCoords = mpos.xyz / mpos.w; - projCoords = projCoords * 0.5 + 0.5; - projCoords.z -= 0.0001; - - vec4 wmpos = u_shadowsMatrix[1] * vec4(a_modelpos.xyz + a_realnormal * 0.2, 1.0); - vec3 wprojCoords = wmpos.xyz / wmpos.w; - wprojCoords = wprojCoords * 0.5 + 0.5; - wprojCoords.z -= 0.0001; - - shadow = 0.0; - - // TODO: optimize - if (dot(a_realnormal, u_sunDir) < 0.0 || true) { - if (a_distance > 128) { - for (int y = -1; y <= 1; y++) { - for (int x = -1; x <= 1; x++) { - shadow += texture( - u_shadows[1], - wprojCoords.xyz + - vec3(x, y, -(abs(x) + abs(y))) / - u_shadowsRes - ); - } - } - shadow /= 9; - } else { - for (int y = -2; y <= 2; y++) { - for (int x = -2; x <= 2; x++) { - shadow += texture( - u_shadows[0], - projCoords.xyz + - vec3(x, y, -(abs(x) + abs(y))) / - u_shadowsRes * 1.0 - ); - } - } - shadow /= 25; - } - float s = abs(cos(u_dayTime * 3.141592 * 2.0)); - s = pow(s, 0.7); - shadow = mix(0.5, shadow * 0.5 + 0.5, s); - } else { - shadow = 0.5; - } + if (!u_enableShadows) { + return 1.0; } - return shadow; + + float step = 1.0 / float(u_shadowsRes); + float s = pow(abs(cos(u_dayTime * 6.283185)), 0.7); // 2*PI precomputed + vec3 normalOffset = a_realnormal * (a_distance > 128.0 ? 0.2 : 0.04); + int shadowIdx = a_distance > 128.0 ? 1 : 0; + + vec4 mpos = u_shadowsMatrix[shadowIdx] * vec4(a_modelpos.xyz + normalOffset, 1.0); + vec3 projCoords = mpos.xyz / mpos.w; + projCoords = projCoords * 0.5 + 0.5; + projCoords.z -= 0.0001; + + float shadow = 0.0; + if (dot(a_realnormal, u_sunDir) < 0.0) { + for (int y = -1; y <= 1; y++) { + for (int x = -1; x <= 1; x++) { + vec3 offset = vec3(x, y, -(abs(x) + abs(y))) * step; + shadow += texture(u_shadows[shadowIdx], projCoords + offset); + } + } + shadow /= 9.0; + } else { + shadow = 0.5; + } + return 0.5 * (1.0 + s * shadow); } #endif // SHADOWS_GLSL_ From 02a91e0b72fc821ac3370cf4c1798cf70ea7fd65 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 13 Jun 2025 23:28:16 +0300 Subject: [PATCH 18/47] add 'advanced' post-effect load configuration --- res/preload.json | 5 ++++- res/shaders/lib/shadows.glsl | 2 +- src/assets/AssetsLoader.cpp | 16 ++++++++++------ src/assets/AssetsLoader.hpp | 12 ++++++++---- src/assets/assetload_funcs.cpp | 7 ++++++- src/graphics/core/PostEffect.cpp | 3 ++- src/graphics/core/PostEffect.hpp | 6 ++++++ src/graphics/core/PostProcessing.cpp | 8 +++++++- src/graphics/core/PostProcessing.hpp | 1 - src/graphics/render/WorldRenderer.cpp | 10 +++++----- 10 files changed, 49 insertions(+), 21 deletions(-) diff --git a/res/preload.json b/res/preload.json index e10d1b68..e3069eef 100644 --- a/res/preload.json +++ b/res/preload.json @@ -11,7 +11,10 @@ ], "post-effects": [ "default", - "ssao" + { + "name": "ssao", + "advanced": true + } ], "textures": [ "gui/menubg", diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index 00ba8197..59d874e3 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -12,7 +12,7 @@ float calc_shadow() { } float step = 1.0 / float(u_shadowsRes); - float s = pow(abs(cos(u_dayTime * 6.283185)), 0.7); // 2*PI precomputed + float s = pow(abs(cos(u_dayTime * 6.283185)), 0.5); // 2*PI precomputed vec3 normalOffset = a_realnormal * (a_distance > 128.0 ? 0.2 : 0.04); int shadowIdx = a_distance > 128.0 ? 1 : 0; diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 80c1186d..fd399ecd 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -147,14 +147,12 @@ void AssetsLoader::processPreload( add(tag, path, name); return; } + std::shared_ptr config = nullptr; map.at("path").get(path); switch (tag) { case AssetType::SOUND: { bool keepPCM = false; - add(tag, - path, - name, - std::make_shared(map.at("keep-pcm").get(keepPCM))); + config = std::make_shared(map.at("keep-pcm").get(keepPCM)); break; } case AssetType::ATLAS: { @@ -164,13 +162,19 @@ void AssetsLoader::processPreload( if (typeName == "separate") { type = AtlasType::SEPARATE; } - add(tag, path, name, std::make_shared(type)); + config = std::make_shared(type); + break; + } + case AssetType::POST_EFFECT: { + bool advanced = false; + map.at("advanced").get(advanced); + config = std::make_shared(advanced); break; } default: - add(tag, path, name); break; } + add(tag, path, name, std::move(config)); } void AssetsLoader::processPreloadList(AssetType tag, const dv::value& list) { diff --git a/src/assets/AssetsLoader.hpp b/src/assets/AssetsLoader.hpp index e3c137ba..e35a78ce 100644 --- a/src/assets/AssetsLoader.hpp +++ b/src/assets/AssetsLoader.hpp @@ -40,8 +40,7 @@ struct LayoutCfg : AssetCfg { struct SoundCfg : AssetCfg { bool keepPCM; - SoundCfg(bool keepPCM) : keepPCM(keepPCM) { - } + SoundCfg(bool keepPCM) : keepPCM(keepPCM) {} }; enum class AtlasType { @@ -51,8 +50,13 @@ enum class AtlasType { struct AtlasCfg : AssetCfg { AtlasType type; - AtlasCfg(AtlasType type) : type(type) { - } + AtlasCfg(AtlasType type) : type(type) {} +}; + +struct PostEffectCfg : AssetCfg { + bool advanced; + + PostEffectCfg(bool advanced) : advanced(advanced) {} }; using aloader_func = std::function< diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index db77e354..4bd30416 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -132,8 +132,13 @@ assetload::postfunc assetload::posteffect( vertexSource, fragmentSource ); + bool advanced = false; + if (settings) { + advanced = dynamic_cast(settings.get())->advanced; + } assets->store( - std::make_shared(std::move(program), params), name + std::make_shared(advanced, std::move(program), params), + name ); }; } diff --git a/src/graphics/core/PostEffect.cpp b/src/graphics/core/PostEffect.cpp index d634c636..584a9b43 100644 --- a/src/graphics/core/PostEffect.cpp +++ b/src/graphics/core/PostEffect.cpp @@ -10,10 +10,11 @@ PostEffect::Param::Param(Type type, Value defValue) } PostEffect::PostEffect( + bool advanced, std::shared_ptr shader, std::unordered_map params ) - : shader(std::move(shader)), params(std::move(params)) { + : advanced(advanced), shader(std::move(shader)), params(std::move(params)) { } Shader& PostEffect::use() { diff --git a/src/graphics/core/PostEffect.hpp b/src/graphics/core/PostEffect.hpp index 9c4bd84f..3448e05c 100644 --- a/src/graphics/core/PostEffect.hpp +++ b/src/graphics/core/PostEffect.hpp @@ -35,6 +35,7 @@ public: }; PostEffect( + bool advanced, std::shared_ptr shader, std::unordered_map params ); @@ -48,10 +49,15 @@ public: void setParam(const std::string& name, const dv::value& value); + bool isAdvanced() const { + return advanced; + } + bool isActive() { return intensity > 1e-4f; } private: + bool advanced = false; std::shared_ptr shader; std::unordered_map params; float intensity = 0.0f; diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index acebd519..b5922f72 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -97,6 +97,7 @@ void PostProcessing::configureEffect( ) { const auto& viewport = context.getViewport(); + bool ssaoConfigured = false; if (!ssaoConfigured) { for (unsigned int i = 0; i < 64; ++i) { auto name = "u_ssaoSamples["+ std::to_string(i) + "]"; @@ -129,7 +130,9 @@ void PostProcessing::render( } int totalPasses = 0; for (const auto& effect : effectSlots) { - totalPasses += (effect != nullptr && effect->isActive()); + totalPasses += + (effect != nullptr && effect->isActive() && + !(effect->isAdvanced() && gbuffer == nullptr)); } const auto& vp = context.getViewport(); @@ -163,6 +166,9 @@ void PostProcessing::render( if (effect == nullptr || !effect->isActive()) { continue; } + if (effect->isAdvanced() && gbuffer == nullptr) { + continue; + } auto& shader = effect->use(); configureEffect(context, shader, timer, camera, shadowMap); diff --git a/src/graphics/core/PostProcessing.hpp b/src/graphics/core/PostProcessing.hpp index 41597a4f..51e23ece 100644 --- a/src/graphics/core/PostProcessing.hpp +++ b/src/graphics/core/PostProcessing.hpp @@ -76,5 +76,4 @@ private: std::vector ssaoKernel; uint noiseTexture; - bool ssaoConfigured = false; }; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index dce8caec..d742ec3f 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -366,7 +366,7 @@ void WorldRenderer::generateShadowsMap( glm::vec3 basePos = glm::floor(camera.position); shadowCamera = Camera(basePos, shadowMapSize); shadowCamera.near = 0.1f; - shadowCamera.far = 800.0f; + shadowCamera.far = 1000.0f; shadowCamera.perspective = false; shadowCamera.setAspectRatio(1.0f); @@ -375,7 +375,7 @@ void WorldRenderer::generateShadowsMap( t += 1.0f; } t = fmod(t, 0.5f); - float sunAngle = glm::radians(90.0f - (t + 0.25f) * 360.0f); + float sunAngle = glm::radians(90.0f - (((int)(t*1000)) / 1000.0f + 0.25f) * 360.0f); shadowCamera.rotate( sunAngle, glm::radians(-45.0f), @@ -383,7 +383,7 @@ void WorldRenderer::generateShadowsMap( ); shadowCamera.updateVectors(); - shadowCamera.position -= shadowCamera.front * 200.0f; + shadowCamera.position -= shadowCamera.front * 300.0f; shadowCamera.position += shadowCamera.up * 10.0f; shadowCamera.position += camera.front * 100.0f; @@ -393,7 +393,7 @@ void WorldRenderer::generateShadowsMap( auto min = view * glm::vec4(currentPos - (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); auto max = view * glm::vec4(currentPos + (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); - shadowCamera.setProjection(glm::ortho(min.x, max.x, min.y, max.y, 0.1f, 800.0f)); + shadowCamera.setProjection(glm::ortho(min.x, max.x, min.y, max.y, 0.1f, 1000.0f)); { frustumCulling->update(shadowCamera.getProjView()); @@ -456,7 +456,7 @@ void WorldRenderer::draw( chunks->update(); static int frameid = 0; - if (shadows && frameid % 3 == 0) { + if (shadows) { if (frameid % 2 == 0) { generateShadowsMap(camera, pctx, *shadowMap, shadowCamera, 1.0f); } else { From 436a89b0665f48733fcb57f0831db25835253f8f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 14 Jun 2025 20:06:05 +0300 Subject: [PATCH 19/47] feat: post-effects array parameters & add gfx.posteffects.set_array & make shadows opacity depending on clouds opacity --- res/scripts/hud.lua | 26 +++++- res/shaders/effects/ssao.glsl | 19 ++-- res/shaders/lib/shadows.glsl | 21 +++-- src/coders/GLSLExtension.cpp | 22 ++++- src/graphics/core/PostEffect.cpp | 89 +++++++++++++++---- src/graphics/core/PostEffect.hpp | 13 ++- src/graphics/core/PostProcessing.cpp | 28 +----- src/graphics/core/PostProcessing.hpp | 3 +- src/graphics/core/Shader.cpp | 19 ++++ src/graphics/core/Shader.hpp | 6 ++ src/graphics/render/WorldRenderer.cpp | 16 ++-- .../scripting/lua/libs/libposteffects.cpp | 17 ++++ src/logic/scripting/lua/lua_extensions.cpp | 16 ++++ src/world/Weather.hpp | 6 ++ 14 files changed, 223 insertions(+), 78 deletions(-) diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua index 79fe0e42..e8cc137d 100644 --- a/res/scripts/hud.lua +++ b/res/scripts/hud.lua @@ -1,3 +1,25 @@ +local function configure_SSAO() + local slot = gfx.posteffects.index("core:default") + gfx.posteffects.set_effect(slot, "ssao") + gfx.posteffects.set_intensity(slot, 1.0) + + -- Generating random SSAO samples + local buffer = Bytearray(0) + for i = 0, 63 do + local x = math.random() * 2.0 - 1.0 + local y = math.random() * 2.0 - 1.0 + local z = math.random() + local len = math.sqrt(x * x + y * y + z * z) + if len > 0 then + x = x / len + y = y / len + z = z / len + end + Bytearray.append(buffer, byteutil.pack("fff", x, y, z)) + end + gfx.posteffects.set_array(slot, "u_ssaoSamples", Bytearray_as_string(buffer)) +end + function on_hud_open() input.add_callback("player.pick", function () if hud.is_paused() or hud.is_inventory_open() then @@ -55,8 +77,4 @@ function on_hud_open() player.set_vel(pid, 0, 1, 0) end end) - - local slot = gfx.posteffects.index("core:default") - gfx.posteffects.set_effect(slot, "ssao") - gfx.posteffects.set_intensity(slot, 1.0) end diff --git a/res/shaders/effects/ssao.glsl b/res/shaders/effects/ssao.glsl index f0894b49..3446ecdb 100644 --- a/res/shaders/effects/ssao.glsl +++ b/res/shaders/effects/ssao.glsl @@ -1,8 +1,7 @@ -uniform vec3 u_ssaoSamples[64]; - -int kernelSize = 16; -float radius = 0.25; -float bias = 0.025; +#param vec3 u_ssaoSamples[64] +#param int u_kernelSize = 16 +#param float u_radius = 0.25 +#param float u_bias = 0.025 vec4 effect() { vec2 noiseScale = u_screenSize / 4.0; @@ -17,9 +16,9 @@ vec4 effect() { mat3 tbn = mat3(tangent, bitangent, normal); float occlusion = 0.0; - for (int i = 0; i < kernelSize; i++) { + for (int i = 0; i < u_kernelSize; i++) { vec3 samplePos = tbn * u_ssaoSamples[i]; - samplePos = position + samplePos * radius; + samplePos = position + samplePos * u_radius; vec4 offset = vec4(samplePos, 1.0); offset = u_projection * offset; @@ -27,10 +26,10 @@ vec4 effect() { 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; + float rangeCheck = smoothstep(0.0, 1.0, u_radius / abs(position.z - sampleDepth)); + occlusion += (sampleDepth >= samplePos.z + u_bias ? 1.0 : 0.0) * rangeCheck; } - occlusion = min(1.0, 1.05 - (occlusion / kernelSize)); + occlusion = min(1.0, 1.05 - (occlusion / u_kernelSize)); float z = -position.z * 0.02; z = max(0.0, 1.0 - z); diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index 59d874e3..e21afc22 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -1,10 +1,14 @@ #ifndef SHADOWS_GLSL_ #define SHADOWS_GLSL_ +#include + uniform sampler2DShadow u_shadows[2]; uniform mat4 u_shadowsMatrix[2]; uniform float u_dayTime; uniform int u_shadowsRes; +uniform float u_shadowsOpacity; +uniform float u_shadowsSoftness; float calc_shadow() { if (!u_enableShadows) { @@ -12,24 +16,25 @@ float calc_shadow() { } float step = 1.0 / float(u_shadowsRes); - float s = pow(abs(cos(u_dayTime * 6.283185)), 0.5); // 2*PI precomputed - vec3 normalOffset = a_realnormal * (a_distance > 128.0 ? 0.2 : 0.04); - int shadowIdx = a_distance > 128.0 ? 1 : 0; + float s = pow(abs(cos(u_dayTime * PI2)), 0.25) * u_shadowsOpacity; + vec3 normalOffset = a_realnormal * (a_distance > 64.0 ? 0.2 : 0.04); + int shadowIdx = a_distance > 64.0 ? 1 : 0; vec4 mpos = u_shadowsMatrix[shadowIdx] * vec4(a_modelpos.xyz + normalOffset, 1.0); vec3 projCoords = mpos.xyz / mpos.w; projCoords = projCoords * 0.5 + 0.5; - projCoords.z -= 0.0001; + projCoords.z -= 0.00001; float shadow = 0.0; if (dot(a_realnormal, u_sunDir) < 0.0) { - for (int y = -1; y <= 1; y++) { - for (int x = -1; x <= 1; x++) { - vec3 offset = vec3(x, y, -(abs(x) + abs(y))) * step; + // 5x5 kernel + for (int y = -2; y <= 2; y++) { + for (int x = -2; x <= 2; x++) { + vec3 offset = vec3(x, y, -(abs(x) + abs(y)) * 0.1) * step * 2.0 * u_shadowsSoftness; shadow += texture(u_shadows[shadowIdx], projCoords + offset); } } - shadow /= 9.0; + shadow /= 25.0; } else { shadow = 0.5; } diff --git a/src/coders/GLSLExtension.cpp b/src/coders/GLSLExtension.cpp index 47948bd9..f6543092 100644 --- a/src/coders/GLSLExtension.cpp +++ b/src/coders/GLSLExtension.cpp @@ -98,6 +98,8 @@ inline void source_line(std::stringstream& ss, uint linenum) { static Value default_value_for(Type type) { switch (type) { + case Type::INT: + return 0; case Type::FLOAT: return 0.0f; case Type::VEC2: @@ -183,6 +185,8 @@ public: Value parseDefaultValue(Type type, const std::string& name) { switch (type) { + case Type::INT: + return static_cast(parseNumber(1).asInteger()); case Type::FLOAT: return static_cast(parseNumber(1).asNumber()); case Type::VEC2: @@ -212,8 +216,22 @@ public: if (params.find(paramName) != params.end()) { throw error("duplicating param " + util::quote(paramName)); } + skipWhitespace(false); - ss << "uniform " << typeName << " " << paramName << ";\n"; + int start = pos; + + ss << "uniform " << typeName << " " << paramName; + + bool array = false; + if (peekNoJump() == '[') { + skip(1); + array = true; + readUntil(']'); + skip(1); + ss << source.substr(start, pos - start + 1); + } + + ss << ";\n"; auto defValue = default_value_for(type); // Parse default value @@ -225,7 +243,7 @@ public: skipLine(); - params[paramName] = PostEffect::Param(type, std::move(defValue)); + params[paramName] = PostEffect::Param(type, std::move(defValue), array); return false; } diff --git a/src/graphics/core/PostEffect.cpp b/src/graphics/core/PostEffect.cpp index 584a9b43..47f2ac9f 100644 --- a/src/graphics/core/PostEffect.cpp +++ b/src/graphics/core/PostEffect.cpp @@ -2,11 +2,14 @@ #include "Shader.hpp" #include "data/dv_util.hpp" +#include "debug/Logger.hpp" + +static debug::Logger logger("post-effect"); PostEffect::Param::Param() : type(Type::FLOAT) {} -PostEffect::Param::Param(Type type, Value defValue) - : type(type), defValue(defValue), value(defValue) { +PostEffect::Param::Param(Type type, Value defValue, bool array) + : type(type), defValue(defValue), value(defValue), array(array) { } PostEffect::PostEffect( @@ -24,21 +27,53 @@ Shader& PostEffect::use() { if (!param.dirty) { continue; } - switch (param.type) { - case Param::Type::FLOAT: - shader->uniform1f(name, std::get(param.value)); - break; - case Param::Type::VEC2: - shader->uniform2f(name, std::get(param.value)); - break; - case Param::Type::VEC3: - shader->uniform3f(name, std::get(param.value)); - break; - case Param::Type::VEC4: - shader->uniform4f(name, std::get(param.value)); - break; - default: - assert(false); + if (param.array) { + const auto& found = arrayValues.find(name); + if (found == arrayValues.end()) { + continue; + } + size_t size = found->second.size(); + auto ibuffer = reinterpret_cast(found->second.data()); + auto fbuffer = reinterpret_cast(found->second.data()); + switch (param.type) { + case Param::Type::INT: + shader->uniform1v(name, size / sizeof(int), ibuffer); + break; + case Param::Type::FLOAT: + shader->uniform1v(name, size / sizeof(float), fbuffer); + break; + case Param::Type::VEC2: + shader->uniform2v(name, size / sizeof(glm::vec2), fbuffer); + break; + case Param::Type::VEC3: + shader->uniform3v(name, size / sizeof(glm::vec3), fbuffer); + break; + case Param::Type::VEC4: + shader->uniform4v(name, size / sizeof(glm::vec4), fbuffer); + break; + default: + assert(false); + } + } else { + switch (param.type) { + case Param::Type::INT: + shader->uniform1i(name, std::get(param.value)); + break; + case Param::Type::FLOAT: + shader->uniform1f(name, std::get(param.value)); + break; + case Param::Type::VEC2: + shader->uniform2f(name, std::get(param.value)); + break; + case Param::Type::VEC3: + shader->uniform3f(name, std::get(param.value)); + break; + case Param::Type::VEC4: + shader->uniform4f(name, std::get(param.value)); + break; + default: + assert(false); + } } param.dirty = false; } @@ -67,6 +102,9 @@ void PostEffect::setParam(const std::string& name, const dv::value& value) { } auto& param = found->second; switch (param.type) { + case Param::Type::INT: + param.value = static_cast(value.asInteger()); + break; case Param::Type::FLOAT: param.value = static_cast(value.asNumber()); break; @@ -82,3 +120,20 @@ void PostEffect::setParam(const std::string& name, const dv::value& value) { } param.dirty = true; } + +void PostEffect::setArray(const std::string& name, std::vector&& values) { + const auto& found = params.find(name); + if (found == params.end()) { + return; + } + auto& param = found->second; + if (!param.array) { + logger.warning() << "set_array is used on non-array effect parameter"; + if (!values.empty()) { + setParam(name, values[0]); + } + return; + } + param.dirty = true; + arrayValues[name] = std::move(values); +} diff --git a/src/graphics/core/PostEffect.hpp b/src/graphics/core/PostEffect.hpp index 3448e05c..6dac6748 100644 --- a/src/graphics/core/PostEffect.hpp +++ b/src/graphics/core/PostEffect.hpp @@ -1,11 +1,13 @@ #pragma once +#include #include #include #include #include #include +#include "typedefs.hpp" #include "data/dv_fwd.hpp" #include "util/EnumMetadata.hpp" @@ -14,24 +16,26 @@ class Shader; class PostEffect { public: struct Param { - enum class Type { FLOAT, VEC2, VEC3, VEC4 }; + enum class Type { INT, FLOAT, VEC2, VEC3, VEC4 }; VC_ENUM_METADATA(Type) + {"int", Type::INT}, {"float", Type::FLOAT}, {"vec2", Type::VEC2}, {"vec3", Type::VEC3}, {"vec4", Type::VEC4}, VC_ENUM_END - using Value = std::variant; + using Value = std::variant; Type type; Value defValue; Value value; + bool array = false; bool dirty = true; Param(); - Param(Type type, Value defValue); + Param(Type type, Value defValue, bool array); }; PostEffect( @@ -49,6 +53,8 @@ public: void setParam(const std::string& name, const dv::value& value); + void setArray(const std::string& name, std::vector&& values); + bool isAdvanced() const { return advanced; } @@ -60,5 +66,6 @@ private: bool advanced = false; std::shared_ptr shader; std::unordered_map params; + std::unordered_map> arrayValues; float intensity = 0.0f; }; diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index b5922f72..13244c89 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -43,20 +43,6 @@ PostProcessing::PostProcessing(size_t effectSlotsCount) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, 0); - - std::uniform_real_distribution randomFloats(0.0, 1.0); - std::default_random_engine generator; - for (unsigned int i = 0; i < 64; ++i) - { - glm::vec3 sample( - randomFloats(generator) * 2.0 - 1.0, - randomFloats(generator) * 2.0 - 1.0, - randomFloats(generator) - ); - sample = glm::normalize(sample); - sample *= randomFloats(generator); - ssaoKernel.push_back(sample); - } } PostProcessing::~PostProcessing() = default; @@ -90,21 +76,13 @@ void PostProcessing::refreshFbos(uint width, uint height) { void PostProcessing::configureEffect( const DrawContext& context, + PostEffect& effect, Shader& shader, float timer, const Camera& camera, uint shadowMap ) { const auto& viewport = context.getViewport(); - - bool ssaoConfigured = false; - 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); @@ -156,7 +134,7 @@ void PostProcessing::render( if (totalPasses == 0) { auto& effect = assets.require("default"); auto& shader = effect.use(); - configureEffect(context, shader, timer, camera, shadowMap); + configureEffect(context, effect, shader, timer, camera, shadowMap); quadMesh->draw(); return; } @@ -170,7 +148,7 @@ void PostProcessing::render( continue; } auto& shader = effect->use(); - configureEffect(context, shader, timer, camera, shadowMap); + configureEffect(context, *effect, shader, timer, camera, shadowMap); if (currentPass > 1) { fbo->getTexture()->bind(); diff --git a/src/graphics/core/PostProcessing.hpp b/src/graphics/core/PostProcessing.hpp index 51e23ece..dc0779ed 100644 --- a/src/graphics/core/PostProcessing.hpp +++ b/src/graphics/core/PostProcessing.hpp @@ -58,6 +58,7 @@ public: private: void configureEffect( const DrawContext& context, + PostEffect& effect, Shader& shader, float timer, const Camera& camera, @@ -73,7 +74,5 @@ private: std::unique_ptr> quadMesh; std::vector> effectSlots; std::unique_ptr gbuffer; - - std::vector ssaoKernel; uint noiseTexture; }; diff --git a/src/graphics/core/Shader.cpp b/src/graphics/core/Shader.cpp index 626d747b..df02a5c0 100644 --- a/src/graphics/core/Shader.cpp +++ b/src/graphics/core/Shader.cpp @@ -76,6 +76,25 @@ void Shader::uniform4f(const std::string& name, const glm::vec4& xyzw) { glUniform4f(getUniformLocation(name), xyzw.x, xyzw.y, xyzw.z, xyzw.w); } +void Shader::uniform1v(const std::string& name, int length, const int* v) { + glUniform1iv(getUniformLocation(name), length, v); +} + +void Shader::uniform1v(const std::string& name, int length, const float* v) { + glUniform1fv(getUniformLocation(name), length, v); +} + +void Shader::uniform2v(const std::string& name, int length, const float* v) { + glUniform2fv(getUniformLocation(name), length, v); +} + +void Shader::uniform3v(const std::string& name, int length, const float* v) { + glUniform3fv(getUniformLocation(name), length, v); +} + +void Shader::uniform4v(const std::string& name, int length, const float* v) { + glUniform4fv(getUniformLocation(name), length, v); +} inline auto shader_deleter = [](GLuint* shader) { glDeleteShader(*shader); diff --git a/src/graphics/core/Shader.hpp b/src/graphics/core/Shader.hpp index 18a14da7..d50ccb46 100644 --- a/src/graphics/core/Shader.hpp +++ b/src/graphics/core/Shader.hpp @@ -32,6 +32,12 @@ public: void uniform3f(const std::string& name, const glm::vec3& xyz); void uniform4f(const std::string& name, const glm::vec4& xyzw); + void uniform1v(const std::string& name, int length, const int* v); + void uniform1v(const std::string& name, int length, const float* v); + void uniform2v(const std::string& name, int length, const float* v); + void uniform3v(const std::string& name, int length, const float* v); + void uniform4v(const std::string& name, int length, const float* v); + /// @brief Create shader program using vertex and fragment shaders source. /// @param vertexFile vertex shader file name /// @param fragmentFile fragment shader file name diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index d742ec3f..193cb2d9 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -131,10 +131,14 @@ void WorldRenderer::setupWorldShader( shader.uniform1i("u_enableShadows", shadows); if (shadows) { + const auto& worldInfo = level.getWorld()->getInfo(); + float cloudsIntensity = glm::max(worldInfo.fog, weather.clouds()); shader.uniformMatrix("u_shadowsMatrix[0]", shadowCamera.getProjView()); shader.uniformMatrix("u_shadowsMatrix[1]", wideShadowCamera.getProjView()); shader.uniform3f("u_sunDir", shadowCamera.front); shader.uniform1i("u_shadowsRes", shadowMap->getResolution()); + shader.uniform1f("u_shadowsOpacity", 1.0f - cloudsIntensity); // TODO: make it configurable + shader.uniform1f("u_shadowsSoftness", 1.0f + cloudsIntensity * 4); // TODO: make it configurable glActiveTexture(GL_TEXTURE4); shader.uniform1i("u_shadows[0]", 4); @@ -359,7 +363,7 @@ void WorldRenderer::generateShadowsMap( const auto& settings = engine.getSettings(); int resolution = shadowMap.getResolution(); float shadowMapScale = - 0.2f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) * + 0.16f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) * scale; float shadowMapSize = resolution * shadowMapScale; @@ -383,9 +387,9 @@ void WorldRenderer::generateShadowsMap( ); shadowCamera.updateVectors(); - shadowCamera.position -= shadowCamera.front * 300.0f; - shadowCamera.position += shadowCamera.up * 10.0f; - shadowCamera.position += camera.front * 100.0f; + shadowCamera.position -= shadowCamera.front * 500.0f; + shadowCamera.position += shadowCamera.up * 0.0f; + shadowCamera.position += camera.front * 0.0f; auto view = shadowCamera.getView(); @@ -445,9 +449,7 @@ void WorldRenderer::draw( const auto& worldInfo = world->getInfo(); - float sqrtT = glm::sqrt(weather.t); - float clouds = weather.b.clouds * sqrtT + - weather.a.clouds * (1.0f - sqrtT); + float clouds = weather.clouds(); clouds = glm::max(worldInfo.fog, clouds); float mie = 1.0f + glm::max(worldInfo.fog, clouds * 0.5f) * 2.0f; diff --git a/src/logic/scripting/lua/libs/libposteffects.cpp b/src/logic/scripting/lua/libs/libposteffects.cpp index ccdb34aa..5e3284bf 100644 --- a/src/logic/scripting/lua/libs/libposteffects.cpp +++ b/src/logic/scripting/lua/libs/libposteffects.cpp @@ -57,6 +57,22 @@ static int l_set_params(lua::State* L) { return 0; } +static int l_set_array(lua::State* L) { + size_t index = static_cast(lua::tointeger(L, 1)); + auto key = lua::require_string(L, 2); + auto data = lua::require_lstring(L, 3); + auto effect = post_processing->getEffect(index); + if (effect == nullptr) { + return 0; + } + std::vector buffer( + reinterpret_cast(data.begin()), + reinterpret_cast(data.end()) + ); + effect->setArray(key, std::move(buffer)); + return 0; +} + const luaL_Reg posteffectslib[] = { {"index", lua::wrap}, {"set_effect", lua::wrap}, @@ -64,5 +80,6 @@ const luaL_Reg posteffectslib[] = { {"set_intensity", lua::wrap}, {"is_active", lua::wrap}, {"set_params", lua::wrap}, + {"set_array", lua::wrap}, {NULL, NULL} }; diff --git a/src/logic/scripting/lua/lua_extensions.cpp b/src/logic/scripting/lua/lua_extensions.cpp index 399b6095..b9c25fc6 100644 --- a/src/logic/scripting/lua/lua_extensions.cpp +++ b/src/logic/scripting/lua/lua_extensions.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "libs/api_lua.hpp" #include "debug/Logger.hpp" @@ -149,6 +150,15 @@ int l_debug_print(lua::State* L) { return 0; } +namespace { + std::normal_distribution randomFloats(0.0f, 1.0f); + std::default_random_engine generator; +} + +static int l_math_normal_random(lua::State* L) { + return lua::pushnumber(L, randomFloats(generator)); +} + void initialize_libs_extends(lua::State* L) { if (lua::getglobal(L, "debug")) { lua::pushcfunction(L, lua::wrap); @@ -163,6 +173,12 @@ void initialize_libs_extends(lua::State* L) { lua::pushcfunction(L, lua::wrap); lua::setfield(L, "print"); + lua::pop(L); + } + if (lua::getglobal(L, "math")) { + lua::pushcfunction(L, lua::wrap); + lua::setfield(L, "normal_random"); + lua::pop(L); } } diff --git a/src/world/Weather.hpp b/src/world/Weather.hpp index fde642b7..6d8af0bb 100644 --- a/src/world/Weather.hpp +++ b/src/world/Weather.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include "presets/WeatherPreset.hpp" @@ -45,6 +46,11 @@ struct Weather : Serializable { return b.thunderRate * t + a.thunderRate * (1.0f - t); } + float clouds() const { + float sqrtT = glm::sqrt(t); + return b.clouds * sqrtT + a.clouds * (1.0f - sqrtT); + } + dv::value serialize() const override; void deserialize(const dv::value& src) override; }; From 2ad076bec326af0177a9c8d7863fedf6cbe74556 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 14 Jun 2025 20:42:43 +0300 Subject: [PATCH 20/47] fix gbuffer attachment wrapping --- src/graphics/core/GBuffer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index 574f7a9b..19f6c360 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -45,6 +45,8 @@ void GBuffer::createPositionsBuffer() { ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positionsBuffer, 0 ); @@ -66,6 +68,8 @@ void GBuffer::createNormalsBuffer() { ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normalsBuffer, 0 ); From e849d5e9b77b2ff32ae56f25072ea7cebf579bc3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 14 Jun 2025 22:43:18 +0300 Subject: [PATCH 21/47] feat: deferred lighting (WIP) --- res/preload.json | 4 ++ res/scripts/hud.lua | 6 +- res/shaders/effect.glslf | 1 + res/shaders/effects/default.glsl | 1 - res/shaders/effects/deferred_lighting.glsl | 11 ++++ res/shaders/effects/ssao.glsl | 9 ++- src/graphics/core/GBuffer.cpp | 57 ++++++++++++++++++- src/graphics/core/GBuffer.hpp | 5 ++ src/graphics/core/PostProcessing.cpp | 18 +++++- .../scripting/lua/libs/libposteffects.cpp | 5 +- 10 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 res/shaders/effects/deferred_lighting.glsl diff --git a/res/preload.json b/res/preload.json index e3069eef..eb41f40d 100644 --- a/res/preload.json +++ b/res/preload.json @@ -14,6 +14,10 @@ { "name": "ssao", "advanced": true + }, + { + "name": "deferred_lighting", + "advanced": true } ], "textures": [ diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua index e8cc137d..cfeaad66 100644 --- a/res/scripts/hud.lua +++ b/res/scripts/hud.lua @@ -1,14 +1,14 @@ local function configure_SSAO() local slot = gfx.posteffects.index("core:default") gfx.posteffects.set_effect(slot, "ssao") - gfx.posteffects.set_intensity(slot, 1.0) + -- gfx.posteffects.set_intensity(slot, 1.0) -- Generating random SSAO samples local buffer = Bytearray(0) for i = 0, 63 do local x = math.random() * 2.0 - 1.0 local y = math.random() * 2.0 - 1.0 - local z = math.random() + local z = math.random() * 2.0 local len = math.sqrt(x * x + y * y + z * z) if len > 0 then x = x / len @@ -77,4 +77,6 @@ function on_hud_open() player.set_vel(pid, 0, 1, 0) end end) + + configure_SSAO() end diff --git a/res/shaders/effect.glslf b/res/shaders/effect.glslf index 32f69048..792b6c2b 100644 --- a/res/shaders/effect.glslf +++ b/res/shaders/effect.glslf @@ -5,6 +5,7 @@ uniform sampler2D u_screen; uniform sampler2D u_position; uniform sampler2D u_normal; uniform sampler2D u_noise; +uniform sampler2D u_ssao; uniform sampler2D u_shadows; uniform ivec2 u_screenSize; diff --git a/res/shaders/effects/default.glsl b/res/shaders/effects/default.glsl index f7a94851..c2f9effa 100644 --- a/res/shaders/effects/default.glsl +++ b/res/shaders/effects/default.glsl @@ -1,4 +1,3 @@ vec4 effect() { - //return vec4(vec3(pow(texture(u_shadows, v_uv).r, 5.0) * 1000.0), 1.0); return texture(u_screen, v_uv); } diff --git a/res/shaders/effects/deferred_lighting.glsl b/res/shaders/effects/deferred_lighting.glsl new file mode 100644 index 00000000..ea9c32bb --- /dev/null +++ b/res/shaders/effects/deferred_lighting.glsl @@ -0,0 +1,11 @@ +vec4 effect() { + float ssao = 0.0; + for (int y = -1; y <= 1; y++) { + for (int x = -1; x <= 1; x++) { + vec2 offset = vec2(x, y) / u_screenSize; + ssao += texture(u_ssao, v_uv + offset * 2.0).r; + } + } + ssao /= 9.0; + return vec4(texture(u_screen, v_uv).rgb * mix(1.0, ssao, 1.0), 1.0); +} diff --git a/res/shaders/effects/ssao.glsl b/res/shaders/effects/ssao.glsl index 3446ecdb..c021b13a 100644 --- a/res/shaders/effects/ssao.glsl +++ b/res/shaders/effects/ssao.glsl @@ -1,13 +1,12 @@ #param vec3 u_ssaoSamples[64] #param int u_kernelSize = 16 -#param float u_radius = 0.25 -#param float u_bias = 0.025 +#param float u_radius = 0.2 +#param float u_bias = 0.006 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); @@ -31,7 +30,7 @@ vec4 effect() { } occlusion = min(1.0, 1.05 - (occlusion / u_kernelSize)); - float z = -position.z * 0.02; + float z = -position.z * 0.01; z = max(0.0, 1.0 - z); - return vec4(color * mix(1.0, occlusion, z), 1.0); + return vec4(occlusion, 0.0, 0.0, 1.0); } diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index 19f6c360..eabca78b 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -84,6 +84,26 @@ void GBuffer::createDepthBuffer() { ); } +void GBuffer::createSSAOBuffer() { + glGenTextures(1, &ssaoBuffer); + glBindTexture(GL_TEXTURE_2D, ssaoBuffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_R16F, + width, + height, + 0, + GL_RED, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +} + GBuffer::GBuffer(uint width, uint height) : width(width), height(height) { glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -100,7 +120,20 @@ GBuffer::GBuffer(uint width, uint height) : width(width), height(height) { createDepthBuffer(); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - logger.error() << "framebuffer is not complete!"; + logger.error() << "gbuffer is not complete!"; + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glGenFramebuffers(1, &ssaoFbo); + glBindFramebuffer(GL_FRAMEBUFFER, ssaoFbo); + createSSAOBuffer(); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoBuffer, 0 + ); + GLenum ssaoAttachments[1] = {GL_COLOR_ATTACHMENT0}; + glDrawBuffers(1, ssaoAttachments); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + logger.error() << "SSAO framebuffer is not complete!"; } glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -109,8 +142,10 @@ GBuffer::~GBuffer() { glDeleteTextures(1, &colorBuffer); glDeleteTextures(1, &positionsBuffer); glDeleteTextures(1, &normalsBuffer); + glDeleteTextures(1, &ssaoBuffer); glDeleteRenderbuffers(1, &depthBuffer); glDeleteFramebuffers(1, &fbo); + glDeleteFramebuffers(1, &ssaoFbo); } void GBuffer::bind() { @@ -118,6 +153,11 @@ void GBuffer::bind() { glClear(GL_COLOR_BUFFER_BIT); } +void GBuffer::bindSSAO() const { + glBindFramebuffer(GL_FRAMEBUFFER, ssaoFbo); + glClear(GL_COLOR_BUFFER_BIT); +} + void GBuffer::unbind() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -133,6 +173,10 @@ void GBuffer::bindBuffers() const { glBindTexture(GL_TEXTURE_2D, colorBuffer); } +void GBuffer::bindSSAOBuffer() const { + glBindTexture(GL_TEXTURE_2D, ssaoBuffer); +} + void GBuffer::resize(uint width, uint height) { if (this->width == width && this->height == height) { return; @@ -180,6 +224,17 @@ void GBuffer::resize(uint width, uint height) { glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, ssaoFbo); + glBindTexture(GL_TEXTURE_2D, ssaoBuffer); + glTexImage2D( + GL_TEXTURE_2D, 0, GL_R16F, width, height, 0, GL_RED, GL_FLOAT, nullptr + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoBuffer, 0 + ); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } std::unique_ptr GBuffer::toImage() const { diff --git a/src/graphics/core/GBuffer.hpp b/src/graphics/core/GBuffer.hpp index c5e51d4a..7fa66e1a 100644 --- a/src/graphics/core/GBuffer.hpp +++ b/src/graphics/core/GBuffer.hpp @@ -10,9 +10,11 @@ public: ~GBuffer() override; void bind() override; + void bindSSAO() const; void unbind() override; void bindBuffers() const; + void bindSSAOBuffer() const; void resize(uint width, uint height); @@ -29,9 +31,12 @@ private: uint positionsBuffer; uint normalsBuffer; uint depthBuffer; + uint ssaoFbo; + uint ssaoBuffer; void createColorBuffer(); void createPositionsBuffer(); void createNormalsBuffer(); void createDepthBuffer(); + void createSSAOBuffer(); }; diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index 13244c89..4a2608f3 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -88,7 +88,9 @@ void PostProcessing::configureEffect( shader.uniform1i("u_position", 1); shader.uniform1i("u_normal", 2); } - shader.uniform1i("u_noise", 3); + shader.uniform1i("u_noise", 3); // used in SSAO pass + shader.uniform1i("u_ssao", 3); + shader.uniform1i("u_shadows", 4); shader.uniform2i("u_screenSize", viewport); shader.uniform1f("u_timer", timer); @@ -126,13 +128,25 @@ void PostProcessing::render( glBindTexture(GL_TEXTURE_2D, noiseTexture); glActiveTexture(GL_TEXTURE0); + + auto& ssaoEffect = assets.require("ssao"); + auto& shader = ssaoEffect.use(); + configureEffect(context, ssaoEffect, shader, timer, camera, shadowMap); + gbuffer->bindSSAO(); + quadMesh->draw(); + gbuffer->unbind(); + + glActiveTexture(GL_TEXTURE3); + gbuffer->bindSSAOBuffer(); } else { glActiveTexture(GL_TEXTURE0); fbo->getTexture()->bind(); } if (totalPasses == 0) { - auto& effect = assets.require("default"); + auto& effect = assets.require( + gbuffer ? "deferred_lighting" : "default" + ); auto& shader = effect.use(); configureEffect(context, effect, shader, timer, camera, shadowMap); quadMesh->draw(); diff --git a/src/logic/scripting/lua/libs/libposteffects.cpp b/src/logic/scripting/lua/libs/libposteffects.cpp index 5e3284bf..acd51953 100644 --- a/src/logic/scripting/lua/libs/libposteffects.cpp +++ b/src/logic/scripting/lua/libs/libposteffects.cpp @@ -17,7 +17,10 @@ static int l_set_effect(lua::State* L) { size_t index = static_cast(lua::tointeger(L, 1)); auto name = lua::require_string(L, 2); auto& assets = *engine->getAssets(); - auto effect = std::make_shared(assets.require(name)); + auto effect = assets.getShared(name); + if (effect == nullptr) { + throw std::runtime_error(std::string("post-effect '") + name + "' not found"); + } post_processing->setEffect(index, std::move(effect)); return 0; } From f75fd186fd63fd3ef8155e0e2217bf7a7d689303 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 14 Jun 2025 23:01:37 +0300 Subject: [PATCH 22/47] fix build --- src/graphics/render/WorldRenderer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 193cb2d9..cb96252b 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -362,9 +362,8 @@ void WorldRenderer::generateShadowsMap( const auto& settings = engine.getSettings(); int resolution = shadowMap.getResolution(); - float shadowMapScale = - 0.16f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) * - scale; + int quality = settings.graphics.shadowsQuality.get(); + float shadowMapScale = 0.16f / (1 << glm::max(0, quality)) * scale; float shadowMapSize = resolution * shadowMapScale; glm::vec3 basePos = glm::floor(camera.position); From e146740da8dcb778b4cb382a721efc5799c4ef91 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 14 Jun 2025 23:12:32 +0300 Subject: [PATCH 23/47] fix windows build --- src/logic/scripting/lua/libs/libposteffects.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logic/scripting/lua/libs/libposteffects.cpp b/src/logic/scripting/lua/libs/libposteffects.cpp index acd51953..f4e1e252 100644 --- a/src/logic/scripting/lua/libs/libposteffects.cpp +++ b/src/logic/scripting/lua/libs/libposteffects.cpp @@ -69,8 +69,8 @@ static int l_set_array(lua::State* L) { return 0; } std::vector buffer( - reinterpret_cast(data.begin()), - reinterpret_cast(data.end()) + reinterpret_cast(data.data()), + reinterpret_cast(data.data() + data.size()) ); effect->setArray(key, std::move(buffer)); return 0; From 021cfd8a1efb2c5cb902c5649b14bb4c75221d5c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 14 Jun 2025 23:20:10 +0300 Subject: [PATCH 24/47] refactor PostEffect.cpp --- src/graphics/core/PostEffect.cpp | 102 ++++++++++++++++++------------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/src/graphics/core/PostEffect.cpp b/src/graphics/core/PostEffect.cpp index 47f2ac9f..317f215a 100644 --- a/src/graphics/core/PostEffect.cpp +++ b/src/graphics/core/PostEffect.cpp @@ -20,6 +20,65 @@ PostEffect::PostEffect( : advanced(advanced), shader(std::move(shader)), params(std::move(params)) { } +static void apply_uniform_value( + const PostEffect::Param& param, + Shader& shader, + const std::string& name +) { + using Type = PostEffect::Param::Type; + switch (param.type) { + case Type::INT: + shader.uniform1i(name, std::get(param.value)); + break; + case Type::FLOAT: + shader.uniform1f(name, std::get(param.value)); + break; + case Type::VEC2: + shader.uniform2f(name, std::get(param.value)); + break; + case Type::VEC3: + shader.uniform3f(name, std::get(param.value)); + break; + case Type::VEC4: + shader.uniform4f(name, std::get(param.value)); + break; + default: + assert(false); + } +} + +static void apply_uniform_array( + const PostEffect::Param& param, + Shader& shader, + const std::string& name, + const std::vector& values +) { + size_t size = values.size(); + auto ibuffer = reinterpret_cast(values.data()); + auto fbuffer = reinterpret_cast(values.data()); + + using Type = PostEffect::Param::Type; + switch (param.type) { + case Type::INT: + shader.uniform1v(name, size / sizeof(int), ibuffer); + break; + case Type::FLOAT: + shader.uniform1v(name, size / sizeof(float), fbuffer); + break; + case Type::VEC2: + shader.uniform2v(name, size / sizeof(glm::vec2), fbuffer); + break; + case Type::VEC3: + shader.uniform3v(name, size / sizeof(glm::vec3), fbuffer); + break; + case Type::VEC4: + shader.uniform4v(name, size / sizeof(glm::vec4), fbuffer); + break; + default: + assert(false); + } +} + Shader& PostEffect::use() { shader->use(); shader->uniform1f("u_intensity", intensity); @@ -32,48 +91,9 @@ Shader& PostEffect::use() { if (found == arrayValues.end()) { continue; } - size_t size = found->second.size(); - auto ibuffer = reinterpret_cast(found->second.data()); - auto fbuffer = reinterpret_cast(found->second.data()); - switch (param.type) { - case Param::Type::INT: - shader->uniform1v(name, size / sizeof(int), ibuffer); - break; - case Param::Type::FLOAT: - shader->uniform1v(name, size / sizeof(float), fbuffer); - break; - case Param::Type::VEC2: - shader->uniform2v(name, size / sizeof(glm::vec2), fbuffer); - break; - case Param::Type::VEC3: - shader->uniform3v(name, size / sizeof(glm::vec3), fbuffer); - break; - case Param::Type::VEC4: - shader->uniform4v(name, size / sizeof(glm::vec4), fbuffer); - break; - default: - assert(false); - } + apply_uniform_array(param, *shader, name, found->second); } else { - switch (param.type) { - case Param::Type::INT: - shader->uniform1i(name, std::get(param.value)); - break; - case Param::Type::FLOAT: - shader->uniform1f(name, std::get(param.value)); - break; - case Param::Type::VEC2: - shader->uniform2f(name, std::get(param.value)); - break; - case Param::Type::VEC3: - shader->uniform3f(name, std::get(param.value)); - break; - case Param::Type::VEC4: - shader->uniform4f(name, std::get(param.value)); - break; - default: - assert(false); - } + apply_uniform_value(param, *shader, name); } param.dirty = false; } From 3e66ff5924eb9f65f8a04e13a2992c436fc16837 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 15 Jun 2025 02:14:39 +0300 Subject: [PATCH 25/47] fix ssao --- res/shaders/background.glslf | 2 +- res/shaders/effects/ssao.glsl | 4 ++-- src/graphics/core/GBuffer.cpp | 1 - src/graphics/render/WorldRenderer.cpp | 7 ++++++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/res/shaders/background.glslf b/res/shaders/background.glslf index c442bb06..d485650a 100644 --- a/res/shaders/background.glslf +++ b/res/shaders/background.glslf @@ -7,7 +7,7 @@ uniform samplerCube u_skybox; void main(){ vec3 dir = normalize(v_coord); - f_position = vec4(0.0, 0.0, 0.0, 0.0); + f_position = vec4(0.0, 0.0, -1e9, 1.0); f_normal = vec4(0.0); f_color = texture(u_skybox, dir); } diff --git a/res/shaders/effects/ssao.glsl b/res/shaders/effects/ssao.glsl index c021b13a..399f2fde 100644 --- a/res/shaders/effects/ssao.glsl +++ b/res/shaders/effects/ssao.glsl @@ -1,6 +1,6 @@ #param vec3 u_ssaoSamples[64] #param int u_kernelSize = 16 -#param float u_radius = 0.2 +#param float u_radius = 0.4 #param float u_bias = 0.006 vec4 effect() { @@ -32,5 +32,5 @@ vec4 effect() { float z = -position.z * 0.01; z = max(0.0, 1.0 - z); - return vec4(occlusion, 0.0, 0.0, 1.0); + return vec4(mix(1.0, occlusion, z), 0.0, 0.0, 1.0); } diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index eabca78b..08180d75 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -155,7 +155,6 @@ void GBuffer::bind() { void GBuffer::bindSSAO() const { glBindFramebuffer(GL_FRAMEBUFFER, ssaoFbo); - glClear(GL_COLOR_BUFFER_BIT); } void GBuffer::unbind() { diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index cb96252b..fe6b0fcc 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -378,7 +378,12 @@ void WorldRenderer::generateShadowsMap( t += 1.0f; } t = fmod(t, 0.5f); - float sunAngle = glm::radians(90.0f - (((int)(t*1000)) / 1000.0f + 0.25f) * 360.0f); + + float sunCycleStep = 1.0f / 1000.0f; + float sunAngle = glm::radians( + 90.0f - + ((static_cast(t / sunCycleStep)) * sunCycleStep + 0.25f) * 360.0f + ); shadowCamera.rotate( sunAngle, glm::radians(-45.0f), From 1b84b7df5ee1f33d476929331d049cfcd73dd820 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 15 Jun 2025 03:35:40 +0300 Subject: [PATCH 26/47] fix sun and shadows position synchronization --- res/content/base/preload.json | 1 + res/textures/misc/moon_flare.png | Bin 0 -> 20106 bytes src/graphics/render/Skybox.cpp | 40 +++++++++++++++++--------- src/graphics/render/Skybox.hpp | 5 ++-- src/graphics/render/WorldRenderer.cpp | 7 +++-- 5 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 res/textures/misc/moon_flare.png diff --git a/res/content/base/preload.json b/res/content/base/preload.json index 760ad2c9..24d54a42 100644 --- a/res/content/base/preload.json +++ b/res/content/base/preload.json @@ -14,6 +14,7 @@ ], "textures": [ "misc/moon", + "misc/moon_flare", "misc/sun", "gui/crosshair" ] diff --git a/res/textures/misc/moon_flare.png b/res/textures/misc/moon_flare.png new file mode 100644 index 0000000000000000000000000000000000000000..57304f3b48a1c4582163e0ac91b6cc3f5440a32c GIT binary patch literal 20106 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 E1Mb(S-~a#s literal 0 HcmV?d00001 diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index bf6eedc1..2687dc20 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #ifndef M_PI @@ -46,18 +47,28 @@ Skybox::Skybox(uint size, Shader& shader) mesh = std::make_unique>(vertices, 6); - sprites.push_back(skysprite { - "misc/moon", - glm::pi()*0.5f, - 4.0f, - false + sprites.push_back(SkySprite { + "misc/moon_flare", + glm::pi() * 0.5f, + 0.5f, + false, + glm::pi() * 0.25f, }); - sprites.push_back(skysprite { - "misc/sun", - glm::pi()*1.5f, + sprites.push_back(SkySprite { + "misc/moon", + glm::pi() * 0.5f, 4.0f, - true + false, + glm::pi() * 0.25f, + }); + + sprites.push_back(SkySprite { + "misc/sun", + glm::pi() * 1.5f, + 4.0f, + true, + glm::pi() * 0.25f, }); } @@ -124,16 +135,19 @@ void Skybox::draw( for (auto& sprite : sprites) { batch3d->texture(assets.get(sprite.texture)); - float sangle = daytime * glm::pi()*2.0 + sprite.phase; + float sangle = daytime * glm::pi() * 2.0 + sprite.phase; float distance = sprite.distance; - glm::vec3 pos(-std::cos(sangle)*distance, std::sin(sangle)*distance, 0); - glm::vec3 up(-std::sin(-sangle), std::cos(-sangle), 0.0f); + glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), -sangle + glm::pi() * 0.5f, glm::vec3(0, 0, -1)); + rotation = glm::rotate(rotation, sprite.altitude, glm::vec3(1, 0, 0)); + glm::vec3 pos = glm::vec4(0, distance, 0, 1) * rotation; + glm::vec3 up = glm::vec4(1, 0, 0, 1) * rotation; + glm::vec3 right = glm::vec4(0, 0, 1, 1) * rotation; glm::vec4 tint (1,1,1, opacity); if (!sprite.emissive) { tint *= 0.6f+std::cos(angle)*0.4; } - batch3d->sprite(pos, glm::vec3(0, 0, 1), + batch3d->sprite(pos, right, up, 1, 1, UVRegion(), tint); } batch3d->flush(); diff --git a/src/graphics/render/Skybox.hpp b/src/graphics/render/Skybox.hpp index f469b155..c1184a14 100644 --- a/src/graphics/render/Skybox.hpp +++ b/src/graphics/render/Skybox.hpp @@ -25,11 +25,12 @@ struct SkyboxVertex { {{}, 0}}; }; -struct skysprite { +struct SkySprite { std::string texture; float phase; float distance; bool emissive; + float altitude; }; class Skybox { @@ -42,7 +43,7 @@ class Skybox { std::unique_ptr> mesh; std::unique_ptr batch3d; - std::vector sprites; + std::vector sprites; int frameid = 0; float prevMie = -1.0f; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index fe6b0fcc..e2b3dbef 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -384,10 +384,11 @@ void WorldRenderer::generateShadowsMap( 90.0f - ((static_cast(t / sunCycleStep)) * sunCycleStep + 0.25f) * 360.0f ); + float sunAltitude = glm::pi() * 0.25f; shadowCamera.rotate( - sunAngle, - glm::radians(-45.0f), - glm::radians(-0.0f) + -glm::cos(sunAngle + glm::pi() * 0.5f) * sunAltitude, + sunAngle - glm::pi() * 0.5f, + glm::radians(0.0f) ); shadowCamera.updateVectors(); From 96a94aa33cdc51e3741aa8152e91998bc3a76777 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 2 Jul 2025 23:02:50 +0300 Subject: [PATCH 27/47] feat: recompiling shaders --- res/shaders/lib/shadows.glsl | 8 +-- src/assets/assetload_funcs.cpp | 27 +++++---- src/graphics/core/Shader.cpp | 87 +++++++++++++++++++-------- src/graphics/core/Shader.hpp | 24 +++++--- src/graphics/render/WorldRenderer.cpp | 8 ++- 5 files changed, 102 insertions(+), 52 deletions(-) diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index e21afc22..fa6b9b54 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -11,10 +11,7 @@ uniform float u_shadowsOpacity; uniform float u_shadowsSoftness; float calc_shadow() { - if (!u_enableShadows) { - return 1.0; - } - +#ifdef ENABLE_SHADOWS float step = 1.0 / float(u_shadowsRes); float s = pow(abs(cos(u_dayTime * PI2)), 0.25) * u_shadowsOpacity; vec3 normalOffset = a_realnormal * (a_distance > 64.0 ? 0.2 : 0.04); @@ -39,6 +36,9 @@ float calc_shadow() { shadow = 0.5; } return 0.5 * (1.0 + s * shadow); +#else + return 1.0; +#endif } #endif // SHADOWS_GLSL_ diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index 4bd30416..78d89a0b 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -76,6 +76,14 @@ static auto process_program(const ResPaths& paths, const std::string& filename) return std::make_pair(vertex, fragment); } +static auto read_program(const ResPaths& paths, const std::string& filename) { + io::path vertexFile = paths.find(filename + ".glslv"); + io::path fragmentFile = paths.find(filename + ".glslf"); + return std::make_pair( + io::read_string(vertexFile), io::read_string(fragmentFile) + ); +} + assetload::postfunc assetload::shader( AssetsLoader*, const ResPaths& paths, @@ -83,21 +91,18 @@ assetload::postfunc assetload::shader( const std::string& name, const std::shared_ptr& ) { - auto [vertex, fragment] = process_program(paths, filename); + auto result = read_program(paths, filename); + auto vertex = result.first; + auto fragment = result.second; io::path vertexFile = paths.find(filename + ".glslv"); io::path fragmentFile = paths.find(filename + ".glslf"); - std::string vertexSource = std::move(vertex.code); - std::string fragmentSource = std::move(fragment.code); - return [=](auto assets) { assets->store( Shader::create( - vertexFile.string(), - fragmentFile.string(), - vertexSource, - fragmentSource + {vertexFile.string(), vertex}, + {fragmentFile.string(), fragment} ), name ); @@ -127,10 +132,8 @@ assetload::postfunc assetload::posteffect( return [=](auto assets) { auto program = Shader::create( - effectFile.string(), - effectFile.string(), - vertexSource, - fragmentSource + {effectFile.string(), vertexSource}, + {effectFile.string(), fragmentSource} ); bool advanced = false; if (settings) { diff --git a/src/graphics/core/Shader.cpp b/src/graphics/core/Shader.cpp index df02a5c0..24ea0241 100644 --- a/src/graphics/core/Shader.cpp +++ b/src/graphics/core/Shader.cpp @@ -12,20 +12,25 @@ #include #include "coders/GLSLExtension.hpp" +#include "debug/Logger.hpp" + +static debug::Logger logger("gl-shader"); namespace fs = std::filesystem; GLSLExtension* Shader::preprocessor = new GLSLExtension(); Shader* Shader::used = nullptr; -Shader::Shader(uint id) : id(id){ -} +Shader::Shader(uint id, Source&& vertexSource, Source&& fragmentSource) + : id(id), + vertexSource(std::move(vertexSource)), + fragmentSource(std::move(fragmentSource)) {} -Shader::~Shader(){ +Shader::~Shader() { glDeleteProgram(id); } -void Shader::use(){ +void Shader::use() { used = this; glUseProgram(id); } @@ -40,8 +45,10 @@ uint Shader::getUniformLocation(const std::string& name) { return found->second; } -void Shader::uniformMatrix(const std::string& name, const glm::mat4& matrix){ - glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix)); +void Shader::uniformMatrix(const std::string& name, const glm::mat4& matrix) { + glUniformMatrix4fv( + getUniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix) + ); } void Shader::uniform1i(const std::string& name, int x){ @@ -96,7 +103,7 @@ void Shader::uniform4v(const std::string& name, int length, const float* v) { glUniform4fv(getUniformLocation(name), length, v); } -inline auto shader_deleter = [](GLuint* shader) { +static inline auto shader_deleter = [](GLuint* shader) { glDeleteShader(*shader); delete shader; }; @@ -112,45 +119,73 @@ glshader compile_shader(GLenum type, const GLchar* source, const std::string& fi glShaderSource(shader, 1, &source, nullptr); glCompileShader(shader); glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success){ + if (!success) { GLchar infoLog[GL_LOG_LEN]; glGetShaderInfoLog(shader, GL_LOG_LEN, nullptr, infoLog); glDeleteShader(shader); throw std::runtime_error( - "vertex shader compilation failed ("+file+"):\n"+std::string(infoLog) + "vertex shader compilation failed (" + file + "):\n" + + std::string(infoLog) ); - } + } return glshader(new GLuint(shader), shader_deleter); //-V508 } -std::unique_ptr Shader::create( - const std::string& vertexFile, - const std::string& fragmentFile, - const std::string& vertexCode, - const std::string& fragmentCode +static GLuint compile_program( + const Shader::Source& vertexSource, const Shader::Source& fragmentSource ) { + auto& preprocessor = *Shader::preprocessor; + + auto vertexCode = std::move( + preprocessor.process(vertexSource.file, vertexSource.code).code + ); + auto fragmentCode = std::move( + preprocessor.process(fragmentSource.file, fragmentSource.code).code + ); + const GLchar* vCode = vertexCode.c_str(); const GLchar* fCode = fragmentCode.c_str(); - glshader vertex = compile_shader(GL_VERTEX_SHADER, vCode, vertexFile); - glshader fragment = compile_shader(GL_FRAGMENT_SHADER, fCode, fragmentFile); + glshader vertex = + compile_shader(GL_VERTEX_SHADER, vCode, vertexSource.file); + glshader fragment = + compile_shader(GL_FRAGMENT_SHADER, fCode, fragmentSource.file); // Shader Program GLint success; - GLuint id = glCreateProgram(); - glAttachShader(id, *vertex); - glAttachShader(id, *fragment); - glLinkProgram(id); + GLuint program = glCreateProgram(); + glAttachShader(program, *vertex); + glAttachShader(program, *fragment); + glLinkProgram(program); - glGetProgramiv(id, GL_LINK_STATUS, &success); - if (!success){ + glGetProgramiv(program, GL_LINK_STATUS, &success); + + if (!success) { GLchar infoLog[GL_LOG_LEN]; - glGetProgramInfoLog(id, GL_LOG_LEN, nullptr, infoLog); + glGetProgramInfoLog(program, GL_LOG_LEN, nullptr, infoLog); throw std::runtime_error( - "shader program linking failed:\n"+std::string(infoLog) + "shader program linking failed:\n" + std::string(infoLog) ); } - return std::make_unique(id); + return program; +} + +void Shader::recompile() { + GLuint newProgram = compile_program(vertexSource, fragmentSource); + glDeleteProgram(id); + id = newProgram; + uniformLocations.clear(); + logger.info() << "shader " << id << " has been recompiled"; +} + +std::unique_ptr Shader::create( + Source&& vertexSource, Source&& fragmentSource +) { + return std::make_unique( + compile_program(vertexSource, fragmentSource), + std::move(vertexSource), + std::move(fragmentSource) + ); } Shader& Shader::getUsed() { diff --git a/src/graphics/core/Shader.hpp b/src/graphics/core/Shader.hpp index d50ccb46..8f1aeb33 100644 --- a/src/graphics/core/Shader.hpp +++ b/src/graphics/core/Shader.hpp @@ -10,15 +10,25 @@ class GLSLExtension; class Shader { +public: + struct Source { + std::string file; + std::string code; + }; +private: static Shader* used; uint id; std::unordered_map uniformLocations; + // source code used for re-compiling shaders after updating defines + Source vertexSource; + Source fragmentSource; + uint getUniformLocation(const std::string& name); public: static GLSLExtension* preprocessor; - Shader(uint id); + Shader(uint id, Source&& vertexSource, Source&& fragmentSource); ~Shader(); void use(); @@ -38,17 +48,13 @@ public: void uniform3v(const std::string& name, int length, const float* v); void uniform4v(const std::string& name, int length, const float* v); + /// @brief Re-preprocess source code and re-compile shader program + void recompile(); + /// @brief Create shader program using vertex and fragment shaders source. - /// @param vertexFile vertex shader file name - /// @param fragmentFile fragment shader file name - /// @param vertexSource vertex shader source code - /// @param fragmentSource fragment shader source code /// @return linked shader program containing vertex and fragment shaders static std::unique_ptr create( - const std::string& vertexFile, - const std::string& fragmentFile, - const std::string& vertexSource, - const std::string& fragmentSource + Source&& vertexSource, Source&& fragmentSource ); static Shader& getUsed(); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index e2b3dbef..bc24fd27 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -11,6 +11,7 @@ #include "assets/assets_util.hpp" #include "content/Content.hpp" #include "engine/Engine.hpp" +#include "coders/GLSLExtension.hpp" #include "frontend/LevelFrontend.hpp" #include "frontend/ContentGfxCache.hpp" #include "items/Inventory.hpp" @@ -434,6 +435,7 @@ void WorldRenderer::draw( const auto& vp = pctx.getViewport(); camera.setAspectRatio(vp.x / static_cast(vp.y)); + auto& mainShader = assets.require("main"); const auto& settings = engine.getSettings(); gbufferPipeline = settings.graphics.advancedRender.get(); int shadowsQuality = settings.graphics.shadowsQuality.get(); @@ -442,10 +444,14 @@ void WorldRenderer::draw( shadowMap = std::make_unique(resolution); wideShadowMap = std::make_unique(resolution); shadows = true; - } else if (shadowsQuality == 0) { + Shader::preprocessor->define("ENABLE_SHADOWS", "true"); + mainShader.recompile(); + } else if (shadowsQuality == 0 && shadows) { shadowMap.reset(); wideShadowMap.reset(); shadows = false; + Shader::preprocessor->undefine("ENABLE_SHADOWS"); + mainShader.recompile(); } if (shadows && shadowMap->getResolution() != resolution) { shadowMap = std::make_unique(resolution); From a9652327f1c5f3b2734ccc2e43c8ae72596e09bf Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 3 Jul 2025 20:12:11 +0300 Subject: [PATCH 28/47] improve ssao --- res/shaders/effects/deferred_lighting.glsl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/res/shaders/effects/deferred_lighting.glsl b/res/shaders/effects/deferred_lighting.glsl index ea9c32bb..79c01435 100644 --- a/res/shaders/effects/deferred_lighting.glsl +++ b/res/shaders/effects/deferred_lighting.glsl @@ -1,11 +1,15 @@ vec4 effect() { float ssao = 0.0; - for (int y = -1; y <= 1; y++) { - for (int x = -1; x <= 1; x++) { + float z = texture(u_position, v_uv).z; + for (int y = -2; y <= 2; y++) { + for (int x = -2; x <= 2; x++) { vec2 offset = vec2(x, y) / u_screenSize; - ssao += texture(u_ssao, v_uv + offset * 2.0).r; + if (abs(z - texture(u_position, v_uv + offset * 2.0).z) > 0.05) + ssao += 1.0; + else + ssao += texture(u_ssao, v_uv + offset * 2.0).r; } } - ssao /= 9.0; + ssao /= 24.0; return vec4(texture(u_screen, v_uv).rgb * mix(1.0, ssao, 1.0), 1.0); } From 931f0180ef340a149abd44c24b15a1ff588aadac Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 4 Jul 2025 18:20:41 +0300 Subject: [PATCH 29/47] update shadows --- res/shaders/lib/shadows.glsl | 17 ++++++++++------- src/graphics/render/WorldRenderer.cpp | 8 ++++---- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index fa6b9b54..b66f8a4b 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -15,23 +15,26 @@ float calc_shadow() { float step = 1.0 / float(u_shadowsRes); float s = pow(abs(cos(u_dayTime * PI2)), 0.25) * u_shadowsOpacity; vec3 normalOffset = a_realnormal * (a_distance > 64.0 ? 0.2 : 0.04); - int shadowIdx = a_distance > 64.0 ? 1 : 0; + int shadowIdx = a_distance > 80.0 ? 1 : 0; vec4 mpos = u_shadowsMatrix[shadowIdx] * vec4(a_modelpos.xyz + normalOffset, 1.0); vec3 projCoords = mpos.xyz / mpos.w; projCoords = projCoords * 0.5 + 0.5; - projCoords.z -= 0.00001; + projCoords.z -= 0.00001 / u_shadowsRes; + if (shadowIdx > 0) { + projCoords.z -= 0.001; + } float shadow = 0.0; if (dot(a_realnormal, u_sunDir) < 0.0) { - // 5x5 kernel - for (int y = -2; y <= 2; y++) { - for (int x = -2; x <= 2; x++) { - vec3 offset = vec3(x, y, -(abs(x) + abs(y)) * 0.1) * step * 2.0 * u_shadowsSoftness; + // 3x3 kernel + for (int y = -1; y <= 1; y++) { + for (int x = -1; x <= 1; x++) { + vec3 offset = vec3(x, y, -(abs(x) + abs(y)) * 0.8) * step * 1.0 * u_shadowsSoftness; shadow += texture(u_shadows[shadowIdx], projCoords + offset); } } - shadow /= 25.0; + shadow /= 9.0; } else { shadow = 0.5; } diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index bc24fd27..4d2a2c2a 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -364,7 +364,7 @@ void WorldRenderer::generateShadowsMap( const auto& settings = engine.getSettings(); int resolution = shadowMap.getResolution(); int quality = settings.graphics.shadowsQuality.get(); - float shadowMapScale = 0.16f / (1 << glm::max(0, quality)) * scale; + float shadowMapScale = 0.32f / (1 << glm::max(0, quality)) * scale; float shadowMapSize = resolution * shadowMapScale; glm::vec3 basePos = glm::floor(camera.position); @@ -380,7 +380,7 @@ void WorldRenderer::generateShadowsMap( } t = fmod(t, 0.5f); - float sunCycleStep = 1.0f / 1000.0f; + float sunCycleStep = 1.0f / 500.0f; float sunAngle = glm::radians( 90.0f - ((static_cast(t / sunCycleStep)) * sunCycleStep + 0.25f) * 360.0f @@ -439,7 +439,7 @@ void WorldRenderer::draw( const auto& settings = engine.getSettings(); gbufferPipeline = settings.graphics.advancedRender.get(); int shadowsQuality = settings.graphics.shadowsQuality.get(); - int resolution = 1024 << shadowsQuality; + int resolution = 512 << shadowsQuality; if (shadowsQuality > 0 && !shadows) { shadowMap = std::make_unique(resolution); wideShadowMap = std::make_unique(resolution); @@ -473,7 +473,7 @@ void WorldRenderer::draw( if (frameid % 2 == 0) { generateShadowsMap(camera, pctx, *shadowMap, shadowCamera, 1.0f); } else { - generateShadowsMap(camera, pctx, *wideShadowMap, wideShadowCamera, 4.0f); + generateShadowsMap(camera, pctx, *wideShadowMap, wideShadowCamera, 3.0f); } } frameid++; From 559322f70a1b8d26fbf64d0f96bc3c2d2dee23b7 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 7 Jul 2025 00:25:12 +0300 Subject: [PATCH 30/47] improve torchlight --- res/shaders/entity.glslv | 2 +- res/shaders/lib/lighting.glsl | 4 ++-- res/shaders/main.glslv | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/res/shaders/entity.glslv b/res/shaders/entity.glslv index ee5b9538..60a1b715 100644 --- a/res/shaders/entity.glslv +++ b/res/shaders/entity.glslv @@ -38,7 +38,7 @@ void main() { a_realnormal = a_normal; vec3 light = v_light.rgb; - float torchlight = calc_torch_light(a_modelpos.xyz); + float torchlight = calc_torch_light(a_realnormal, a_modelpos.xyz); light += torchlight * u_torchlightColor; a_color = vec4(pow(light, vec3(u_gamma)),1.0f); a_texCoord = v_texCoord; diff --git a/res/shaders/lib/lighting.glsl b/res/shaders/lib/lighting.glsl index d2c4f896..d442c64f 100644 --- a/res/shaders/lib/lighting.glsl +++ b/res/shaders/lib/lighting.glsl @@ -7,8 +7,8 @@ uniform float u_weatherFogOpacity; uniform float u_weatherFogDencity; uniform float u_weatherFogCurve; -float calc_torch_light(vec3 modelpos) { - return max(0.0, 1.0 - distance(u_cameraPos, modelpos.xyz) / u_torchlightDistance); +float calc_torch_light(vec3 normal, vec3 modelpos) { + return max(0.0, 1.0 - distance(u_cameraPos, modelpos) / u_torchlightDistance) * -dot(normal, normalize(modelpos - u_cameraPos)); } vec3 calc_screen_normal(vec3 normal) { diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index fa28b8e3..2f0f084a 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -38,7 +38,7 @@ void main() { a_normal = calc_screen_normal(a_realnormal); vec3 light = v_light.rgb; - float torchlight = calc_torch_light(a_modelpos.xyz); + float torchlight = calc_torch_light(a_realnormal, a_modelpos.xyz); a_torchLight = vec4(pow(light + torchlight * u_torchlightColor, vec3(u_gamma)), 1.0f); a_texCoord = v_texCoord; From 85212e271d8a78716ddc6166758b0164f98033b6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 7 Jul 2025 02:15:59 +0300 Subject: [PATCH 31/47] fix --- res/shaders/lib/lighting.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/shaders/lib/lighting.glsl b/res/shaders/lib/lighting.glsl index d442c64f..2d164c30 100644 --- a/res/shaders/lib/lighting.glsl +++ b/res/shaders/lib/lighting.glsl @@ -8,7 +8,7 @@ uniform float u_weatherFogDencity; uniform float u_weatherFogCurve; float calc_torch_light(vec3 normal, vec3 modelpos) { - return max(0.0, 1.0 - distance(u_cameraPos, modelpos) / u_torchlightDistance) * -dot(normal, normalize(modelpos - u_cameraPos)); + return max(0.0, 1.0 - distance(u_cameraPos, modelpos) / u_torchlightDistance) * max(0.0, -dot(normal, normalize(modelpos - u_cameraPos))); } vec3 calc_screen_normal(vec3 normal) { From 07d39d27421240b2545b06b55abddd7d526e2e98 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 7 Jul 2025 02:16:55 +0300 Subject: [PATCH 32/47] update base:torch --- res/content/base/blocks/torch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/content/base/blocks/torch.json b/res/content/base/blocks/torch.json index cf26bfec..e9a976f0 100644 --- a/res/content/base/blocks/torch.json +++ b/res/content/base/blocks/torch.json @@ -7,7 +7,7 @@ "torch_side", "torch_side" ], - "emission": [13, 13, 12], + "emission": [13, 10, 2], "model": "aabb", "hitbox": [0.4375, 0.0, 0.4375, 0.125, 0.5, 0.125], "light-passing": true, From 7a98f0c4111c26c5c248595a9d2e36a7d0522a27 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 7 Jul 2025 19:43:18 +0300 Subject: [PATCH 33/47] fix entities shading --- res/shaders/entity.glslf | 25 ++++++++++------------- res/shaders/entity.glslv | 5 +++-- res/shaders/lib/lighting.glsl | 3 ++- res/shaders/main.glslf | 9 ++++----- src/graphics/render/MainBatch.hpp | 29 +++++++++++++++++++-------- src/graphics/render/ModelBatch.cpp | 18 +++++++++-------- src/graphics/render/WorldRenderer.cpp | 10 ++++++--- 7 files changed, 58 insertions(+), 41 deletions(-) diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index 4348c60f..cda2c92c 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -1,17 +1,17 @@ -in float a_distance; -in vec4 a_color; -in vec2 a_texCoord; -in vec3 a_position; -in vec3 a_dir; -in vec3 a_normal; -in vec3 a_realnormal; -in vec4 a_modelpos; -in float a_fog; - layout (location = 0) out vec4 f_color; layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; +in float a_distance; +in float a_fog; +in vec2 a_texCoord; +in vec3 a_dir; +in vec3 a_normal; +in vec3 a_position; +in vec3 a_realnormal; +in vec4 a_color; +in vec4 a_modelpos; + uniform sampler2D u_texture0; uniform samplerCube u_skybox; uniform vec3 u_fogColor; @@ -20,8 +20,6 @@ uniform float u_fogCurve; uniform bool u_alphaClip; uniform vec3 u_sunDir; -uniform bool u_enableShadows; - #include void main() { @@ -33,8 +31,7 @@ void main() { if (alpha < (u_alphaClip ? 0.5f : 0.15f)) { discard; } - f_color = a_color * tex_color; - f_color.rgb *= shadow; + f_color = a_color * tex_color * shadow; f_color = mix(f_color, vec4(fogColor, 1.0), a_fog); f_color.a = alpha; f_position = vec4(a_position, 1.0); diff --git a/res/shaders/entity.glslv b/res/shaders/entity.glslv index 60a1b715..df11f062 100644 --- a/res/shaders/entity.glslv +++ b/res/shaders/entity.glslv @@ -4,6 +4,7 @@ layout (location = 0) in vec3 v_position; layout (location = 1) in vec2 v_texCoord; layout (location = 2) in vec3 v_color; layout (location = 3) in vec4 v_light; +layout (location = 4) in vec4 v_normal; out float a_distance; out float a_fog; @@ -34,8 +35,8 @@ void main() { vec3 pos3d = a_modelpos.xyz - u_cameraPos; a_modelpos.xyz = apply_planet_curvature(a_modelpos.xyz, pos3d); - a_normal = vec3(0.0, 1.0, 0.0);//v_normal.xyz * 2.0 - 1.0; - a_realnormal = a_normal; + a_realnormal = v_normal.xyz * 2.0 - 1.0; + a_normal = calc_screen_normal(a_realnormal); vec3 light = v_light.rgb; float torchlight = calc_torch_light(a_realnormal, a_modelpos.xyz); diff --git a/res/shaders/lib/lighting.glsl b/res/shaders/lib/lighting.glsl index 2d164c30..a18a85a2 100644 --- a/res/shaders/lib/lighting.glsl +++ b/res/shaders/lib/lighting.glsl @@ -8,7 +8,8 @@ uniform float u_weatherFogDencity; uniform float u_weatherFogCurve; float calc_torch_light(vec3 normal, vec3 modelpos) { - return max(0.0, 1.0 - distance(u_cameraPos, modelpos) / u_torchlightDistance) * max(0.0, -dot(normal, normalize(modelpos - u_cameraPos))); + return max(0.0, 1.0 - distance(u_cameraPos, modelpos) / u_torchlightDistance) + * max(0.0, -dot(normal, normalize(modelpos - u_cameraPos))); } vec3 calc_screen_normal(vec3 normal) { diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index f1a4a549..51f0b9c6 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -3,15 +3,15 @@ layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; in float a_distance; -in vec4 a_torchLight; -in vec3 a_skyLight; -in vec2 a_texCoord; in float a_fog; -in vec3 a_position; +in vec2 a_texCoord; in vec3 a_dir; in vec3 a_normal; +in vec3 a_position; in vec3 a_realnormal; +in vec3 a_skyLight; in vec4 a_modelpos; +in vec4 a_torchLight; uniform sampler2D u_texture0; uniform samplerCube u_skybox; @@ -21,7 +21,6 @@ uniform vec3 u_sunDir; uniform bool u_alphaClip; uniform bool u_debugLights; uniform bool u_debugNormals; -uniform bool u_enableShadows; #include diff --git a/src/graphics/render/MainBatch.hpp b/src/graphics/render/MainBatch.hpp index 2ca1d3d0..bafecd80 100644 --- a/src/graphics/render/MainBatch.hpp +++ b/src/graphics/render/MainBatch.hpp @@ -18,13 +18,15 @@ struct MainBatchVertex { glm::vec3 position; glm::vec2 uv; glm::vec3 tint; - std::array color; + std::array color; + std::array normal; static constexpr VertexAttribute ATTRIBUTES[] = { {VertexAttribute::Type::FLOAT, false, 3}, {VertexAttribute::Type::FLOAT, false, 2}, {VertexAttribute::Type::FLOAT, false, 3}, {VertexAttribute::Type::UNSIGNED_BYTE, true, 4}, + {VertexAttribute::Type::UNSIGNED_BYTE, true, 4}, {{}, 0}}; }; @@ -61,7 +63,8 @@ public: const glm::vec3& pos, const glm::vec2& uv, const glm::vec4& light, - const glm::vec3& tint + const glm::vec3& tint, + const glm::vec3& normal ) { MainBatchVertex* buffer = this->buffer.get(); buffer[index].position = pos; @@ -72,6 +75,10 @@ public: buffer[index].color[1] = static_cast(light.g * 255); buffer[index].color[2] = static_cast(light.b * 255); buffer[index].color[3] = static_cast(light.a * 255); + + buffer[index].normal[0] = static_cast(normal.x * 128 + 127); + buffer[index].normal[1] = static_cast(normal.y * 128 + 127); + buffer[index].normal[2] = static_cast(normal.z * 128 + 127); index++; } @@ -89,38 +96,44 @@ public: pos - right * size.x * 0.5f - up * size.y * 0.5f, {subregion.u1, subregion.v1}, light, - tint + tint, + glm::cross(up, right) ); vertex( pos + right * size.x * 0.5f - up * size.y * 0.5f, {subregion.u2, subregion.v1}, light, - tint + tint, + glm::cross(up, right) ); vertex( pos + right * size.x * 0.5f + up * size.y * 0.5f, {subregion.u2, subregion.v2}, light, - tint + tint, + glm::cross(up, right) ); vertex( pos - right * size.x * 0.5f - up * size.y * 0.5f, {subregion.u1, subregion.v1}, light, - tint + tint, + glm::cross(up, right) ); vertex( pos + right * size.x * 0.5f + up * size.y * 0.5f, {subregion.u2, subregion.v2}, light, - tint + tint, + glm::cross(up, right) ); vertex( pos - right * size.x * 0.5f + up * size.y * 0.5f, {subregion.u1, subregion.v2}, light, - tint + tint, + glm::cross(up, right) ); } diff --git a/src/graphics/render/ModelBatch.cpp b/src/graphics/render/ModelBatch.cpp index 08deb7bd..77e948e7 100644 --- a/src/graphics/render/ModelBatch.cpp +++ b/src/graphics/render/ModelBatch.cpp @@ -57,12 +57,14 @@ ModelBatch::ModelBatch( ModelBatch::~ModelBatch() = default; -void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix, - const glm::mat3& rotation, glm::vec3 tint, - const texture_names_map* varTextures, - bool backlight) { - - +void ModelBatch::draw( + const model::Mesh& mesh, + const glm::mat4& matrix, + const glm::mat3& rotation, + glm::vec3 tint, + const texture_names_map* varTextures, + bool backlight +) { setTexture(mesh.texture, varTextures); size_t vcount = mesh.vertices.size(); const auto& vertexData = mesh.vertices.data(); @@ -78,12 +80,12 @@ void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix, for (size_t j = 0; j < 3; j++) { const auto vert = vertexData[i * 3 + j]; float d = 1.0f; + auto norm = rotation * vert.normal; if (mesh.lighting) { - auto norm = rotation * vert.normal; d = glm::dot(norm, SUN_VECTOR); d = 0.8f + d * 0.2f; } - batch->vertex(matrix * glm::vec4(vert.coord, 1.0f), vert.uv, lights*d, tint); + batch->vertex(matrix * glm::vec4(vert.coord, 1.0f), vert.uv, lights*d, tint, norm); } } } diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 4d2a2c2a..3f74d8fb 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -367,7 +367,7 @@ void WorldRenderer::generateShadowsMap( float shadowMapScale = 0.32f / (1 << glm::max(0, quality)) * scale; float shadowMapSize = resolution * shadowMapScale; - glm::vec3 basePos = glm::floor(camera.position); + glm::vec3 basePos = glm::floor(camera.position / 4.0f) * 4.0f; shadowCamera = Camera(basePos, shadowMapSize); shadowCamera.near = 0.1f; shadowCamera.far = 1000.0f; @@ -400,8 +400,9 @@ void WorldRenderer::generateShadowsMap( auto view = shadowCamera.getView(); auto currentPos = shadowCamera.position; - auto min = view * glm::vec4(currentPos - (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); - auto max = view * glm::vec4(currentPos + (shadowCamera.right + shadowCamera.up) * (shadowMapSize * 0.5f), 1.0f); + auto topRight = shadowCamera.right + shadowCamera.up; + auto min = view * glm::vec4(currentPos - topRight * shadowMapSize * 0.5f, 1.0f); + auto max = view * glm::vec4(currentPos + topRight * shadowMapSize * 0.5f, 1.0f); shadowCamera.setProjection(glm::ortho(min.x, max.x, min.y, max.y, 0.1f, 1000.0f)); @@ -436,6 +437,7 @@ void WorldRenderer::draw( camera.setAspectRatio(vp.x / static_cast(vp.y)); auto& mainShader = assets.require("main"); + auto& entityShader = assets.require("entity"); const auto& settings = engine.getSettings(); gbufferPipeline = settings.graphics.advancedRender.get(); int shadowsQuality = settings.graphics.shadowsQuality.get(); @@ -446,12 +448,14 @@ void WorldRenderer::draw( shadows = true; Shader::preprocessor->define("ENABLE_SHADOWS", "true"); mainShader.recompile(); + entityShader.recompile(); } else if (shadowsQuality == 0 && shadows) { shadowMap.reset(); wideShadowMap.reset(); shadows = false; Shader::preprocessor->undefine("ENABLE_SHADOWS"); mainShader.recompile(); + entityShader.recompile(); } if (shadows && shadowMap->getResolution() != resolution) { shadowMap = std::make_unique(resolution); From a585b52aa23e572abeb35fbb25322342a3a4f0e8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 7 Jul 2025 20:42:30 +0300 Subject: [PATCH 34/47] fix particles normals --- src/graphics/render/MainBatch.cpp | 48 +++++++++---------- src/graphics/render/MainBatch.hpp | 13 ++--- src/graphics/render/ParticlesRenderer.cpp | 1 + src/graphics/render/PrecipitationRenderer.cpp | 1 + 4 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/graphics/render/MainBatch.cpp b/src/graphics/render/MainBatch.cpp index 34976819..f05b715d 100644 --- a/src/graphics/render/MainBatch.cpp +++ b/src/graphics/render/MainBatch.cpp @@ -94,39 +94,39 @@ void MainBatch::cube( const glm::vec3 Z(0.0f, 0.0f, 1.0f); quad( - coord + Z * size.z * 0.5f, - X, Y, glm::vec2(size.x, size.y), - (shading ? do_tint(0.8) * tint : tint), - glm::vec3(1.0f), texfaces[5] + coord + Z * size.z * 0.5f, + X, Y, Z, glm::vec2(size.x, size.y), + (shading ? do_tint(0.8) * tint : tint), + glm::vec3(1.0f), texfaces[5] ); quad( - coord - Z * size.z * 0.5f, - -X, Y, glm::vec2(size.x, size.y), - (shading ? do_tint(0.9f) * tint : tint), - glm::vec3(1.0f), texfaces[4] + coord - Z * size.z * 0.5f, + -X, Y, -Z, glm::vec2(size.x, size.y), + (shading ? do_tint(0.9f) * tint : tint), + glm::vec3(1.0f), texfaces[4] ); quad( - coord + Y * size.y * 0.5f, - -X, Z, glm::vec2(size.x, size.z), - (shading ? do_tint(1.0f) * tint : tint), - glm::vec3(1.0f), texfaces[3] + coord + Y * size.y * 0.5f, + -X, Z, Y, glm::vec2(size.x, size.z), + (shading ? do_tint(1.0f) * tint : tint), + glm::vec3(1.0f), texfaces[3] ); quad( - coord - Y * size.y * 0.5f, - X, Z, glm::vec2(size.x, size.z), - (shading ? do_tint(0.7f) * tint : tint), - glm::vec3(1.0f), texfaces[2] + coord - Y * size.y * 0.5f, + X, Z, -Y, glm::vec2(size.x, size.z), + (shading ? do_tint(0.7f) * tint : tint), + glm::vec3(1.0f), texfaces[2] ); quad( - coord + X * size.x * 0.5f, - -Z, Y, glm::vec2(size.z, size.y), - (shading ? do_tint(0.8f) * tint : tint), - glm::vec3(1.0f), texfaces[1] + coord + X * size.x * 0.5f, + -Z, Y, X, glm::vec2(size.z, size.y), + (shading ? do_tint(0.8f) * tint : tint), + glm::vec3(1.0f), texfaces[1] ); quad( - coord - X * size.x * 0.5f, - Z, Y, glm::vec2(size.z, size.y), - (shading ? do_tint(0.9f) * tint : tint), - glm::vec3(1.0f), texfaces[1] + coord - X * size.x * 0.5f, + Z, Y, -X, glm::vec2(size.z, size.y), + (shading ? do_tint(0.9f) * tint : tint), + glm::vec3(1.0f), texfaces[1] ); } diff --git a/src/graphics/render/MainBatch.hpp b/src/graphics/render/MainBatch.hpp index bafecd80..2c22412e 100644 --- a/src/graphics/render/MainBatch.hpp +++ b/src/graphics/render/MainBatch.hpp @@ -86,6 +86,7 @@ public: const glm::vec3& pos, const glm::vec3& right, const glm::vec3& up, + const glm::vec3& normal, const glm::vec2& size, const glm::vec4& light, const glm::vec3& tint, @@ -97,21 +98,21 @@ public: {subregion.u1, subregion.v1}, light, tint, - glm::cross(up, right) + normal ); vertex( pos + right * size.x * 0.5f - up * size.y * 0.5f, {subregion.u2, subregion.v1}, light, tint, - glm::cross(up, right) + normal ); vertex( pos + right * size.x * 0.5f + up * size.y * 0.5f, {subregion.u2, subregion.v2}, light, tint, - glm::cross(up, right) + normal ); vertex( @@ -119,21 +120,21 @@ public: {subregion.u1, subregion.v1}, light, tint, - glm::cross(up, right) + normal ); vertex( pos + right * size.x * 0.5f + up * size.y * 0.5f, {subregion.u2, subregion.v2}, light, tint, - glm::cross(up, right) + normal ); vertex( pos - right * size.x * 0.5f + up * size.y * 0.5f, {subregion.u1, subregion.v2}, light, tint, - glm::cross(up, right) + normal ); } diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 4c6a913e..23b7a857 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -134,6 +134,7 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { particle.position, localRight, localUp, + -camera.front, preset.size * scale, light, glm::vec3(1.0f), diff --git a/src/graphics/render/PrecipitationRenderer.cpp b/src/graphics/render/PrecipitationRenderer.cpp index 60f2c026..42dc3115 100644 --- a/src/graphics/render/PrecipitationRenderer.cpp +++ b/src/graphics/render/PrecipitationRenderer.cpp @@ -146,6 +146,7 @@ void PrecipitationRenderer::render( pos, face.right, {0, 1, 0}, + glm::cross(glm::vec3(0, 1, 0), face.right), FACE_SIZE, light_at(chunks, pos.x, y, pos.z), glm::vec3(1.0f), From 0bd901d1a604c816b0f5488c80b41e9961abdc6d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 8 Jul 2025 23:56:22 +0300 Subject: [PATCH 35/47] feat: deferred shading (day 2) --- res/shaders/background.glslf | 7 +- res/shaders/background.glslv | 4 +- res/shaders/effect.glslf | 6 +- res/shaders/effects/deferred_lighting.glsl | 21 +++-- res/shaders/entity.glslf | 2 +- res/shaders/entity.glslv | 1 + res/shaders/lib/fog.glsl | 19 +++++ res/shaders/lib/lighting.glsl | 15 ---- res/shaders/lib/shadows.glsl | 10 +-- res/shaders/main.glslf | 7 +- res/shaders/main.glslv | 1 + src/graphics/core/GBuffer.cpp | 18 ++++- src/graphics/core/GBuffer.hpp | 2 + src/graphics/core/PostEffect.cpp | 4 + src/graphics/core/PostEffect.hpp | 2 + src/graphics/core/PostProcessing.cpp | 89 ++++++++++++++++++---- src/graphics/core/PostProcessing.hpp | 13 +++- src/graphics/core/Shader.cpp | 6 ++ src/graphics/core/Shader.hpp | 1 + src/graphics/core/commons.hpp | 10 +++ src/graphics/render/Skybox.cpp | 41 +++++----- src/graphics/render/WorldRenderer.cpp | 47 ++++++++---- src/window/Camera.hpp | 2 +- 23 files changed, 236 insertions(+), 92 deletions(-) create mode 100644 res/shaders/lib/fog.glsl diff --git a/res/shaders/background.glslf b/res/shaders/background.glslf index d485650a..ea4079ba 100644 --- a/res/shaders/background.glslf +++ b/res/shaders/background.glslf @@ -3,11 +3,12 @@ layout (location = 0) out vec4 f_color; layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; +uniform mat4 u_view; uniform samplerCube u_skybox; void main(){ - vec3 dir = normalize(v_coord); - f_position = vec4(0.0, 0.0, -1e9, 1.0); - f_normal = vec4(0.0); + vec3 dir = normalize(v_coord) * 1e6; + f_position = u_view * vec4(dir, 1.0); + f_normal = vec4(0.0, 0.0, 1.0, 1.0); f_color = texture(u_skybox, dir); } diff --git a/res/shaders/background.glslv b/res/shaders/background.glslv index 4de0d5b8..a3dfa198 100644 --- a/res/shaders/background.glslv +++ b/res/shaders/background.glslv @@ -7,6 +7,6 @@ uniform float u_ar; uniform float u_zoom; void main(){ - v_coord = (vec4(v_position*vec2(u_ar, 1.0f)*u_zoom, -1.0, 1.0) * u_view).xyz; - gl_Position = vec4(v_position, 0.0, 1.0); + v_coord = (vec4(v_position * vec2(u_ar, 1.0f) * u_zoom, -1.0, 1.0) * u_view).xyz; + gl_Position = vec4(v_position, 1.0 - 1e-6, 1.0); } diff --git a/res/shaders/effect.glslf b/res/shaders/effect.glslf index 792b6c2b..be50d779 100644 --- a/res/shaders/effect.glslf +++ b/res/shaders/effect.glslf @@ -6,13 +6,17 @@ uniform sampler2D u_position; uniform sampler2D u_normal; uniform sampler2D u_noise; uniform sampler2D u_ssao; -uniform sampler2D u_shadows; +uniform samplerCube u_skybox; uniform ivec2 u_screenSize; uniform float u_intensity; uniform float u_timer; uniform bool u_enableShadows; uniform mat4 u_projection; +uniform mat4 u_view; +uniform mat4 u_inverseView; +uniform vec3 u_sunDir; +uniform vec3 u_cameraPos; #include <__effect__> diff --git a/res/shaders/effects/deferred_lighting.glsl b/res/shaders/effects/deferred_lighting.glsl index 79c01435..f21b1b4a 100644 --- a/res/shaders/effects/deferred_lighting.glsl +++ b/res/shaders/effects/deferred_lighting.glsl @@ -1,15 +1,24 @@ +#include +#include + vec4 effect() { float ssao = 0.0; - float z = texture(u_position, v_uv).z; + vec4 pos = texture(u_position, v_uv); + float z = pos.z; for (int y = -2; y <= 2; y++) { for (int x = -2; x <= 2; x++) { vec2 offset = vec2(x, y) / u_screenSize; - if (abs(z - texture(u_position, v_uv + offset * 2.0).z) > 0.05) - ssao += 1.0; - else - ssao += texture(u_ssao, v_uv + offset * 2.0).r; + ssao += texture(u_ssao, v_uv + offset * 2.0).r; } } ssao /= 24.0; - return vec4(texture(u_screen, v_uv).rgb * mix(1.0, ssao, 1.0), 1.0); + vec4 modelpos = u_inverseView * pos; + vec3 normal = transpose(mat3(u_view)) * texture(u_normal, v_uv).xyz; + vec3 dir = modelpos.xyz - u_cameraPos; +#ifdef ENABLE_SHADOWS + ssao *= calc_shadow(modelpos, normal, length(pos)); +#endif + vec3 fogColor = texture(u_skybox, dir).rgb; + float fog = calc_fog(length(u_view * vec4((modelpos.xyz - u_cameraPos) * FOG_POS_SCALE, 0.0)) / 256.0); + return vec4(mix(texture(u_screen, v_uv).rgb * mix(1.0, ssao, 1.0), fogColor, fog), 1.0); } diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index cda2c92c..8cc2f75a 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -23,7 +23,7 @@ uniform vec3 u_sunDir; #include void main() { - float shadow = calc_shadow(); + 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; diff --git a/res/shaders/entity.glslv b/res/shaders/entity.glslv index df11f062..24a8a714 100644 --- a/res/shaders/entity.glslv +++ b/res/shaders/entity.glslv @@ -29,6 +29,7 @@ uniform vec3 u_torchlightColor; uniform float u_torchlightDistance; #include +#include void main() { a_modelpos = u_model * vec4(v_position, 1.0); diff --git a/res/shaders/lib/fog.glsl b/res/shaders/lib/fog.glsl new file mode 100644 index 00000000..e5ff18bb --- /dev/null +++ b/res/shaders/lib/fog.glsl @@ -0,0 +1,19 @@ +#ifndef FOG_GLSL_ +#define FOG_GLSL_ + +uniform float u_fogFactor; +uniform float u_fogCurve; +uniform float u_weatherFogOpacity; +uniform float u_weatherFogDencity; +uniform float u_weatherFogCurve; + +float calc_fog(float depth) { + return min( + 1.0, + max(pow(depth * u_fogFactor, u_fogCurve), + min(pow(depth * u_weatherFogDencity, u_weatherFogCurve), + u_weatherFogOpacity)) + ); +} + +#endif // FOG_GLSL_ diff --git a/res/shaders/lib/lighting.glsl b/res/shaders/lib/lighting.glsl index a18a85a2..c9e14920 100644 --- a/res/shaders/lib/lighting.glsl +++ b/res/shaders/lib/lighting.glsl @@ -1,12 +1,6 @@ #ifndef LIGHTING_GLSL_ #define LIGHTING_GLSL_ -uniform float u_fogFactor; -uniform float u_fogCurve; -uniform float u_weatherFogOpacity; -uniform float u_weatherFogDencity; -uniform float u_weatherFogCurve; - float calc_torch_light(vec3 normal, vec3 modelpos) { return max(0.0, 1.0 - distance(u_cameraPos, modelpos) / u_torchlightDistance) * max(0.0, -dot(normal, normalize(modelpos - u_cameraPos))); @@ -16,13 +10,4 @@ vec3 calc_screen_normal(vec3 normal) { return transpose(inverse(mat3(u_view * u_model))) * normal; } -float calc_fog(float depth) { - return min( - 1.0, - max(pow(depth * u_fogFactor, u_fogCurve), - min(pow(depth * u_weatherFogDencity, u_weatherFogCurve), - u_weatherFogOpacity)) - ); -} - #endif // LIGHTING_GLSL_ diff --git a/res/shaders/lib/shadows.glsl b/res/shaders/lib/shadows.glsl index b66f8a4b..db37cdaa 100644 --- a/res/shaders/lib/shadows.glsl +++ b/res/shaders/lib/shadows.glsl @@ -10,14 +10,14 @@ uniform int u_shadowsRes; uniform float u_shadowsOpacity; uniform float u_shadowsSoftness; -float calc_shadow() { +float calc_shadow(vec4 modelPos, vec3 realnormal, float distance) { #ifdef ENABLE_SHADOWS float step = 1.0 / float(u_shadowsRes); float s = pow(abs(cos(u_dayTime * PI2)), 0.25) * u_shadowsOpacity; - vec3 normalOffset = a_realnormal * (a_distance > 64.0 ? 0.2 : 0.04); - int shadowIdx = a_distance > 80.0 ? 1 : 0; + vec3 normalOffset = realnormal * (distance > 64.0 ? 0.2 : 0.04); + int shadowIdx = distance > 80.0 ? 1 : 0; - vec4 mpos = u_shadowsMatrix[shadowIdx] * vec4(a_modelpos.xyz + normalOffset, 1.0); + vec4 mpos = u_shadowsMatrix[shadowIdx] * vec4(modelPos.xyz + normalOffset, 1.0); vec3 projCoords = mpos.xyz / mpos.w; projCoords = projCoords * 0.5 + 0.5; projCoords.z -= 0.00001 / u_shadowsRes; @@ -26,7 +26,7 @@ float calc_shadow() { } float shadow = 0.0; - if (dot(a_realnormal, u_sunDir) < 0.0) { + if (dot(realnormal, u_sunDir) < 0.0) { // 3x3 kernel for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index 51f0b9c6..2767390b 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -25,8 +25,7 @@ uniform bool u_debugNormals; #include void main() { - float shadow = calc_shadow(); - vec3 fogColor = texture(u_skybox, a_dir).rgb; + //vec3 fogColor = texture(u_skybox, a_dir).rgb; vec4 texColor = texture(u_texture0, a_texCoord); float alpha = texColor.a; if (u_alphaClip) { @@ -43,8 +42,8 @@ void main() { texColor.rgb *= a_normal * 0.5 + 0.5; } f_color = texColor; - f_color.rgb *= min(vec3(1.0), a_torchLight.rgb + a_skyLight * shadow); - f_color = mix(f_color, vec4(fogColor, 1.0), a_fog); + 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); f_color.a = alpha; f_position = vec4(a_position, 1.0); f_normal = vec4(a_normal, 1.0); diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index 2f0f084a..927b8519 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -28,6 +28,7 @@ uniform vec3 u_torchlightColor; uniform float u_torchlightDistance; #include +#include void main() { a_modelpos = u_model * vec4(v_position, 1.0f); diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index 08180d75..acb491e4 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -4,6 +4,8 @@ #include "debug/Logger.hpp" +using namespace advanced_pipeline; + static debug::Logger logger("gl-gbuffer"); void GBuffer::createColorBuffer() { @@ -162,20 +164,30 @@ void GBuffer::unbind() { } void GBuffer::bindBuffers() const { - glActiveTexture(GL_TEXTURE2); + glActiveTexture(GL_TEXTURE0 + TARGET_NORMALS); glBindTexture(GL_TEXTURE_2D, normalsBuffer); - glActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE0 + TARGET_POSITIONS); glBindTexture(GL_TEXTURE_2D, positionsBuffer); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0 + TARGET_COLOR); glBindTexture(GL_TEXTURE_2D, colorBuffer); + + if (TARGET_COLOR != 0) + glActiveTexture(GL_TEXTURE0); } void GBuffer::bindSSAOBuffer() const { glBindTexture(GL_TEXTURE_2D, ssaoBuffer); } +void GBuffer::bindDepthBuffer() { + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, + GL_DEPTH_BUFFER_BIT, GL_NEAREST); +} + void GBuffer::resize(uint width, uint height) { if (this->width == width && this->height == height) { return; diff --git a/src/graphics/core/GBuffer.hpp b/src/graphics/core/GBuffer.hpp index 7fa66e1a..8885db7d 100644 --- a/src/graphics/core/GBuffer.hpp +++ b/src/graphics/core/GBuffer.hpp @@ -16,6 +16,8 @@ public: void bindBuffers() const; void bindSSAOBuffer() const; + void bindDepthBuffer(); + void resize(uint width, uint height); uint getWidth() const; diff --git a/src/graphics/core/PostEffect.cpp b/src/graphics/core/PostEffect.cpp index 317f215a..b0c34571 100644 --- a/src/graphics/core/PostEffect.cpp +++ b/src/graphics/core/PostEffect.cpp @@ -100,6 +100,10 @@ Shader& PostEffect::use() { return *shader; } +Shader& PostEffect::getShader() { + return *shader; +} + float PostEffect::getIntensity() const { return intensity; } diff --git a/src/graphics/core/PostEffect.hpp b/src/graphics/core/PostEffect.hpp index 6dac6748..a29fd404 100644 --- a/src/graphics/core/PostEffect.hpp +++ b/src/graphics/core/PostEffect.hpp @@ -48,6 +48,8 @@ public: Shader& use(); + Shader& getShader(); + float getIntensity() const; void setIntensity(float value); diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index 4a2608f3..652b3b36 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -12,6 +12,8 @@ #include #include +using namespace advanced_pipeline; + PostProcessing::PostProcessing(size_t effectSlotsCount) : effectSlots(effectSlotsCount) { // Fullscreen quad mesh bulding @@ -74,28 +76,46 @@ void PostProcessing::refreshFbos(uint width, uint height) { } } +void PostProcessing::bindDepthBuffer() { + gbuffer->bindDepthBuffer(); +} + void PostProcessing::configureEffect( const DrawContext& context, PostEffect& effect, Shader& shader, float timer, const Camera& camera, - uint shadowMap + uint shadowMap, + uint shadowMap2, + const glm::mat4& shadowMatrix, + const glm::mat4& shadowMatrix2, + uint shadowMapResolution ) { const auto& viewport = context.getViewport(); - shader.uniform1i("u_screen", 0); + shader.uniform1i("u_screen", TARGET_COLOR); + shader.uniform1i("u_skybox", TARGET_SKYBOX); if (gbuffer) { - shader.uniform1i("u_position", 1); - shader.uniform1i("u_normal", 2); + shader.uniform1i("u_position", TARGET_POSITIONS); + shader.uniform1i("u_normal", TARGET_NORMALS); } - shader.uniform1i("u_noise", 3); // used in SSAO pass - shader.uniform1i("u_ssao", 3); + shader.uniform1i("u_noise", TARGET_SSAO); // used in SSAO pass + shader.uniform1i("u_ssao", TARGET_SSAO); - shader.uniform1i("u_shadows", 4); + shader.uniform1i("u_shadows[0]", TARGET_SHADOWS0); + shader.uniform1i("u_shadows[1]", TARGET_SHADOWS1); + shader.uniformMatrix("u_shadowsMatrix[0]", shadowMatrix); + shader.uniformMatrix("u_shadowsMatrix[1]", shadowMatrix2); + shader.uniform1f("u_shadowsOpacity", 1.0f); + shader.uniform1f("u_shadowsSoftness", 1.0f); + shader.uniform1i("u_shadowsRes", shadowMapResolution); shader.uniform2i("u_screenSize", viewport); + shader.uniform3f("u_cameraPos", camera.position); shader.uniform1f("u_timer", timer); shader.uniform1i("u_enableShadows", shadowMap != 0); shader.uniformMatrix("u_projection", camera.getProjection()); + shader.uniformMatrix("u_view", camera.getView()); + shader.uniformMatrix("u_inverseView", glm::inverse(camera.getView())); } void PostProcessing::render( @@ -103,7 +123,11 @@ void PostProcessing::render( const Assets& assets, float timer, const Camera& camera, - uint shadowMap + uint shadowMap, + uint shadowMap2, + const glm::mat4& shadowMatrix, + const glm::mat4& shadowMatrix2, + uint shadowMapResolution ) { if (fbo == nullptr && gbuffer == nullptr) { throw std::runtime_error("'use(...)' was never called"); @@ -118,25 +142,40 @@ void PostProcessing::render( const auto& vp = context.getViewport(); refreshFbos(vp.x, vp.y); - glActiveTexture(GL_TEXTURE4); + glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS0); glBindTexture(GL_TEXTURE_2D, shadowMap); + glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS1); + glBindTexture(GL_TEXTURE_2D, shadowMap2); + + // Generating ssao if (gbuffer) { gbuffer->bindBuffers(); - glActiveTexture(GL_TEXTURE3); + glActiveTexture(GL_TEXTURE0 + TARGET_SSAO); glBindTexture(GL_TEXTURE_2D, noiseTexture); glActiveTexture(GL_TEXTURE0); auto& ssaoEffect = assets.require("ssao"); auto& shader = ssaoEffect.use(); - configureEffect(context, ssaoEffect, shader, timer, camera, shadowMap); + configureEffect( + context, + ssaoEffect, + shader, + timer, + camera, + shadowMap, + shadowMap2, + shadowMatrix, + shadowMatrix2, + shadowMapResolution + ); gbuffer->bindSSAO(); quadMesh->draw(); gbuffer->unbind(); - glActiveTexture(GL_TEXTURE3); + glActiveTexture(GL_TEXTURE0 + TARGET_SSAO); gbuffer->bindSSAOBuffer(); } else { glActiveTexture(GL_TEXTURE0); @@ -148,7 +187,18 @@ void PostProcessing::render( gbuffer ? "deferred_lighting" : "default" ); auto& shader = effect.use(); - configureEffect(context, effect, shader, timer, camera, shadowMap); + configureEffect( + context, + effect, + shader, + timer, + camera, + shadowMap, + shadowMap2, + shadowMatrix, + shadowMatrix2, + shadowMapResolution + ); quadMesh->draw(); return; } @@ -162,7 +212,18 @@ void PostProcessing::render( continue; } auto& shader = effect->use(); - configureEffect(context, *effect, shader, timer, camera, shadowMap); + configureEffect( + context, + *effect, + shader, + timer, + camera, + shadowMap, + shadowMap2, + shadowMatrix, + shadowMatrix2, + shadowMapResolution + ); if (currentPass > 1) { fbo->getTexture()->bind(); diff --git a/src/graphics/core/PostProcessing.hpp b/src/graphics/core/PostProcessing.hpp index dc0779ed..fc49c950 100644 --- a/src/graphics/core/PostProcessing.hpp +++ b/src/graphics/core/PostProcessing.hpp @@ -44,7 +44,11 @@ public: const Assets& assets, float timer, const Camera& camera, - uint shadowMap + uint shadowMap, + uint shadowMap2, + const glm::mat4& shadowMatrix, + const glm::mat4& shadowMatrix2, + uint shadowMapResolution ); void setEffect(size_t slot, std::shared_ptr effect); @@ -55,6 +59,7 @@ public: std::unique_ptr toImage(); Framebuffer* getFramebuffer() const; + void bindDepthBuffer(); private: void configureEffect( const DrawContext& context, @@ -62,7 +67,11 @@ private: Shader& shader, float timer, const Camera& camera, - uint shadowMap + uint shadowMap, + uint shadowMap2, + const glm::mat4& shadowMatrix, + const glm::mat4& shadowMatrix2, + uint shadowMapResolution ); void refreshFbos(uint width, uint height); diff --git a/src/graphics/core/Shader.cpp b/src/graphics/core/Shader.cpp index 24ea0241..da6ea342 100644 --- a/src/graphics/core/Shader.cpp +++ b/src/graphics/core/Shader.cpp @@ -51,6 +51,12 @@ void Shader::uniformMatrix(const std::string& name, const glm::mat4& matrix) { ); } +void Shader::uniformMatrix(const std::string& name, const glm::mat3& matrix) { + glUniformMatrix3fv( + getUniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix) + ); +} + void Shader::uniform1i(const std::string& name, int x){ glUniform1i(getUniformLocation(name), x); } diff --git a/src/graphics/core/Shader.hpp b/src/graphics/core/Shader.hpp index 8f1aeb33..4808172e 100644 --- a/src/graphics/core/Shader.hpp +++ b/src/graphics/core/Shader.hpp @@ -33,6 +33,7 @@ public: void use(); void uniformMatrix(const std::string&, const glm::mat4& matrix); + void uniformMatrix(const std::string&, const glm::mat3& matrix); void uniform1i(const std::string& name, int x); void uniform1f(const std::string& name, float x); void uniform2f(const std::string& name, float x, float y); diff --git a/src/graphics/core/commons.hpp b/src/graphics/core/commons.hpp index 2ed03db1..ffc89068 100644 --- a/src/graphics/core/commons.hpp +++ b/src/graphics/core/commons.hpp @@ -50,6 +50,16 @@ enum class CursorShape { LAST=NOT_ALLOWED }; +namespace advanced_pipeline { + inline constexpr int TARGET_COLOR = 0; + inline constexpr int TARGET_SKYBOX = 1; + inline constexpr int TARGET_POSITIONS = 2; + inline constexpr int TARGET_NORMALS = 3; + inline constexpr int TARGET_SSAO = 4; + inline constexpr int TARGET_SHADOWS0 = 5; + inline constexpr int TARGET_SHADOWS1 = 6; +} + VC_ENUM_METADATA(CursorShape) {"arrow", CursorShape::ARROW}, {"text", CursorShape::TEXT}, diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index 2687dc20..ceb455d1 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -18,9 +18,7 @@ #include #include -#ifndef M_PI -#define M_PI 3.141592 -#endif // M_PI +using namespace advanced_pipeline; const int STARS_COUNT = 3000; const int STARS_SEED = 632; @@ -47,14 +45,6 @@ Skybox::Skybox(uint size, Shader& shader) mesh = std::make_unique>(vertices, 6); - sprites.push_back(SkySprite { - "misc/moon_flare", - glm::pi() * 0.5f, - 0.5f, - false, - glm::pi() * 0.25f, - }); - sprites.push_back(SkySprite { "misc/moon", glm::pi() * 0.5f, @@ -62,6 +52,14 @@ Skybox::Skybox(uint size, Shader& shader) false, glm::pi() * 0.25f, }); + + sprites.push_back(SkySprite { + "misc/moon_flare", + glm::pi() * 0.5f, + 0.5f, + false, + glm::pi() * 0.25f, + }); sprites.push_back(SkySprite { "misc/sun", @@ -118,6 +116,8 @@ void Skybox::draw( { const glm::uvec2& viewport = pctx.getViewport(); + glActiveTexture(GL_TEXTURE0); + drawBackground(camera, assets, viewport.x, viewport.y); DrawContext ctx = pctx.sub(); @@ -130,22 +130,23 @@ void Skybox::draw( batch3d->begin(); float angle = daytime * glm::pi() * 2.0f; - float opacity = glm::pow(1.0f-fog, 7.0f); + float opacity = glm::pow(1.0f - fog, 7.0f); + float depthScale = 1e3; for (auto& sprite : sprites) { batch3d->texture(assets.get(sprite.texture)); float sangle = daytime * glm::pi() * 2.0 + sprite.phase; - float distance = sprite.distance; + float distance = sprite.distance * depthScale; glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), -sangle + glm::pi() * 0.5f, glm::vec3(0, 0, -1)); rotation = glm::rotate(rotation, sprite.altitude, glm::vec3(1, 0, 0)); glm::vec3 pos = glm::vec4(0, distance, 0, 1) * rotation; - glm::vec3 up = glm::vec4(1, 0, 0, 1) * rotation; - glm::vec3 right = glm::vec4(0, 0, 1, 1) * rotation; + glm::vec3 up = glm::vec4(depthScale, 0, 0, 1) * rotation; + glm::vec3 right = glm::vec4(0, 0, depthScale, 1) * rotation; glm::vec4 tint (1,1,1, opacity); if (!sprite.emissive) { - tint *= 0.6f+std::cos(angle)*0.4; + tint *= 0.6f + std::cos(angle)*0.4; } batch3d->sprite(pos, right, up, 1, 1, UVRegion(), tint); @@ -167,10 +168,10 @@ void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality) assert(cubemap != nullptr); ready = true; - glActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE0 + TARGET_SKYBOX); cubemap->bind(); shader.use(); - t *= glm::pi()*2.0f; + t *= glm::two_pi(); lightDir = glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f)); shader.uniform1i("u_quality", quality); @@ -237,13 +238,13 @@ void Skybox::refreshFace(uint face, Cubemap* cubemap) { } void Skybox::bind() const { - glActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE0 + TARGET_SKYBOX); fbo->getTexture()->bind(); glActiveTexture(GL_TEXTURE0); } void Skybox::unbind() const { - glActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE0 + TARGET_SKYBOX); fbo->getTexture()->unbind(); glActiveTexture(GL_TEXTURE0); } diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 3f74d8fb..390aeb32 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -54,8 +54,11 @@ #include "Emitter.hpp" #include "TextNote.hpp" +using namespace advanced_pipeline; + inline constexpr size_t BATCH3D_CAPACITY = 4096; inline constexpr size_t MODEL_BATCH_CAPACITY = 20'000; +inline constexpr GLenum TEXTURE_MAIN = GL_TEXTURE0; bool WorldRenderer::showChunkBorders = false; bool WorldRenderer::showEntitiesDebug = false; @@ -141,15 +144,15 @@ void WorldRenderer::setupWorldShader( shader.uniform1f("u_shadowsOpacity", 1.0f - cloudsIntensity); // TODO: make it configurable shader.uniform1f("u_shadowsSoftness", 1.0f + cloudsIntensity * 4); // TODO: make it configurable - glActiveTexture(GL_TEXTURE4); - shader.uniform1i("u_shadows[0]", 4); + glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS0); + shader.uniform1i("u_shadows[0]", TARGET_SHADOWS0); glBindTexture(GL_TEXTURE_2D, shadowMap->getDepthMap()); - glActiveTexture(GL_TEXTURE5); - shader.uniform1i("u_shadows[1]", 5); + glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS1); + shader.uniform1i("u_shadows[1]", TARGET_SHADOWS1); glBindTexture(GL_TEXTURE_2D, wideShadowMap->getDepthMap()); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(TEXTURE_MAIN); } auto indices = level.content.getIndices(); @@ -438,9 +441,11 @@ void WorldRenderer::draw( auto& mainShader = assets.require("main"); auto& entityShader = assets.require("entity"); + auto& deferredShader = assets.require("deferred_lighting").getShader(); const auto& settings = engine.getSettings(); + gbufferPipeline = settings.graphics.advancedRender.get(); - int shadowsQuality = settings.graphics.shadowsQuality.get(); + int shadowsQuality = settings.graphics.shadowsQuality.get() * gbufferPipeline; int resolution = 512 << shadowsQuality; if (shadowsQuality > 0 && !shadows) { shadowMap = std::make_unique(resolution); @@ -449,6 +454,7 @@ void WorldRenderer::draw( Shader::preprocessor->define("ENABLE_SHADOWS", "true"); mainShader.recompile(); entityShader.recompile(); + deferredShader.recompile(); } else if (shadowsQuality == 0 && shadows) { shadowMap.reset(); wideShadowMap.reset(); @@ -456,6 +462,7 @@ void WorldRenderer::draw( Shader::preprocessor->undefine("ENABLE_SHADOWS"); mainShader.recompile(); entityShader.recompile(); + deferredShader.recompile(); } if (shadows && shadowMap->getResolution() != resolution) { shadowMap = std::make_unique(resolution); @@ -489,9 +496,6 @@ void WorldRenderer::draw( display::clearDepth(); - // Drawing background sky plane - skybox->draw(pctx, camera, assets, worldInfo.daytime, clouds); - /* Actually world render with depth buffer on */ { DrawContext ctx = wctx.sub(); ctx.setDepthTest(true); @@ -506,19 +510,32 @@ void WorldRenderer::draw( } } } - { - DrawContext ctx = wctx.sub(); - texts->render(ctx, camera, settings, hudVisible, true); - } + 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); postProcessing.render( pctx, assets, timer, camera, - shadows ? shadowMap->getDepthMap() : 0 + shadows ? shadowMap->getDepthMap() : 0, + shadows ? wideShadowMap->getDepthMap() : 0, + shadowCamera.getProjView(), + 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(); ctx.setDepthTest(true); diff --git a/src/window/Camera.hpp b/src/window/Camera.hpp index 11838234..677e0ede 100644 --- a/src/window/Camera.hpp +++ b/src/window/Camera.hpp @@ -19,7 +19,7 @@ public: bool perspective = true; bool flipped = false; float near = 0.05f; - float far = 1500.0f; + float far = 1e4f; bool projset = false; glm::mat4 projection; From 599b0cc3808e030a02b3aa71ae2ad883ac4c574d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 9 Jul 2025 00:42:28 +0300 Subject: [PATCH 36/47] fix msvc build --- src/graphics/render/Skybox.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index ceb455d1..84ac8310 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -78,7 +78,9 @@ void Skybox::drawBackground( auto backShader = assets.get("background"); backShader->use(); backShader->uniformMatrix("u_view", camera.getView(false)); - backShader->uniform1f("u_zoom", camera.zoom*camera.getFov()/(M_PI*0.5f)); + backShader->uniform1f( + "u_zoom", camera.zoom * camera.getFov() / glm::half_pi() + ); backShader->uniform1f("u_ar", float(width)/float(height)); backShader->uniform1i("u_skybox", 1); bind(); @@ -139,7 +141,11 @@ void Skybox::draw( float sangle = daytime * glm::pi() * 2.0 + sprite.phase; float distance = sprite.distance * depthScale; - glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), -sangle + glm::pi() * 0.5f, glm::vec3(0, 0, -1)); + glm::mat4 rotation = glm::rotate( + glm::mat4(1.0f), + -sangle + glm::pi() * 0.5f, + glm::vec3(0, 0, -1) + ); rotation = glm::rotate(rotation, sprite.altitude, glm::vec3(1, 0, 0)); glm::vec3 pos = glm::vec4(0, distance, 0, 1) * rotation; glm::vec3 up = glm::vec4(depthScale, 0, 0, 1) * rotation; From ac9772cd67686347fed22c8c35bbedaec884e778 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 17:31:55 +0300 Subject: [PATCH 37/47] 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()); From 8a3306ed412d9be06e5159472e72fa4d9af52e11 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 19:18:02 +0300 Subject: [PATCH 38/47] fix stars and skybox render --- src/graphics/core/PostProcessing.cpp | 2 ++ src/graphics/render/Skybox.cpp | 33 +++++++++++++++++++++------ src/graphics/render/Skybox.hpp | 2 ++ src/graphics/render/WorldRenderer.cpp | 6 ++--- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index c2d24e60..1c343006 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -12,6 +12,8 @@ #include #include +// TODO: REFACTOR WHOLE RENDER ENGINE + using namespace advanced_pipeline; PostProcessing::PostProcessing(size_t effectSlotsCount) diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index 84ac8310..eb90feef 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -91,20 +91,29 @@ void Skybox::drawBackground( void Skybox::drawStars(float angle, float opacity) { batch3d->texture(nullptr); random.setSeed(STARS_SEED); + + glm::mat4 rotation = glm::rotate( + glm::mat4(1.0f), + -angle + glm::pi() * 0.5f, + glm::vec3(0, 0, -1) + ); + rotation = glm::rotate(rotation, sunAltitude, glm::vec3(1, 0, 0)); + + float depth = 1e3; for (int i = 0; i < STARS_COUNT; i++) { float rx = (random.randFloat()) - 0.5f; float ry = (random.randFloat()) - 0.5f; - float z = (random.randFloat()) - 0.5f; - float x = rx * std::sin(angle) + ry * -std::cos(angle); - float y = rx * std::cos(angle) + ry * std::sin(angle); + float rz = (random.randFloat()) - 0.5f; + + glm::vec3 pos = glm::vec4(rx, ry, rz, 1) * rotation; float sopacity = random.randFloat(); - if (y < 0.0f) + if (pos.y < 0.0f) continue; - sopacity *= (0.2f+std::sqrt(std::cos(angle))*0.5f) - 0.05f; + sopacity *= (0.2f + std::sqrt(std::cos(angle)) * 0.5f) - 0.05f; glm::vec4 tint (1,1,1, sopacity * opacity); - batch3d->point(glm::vec3(x, y, z), tint); + batch3d->point(pos * depth, tint); } batch3d->flushPoints(); } @@ -158,7 +167,7 @@ void Skybox::draw( up, 1, 1, UVRegion(), tint); } batch3d->flush(); - //drawStars(angle, opacity); + drawStars(angle, opacity); } void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality) { @@ -180,6 +189,16 @@ void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality) t *= glm::two_pi(); lightDir = glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f)); + + float sunAngle = glm::radians((t / glm::two_pi() - 0.25f) * 360.0f); + float x = -glm::cos(sunAngle + glm::pi() * 0.5f) * glm::radians(sunAltitude); + float y = sunAngle - glm::pi() * 0.5f; + float z = glm::radians(0.0f); + rotation = glm::rotate(glm::mat4(1.0f), y, glm::vec3(0, 1, 0)); + rotation = glm::rotate(rotation, x, glm::vec3(1, 0, 0)); + rotation = glm::rotate(rotation, z, glm::vec3(0, 0, 1)); + lightDir = glm::vec3(rotation * glm::vec4(0, 0, -1, 1)); + shader.uniform1i("u_quality", quality); shader.uniform1f("u_mie", mie); shader.uniform1f("u_fog", mie - 1.0f); diff --git a/src/graphics/render/Skybox.hpp b/src/graphics/render/Skybox.hpp index c1184a14..f2b81876 100644 --- a/src/graphics/render/Skybox.hpp +++ b/src/graphics/render/Skybox.hpp @@ -48,6 +48,8 @@ class Skybox { float prevMie = -1.0f; float prevT = -1.0f; + float sunAltitude = 45.0f; + glm::mat4 rotation; void drawStars(float angle, float opacity); void drawBackground( diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 053bd222..5a1fe21a 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -60,6 +60,7 @@ using namespace advanced_pipeline; inline constexpr size_t BATCH3D_CAPACITY = 4096; inline constexpr size_t MODEL_BATCH_CAPACITY = 20'000; inline constexpr GLenum TEXTURE_MAIN = GL_TEXTURE0; +inline constexpr int MIN_SHADOW_MAP_RES = 512; bool WorldRenderer::showChunkBorders = false; bool WorldRenderer::showEntitiesDebug = false; @@ -246,7 +247,7 @@ void WorldRenderer::renderBlockSelection() { const glm::vec3 center = glm::vec3(pos) + hitbox.center(); const glm::vec3 size = hitbox.size(); lineBatch->box( - center, size + glm::vec3(0.01), glm::vec4(0.f, 0.f, 0.f, 0.5f) + center, size + glm::vec3(0.01), glm::vec4(0.f, 0.f, 0.f, 1.0f) ); if (debug) { lineBatch->line( @@ -380,7 +381,6 @@ void WorldRenderer::generateShadowsMap( sunAngle - glm::pi() * 0.5f, glm::radians(0.0f) ); - shadowCamera.updateVectors(); shadowCamera.position -= shadowCamera.front * 500.0f; shadowCamera.position += shadowCamera.up * 0.0f; @@ -433,7 +433,7 @@ void WorldRenderer::draw( gbufferPipeline = settings.graphics.advancedRender.get(); int shadowsQuality = settings.graphics.shadowsQuality.get() * gbufferPipeline; - int resolution = 512 << shadowsQuality; + int resolution = MIN_SHADOW_MAP_RES << shadowsQuality; if (shadowsQuality > 0 && !shadows) { shadowMap = std::make_unique(resolution); wideShadowMap = std::make_unique(resolution); From 5ec9f14021810352094d42f8712ea0ca9da0f9f7 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 21:09:23 +0300 Subject: [PATCH 39/47] add emission gbuffer attachment --- res/shaders/effect.glslf | 1 + res/shaders/effects/deferred_lighting.glsl | 2 +- res/shaders/effects/ssao.glsl | 1 + res/shaders/entity.glslf | 2 + res/shaders/main.glslf | 4 +- res/shaders/main.glslv | 2 + src/graphics/core/GBuffer.cpp | 62 ++++++++++++++++++---- src/graphics/core/GBuffer.hpp | 2 + src/graphics/core/PostProcessing.cpp | 1 + src/graphics/core/commons.hpp | 7 +-- src/graphics/render/BlocksRenderer.cpp | 39 ++++++++------ src/graphics/render/BlocksRenderer.hpp | 9 +++- 12 files changed, 101 insertions(+), 31 deletions(-) diff --git a/res/shaders/effect.glslf b/res/shaders/effect.glslf index be50d779..2b6307ef 100644 --- a/res/shaders/effect.glslf +++ b/res/shaders/effect.glslf @@ -4,6 +4,7 @@ out vec4 f_color; uniform sampler2D u_screen; uniform sampler2D u_position; uniform sampler2D u_normal; +uniform sampler2D u_emission; uniform sampler2D u_noise; uniform sampler2D u_ssao; uniform samplerCube u_skybox; diff --git a/res/shaders/effects/deferred_lighting.glsl b/res/shaders/effects/deferred_lighting.glsl index f21b1b4a..5df6b148 100644 --- a/res/shaders/effects/deferred_lighting.glsl +++ b/res/shaders/effects/deferred_lighting.glsl @@ -16,7 +16,7 @@ vec4 effect() { vec3 normal = transpose(mat3(u_view)) * texture(u_normal, v_uv).xyz; vec3 dir = modelpos.xyz - u_cameraPos; #ifdef ENABLE_SHADOWS - ssao *= calc_shadow(modelpos, normal, length(pos)); + ssao *= max(calc_shadow(modelpos, normal, length(pos)), texture(u_emission, v_uv).r); #endif vec3 fogColor = texture(u_skybox, dir).rgb; float fog = calc_fog(length(u_view * vec4((modelpos.xyz - u_cameraPos) * FOG_POS_SCALE, 0.0)) / 256.0); diff --git a/res/shaders/effects/ssao.glsl b/res/shaders/effects/ssao.glsl index 399f2fde..508d74e7 100644 --- a/res/shaders/effects/ssao.glsl +++ b/res/shaders/effects/ssao.glsl @@ -29,6 +29,7 @@ vec4 effect() { occlusion += (sampleDepth >= samplePos.z + u_bias ? 1.0 : 0.0) * rangeCheck; } occlusion = min(1.0, 1.05 - (occlusion / u_kernelSize)); + occlusion = max(occlusion, texture(u_emission, v_uv).r); float z = -position.z * 0.01; z = max(0.0, 1.0 - z); diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index 7c916955..f9675708 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -1,6 +1,7 @@ layout (location = 0) out vec4 f_color; layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; +layout (location = 3) out vec4 f_emission; in float a_distance; in float a_fog; @@ -40,4 +41,5 @@ void main() { f_color.a = alpha; f_position = vec4(a_position, 1.0); f_normal = vec4(a_normal, 1.0); + f_emission = vec4(0.0); } diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index ff6816a7..39797aa0 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -1,6 +1,7 @@ layout (location = 0) out vec4 f_color; layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; +layout (location = 3) out vec4 f_emission; in float a_distance; in float a_fog; @@ -12,6 +13,7 @@ in vec3 a_realnormal; in vec3 a_skyLight; in vec4 a_modelpos; in vec4 a_torchLight; +in float a_emission; uniform sampler2D u_texture0; uniform samplerCube u_skybox; @@ -47,8 +49,8 @@ void main() { 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); + f_emission = vec4(a_emission); } diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index 927b8519..8fd38d20 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -15,6 +15,7 @@ out vec3 a_realnormal; out vec4 a_torchLight; out vec3 a_skyLight; out vec4 a_modelpos; +out float a_emission; uniform mat4 u_model; uniform mat4 u_proj; @@ -51,6 +52,7 @@ void main() { mat4 viewmodel = u_view * u_model; a_distance = length(viewmodel * vec4(pos3d, 0.0)); a_fog = calc_fog(length(viewmodel * vec4(pos3d * FOG_POS_SCALE, 0.0)) / 256.0); + a_emission = v_normal.w; vec4 viewmodelpos = u_view * a_modelpos; a_position = viewmodelpos.xyz; diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index 8b154e91..6307a353 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -8,6 +8,8 @@ using namespace advanced_pipeline; static debug::Logger logger("gl-gbuffer"); +// TODO: REFACTOR + void GBuffer::createColorBuffer() { glGenTextures(1, &colorBuffer); glBindTexture(GL_TEXTURE_2D, colorBuffer); @@ -64,7 +66,7 @@ void GBuffer::createNormalsBuffer() { width, height, 0, - GL_RGBA, + GL_RGB, GL_FLOAT, nullptr ); @@ -77,6 +79,29 @@ void GBuffer::createNormalsBuffer() { ); } +void GBuffer::createEmissionBuffer() { + glGenTextures(1, &emissionBuffer); + glBindTexture(GL_TEXTURE_2D, emissionBuffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_R8, + width, + height, + 0, + GL_RED, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, emissionBuffer, 0 + ); +} + void GBuffer::createDepthBuffer() { glGenRenderbuffers(1, &depthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); @@ -113,16 +138,21 @@ GBuffer::GBuffer(uint width, uint height) : width(width), height(height) { createColorBuffer(); createPositionsBuffer(); createNormalsBuffer(); + createEmissionBuffer(); - GLenum attachments[3] = { - GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 + GLenum attachments[4] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3, }; - glDrawBuffers(3, attachments); + glDrawBuffers(4, attachments); createDepthBuffer(); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - logger.error() << "gbuffer is not complete!"; + int status; + if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { + logger.error() << "gbuffer is not complete! (" << status << ")"; } glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -134,8 +164,10 @@ GBuffer::GBuffer(uint width, uint height) : width(width), height(height) { ); GLenum ssaoAttachments[1] = {GL_COLOR_ATTACHMENT0}; glDrawBuffers(1, ssaoAttachments); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - logger.error() << "SSAO framebuffer is not complete!"; + + + if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { + logger.error() << "SSAO framebuffer is not complete! (" << status << ")"; } glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -144,6 +176,7 @@ GBuffer::~GBuffer() { glDeleteTextures(1, &colorBuffer); glDeleteTextures(1, &positionsBuffer); glDeleteTextures(1, &normalsBuffer); + glDeleteTextures(1, &emissionBuffer); glDeleteTextures(1, &ssaoBuffer); glDeleteRenderbuffers(1, &depthBuffer); glDeleteFramebuffers(1, &fbo); @@ -164,6 +197,9 @@ void GBuffer::unbind() { } void GBuffer::bindBuffers() const { + glActiveTexture(GL_TEXTURE0 + TARGET_EMISSION); + glBindTexture(GL_TEXTURE_2D, emissionBuffer); + glActiveTexture(GL_TEXTURE0 + TARGET_NORMALS); glBindTexture(GL_TEXTURE_2D, normalsBuffer); @@ -227,12 +263,20 @@ void GBuffer::resize(uint width, uint height) { glBindTexture(GL_TEXTURE_2D, normalsBuffer); glTexImage2D( - GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr + GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normalsBuffer, 0 ); + glBindTexture(GL_TEXTURE_2D, emissionBuffer); + glTexImage2D( + GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, GL_LUMINANCE, GL_FLOAT, nullptr + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, emissionBuffer, 0 + ); + glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); diff --git a/src/graphics/core/GBuffer.hpp b/src/graphics/core/GBuffer.hpp index ec3cc045..fa3e13b3 100644 --- a/src/graphics/core/GBuffer.hpp +++ b/src/graphics/core/GBuffer.hpp @@ -32,6 +32,7 @@ private: uint colorBuffer; uint positionsBuffer; uint normalsBuffer; + uint emissionBuffer; uint depthBuffer; uint ssaoFbo; uint ssaoBuffer; @@ -39,6 +40,7 @@ private: void createColorBuffer(); void createPositionsBuffer(); void createNormalsBuffer(); + void createEmissionBuffer(); void createDepthBuffer(); void createSSAOBuffer(); }; diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index 1c343006..85b56067 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -102,6 +102,7 @@ void PostProcessing::configureEffect( if (gbuffer) { shader.uniform1i("u_position", TARGET_POSITIONS); shader.uniform1i("u_normal", TARGET_NORMALS); + shader.uniform1i("u_emission", TARGET_EMISSION); } shader.uniform1i("u_noise", TARGET_SSAO); // used in SSAO pass shader.uniform1i("u_ssao", TARGET_SSAO); diff --git a/src/graphics/core/commons.hpp b/src/graphics/core/commons.hpp index ffc89068..8785cec1 100644 --- a/src/graphics/core/commons.hpp +++ b/src/graphics/core/commons.hpp @@ -55,9 +55,10 @@ namespace advanced_pipeline { inline constexpr int TARGET_SKYBOX = 1; inline constexpr int TARGET_POSITIONS = 2; inline constexpr int TARGET_NORMALS = 3; - inline constexpr int TARGET_SSAO = 4; - inline constexpr int TARGET_SHADOWS0 = 5; - inline constexpr int TARGET_SHADOWS1 = 6; + inline constexpr int TARGET_EMISSION = 4; + inline constexpr int TARGET_SSAO = 5; + inline constexpr int TARGET_SHADOWS0 = 6; + inline constexpr int TARGET_SHADOWS1 = 7; } VC_ENUM_METADATA(CursorShape) diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index f7b1abe1..2fedd15b 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -39,9 +39,13 @@ BlocksRenderer::~BlocksRenderer() { /// Basic vertex add method void BlocksRenderer::vertex( - const glm::vec3& coord, float u, float v, const glm::vec4& light, const glm::vec3& normal + const glm::vec3& coord, + float u, + float v, + const glm::vec4& light, + const glm::vec3& normal, + float emission ) { - vertexBuffer[vertexCount].position = coord; vertexBuffer[vertexCount].uv = {u,v}; @@ -49,11 +53,13 @@ void BlocksRenderer::vertex( vertexBuffer[vertexCount].normal[0] = static_cast(normal.r * 127 + 128); vertexBuffer[vertexCount].normal[1] = static_cast(normal.g * 127 + 128); vertexBuffer[vertexCount].normal[2] = static_cast(normal.b * 127 + 128); + vertexBuffer[vertexCount].normal[3] = static_cast(emission * 255); vertexBuffer[vertexCount].color[0] = static_cast(light.r * 255); vertexBuffer[vertexCount].color[1] = static_cast(light.g * 255); vertexBuffer[vertexCount].color[2] = static_cast(light.b * 255); vertexBuffer[vertexCount].color[3] = static_cast(light.a * 255); + vertexCount++; } @@ -86,10 +92,10 @@ void BlocksRenderer::face( auto Y = axisY * h; auto Z = axisZ * d; float s = 0.5f; - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, lights[0] * tint, axisZ); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, lights[1] * tint, axisZ); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, lights[2] * tint, axisZ); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, lights[3] * tint, axisZ); + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, lights[0] * tint, axisZ, 0); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, lights[1] * tint, axisZ, 0); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, lights[2] * tint, axisZ, 0); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, lights[3] * tint, axisZ, 0); index(0, 1, 3, 1, 2, 3); } @@ -107,7 +113,7 @@ void BlocksRenderer::vertexAO( axisX, axisY ); - vertex(coord, u, v, light * tint, axisZ); + vertex(coord, u, v, light * tint, axisZ, 0.0f); } void BlocksRenderer::faceAO( @@ -140,10 +146,10 @@ void BlocksRenderer::faceAO( } else { auto axisZ = glm::normalize(Z); glm::vec4 tint(1.0f); - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, axisZ); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, axisZ); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, axisZ); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, axisZ); + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, axisZ, 1); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, axisZ, 1); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, axisZ, 1); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, axisZ, 1); } index(0, 1, 2, 0, 2, 3); } @@ -168,10 +174,10 @@ void BlocksRenderer::face( d = (1.0f - DIRECTIONAL_LIGHT_FACTOR) + d * DIRECTIONAL_LIGHT_FACTOR; tint *= d; } - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, Z); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, Z); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, Z); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, Z); + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, Z, lights ? 0 : 1); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, Z, lights ? 0 : 1); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, Z, lights ? 0 : 1); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, Z, lights ? 0 : 1); index(0, 1, 2, 0, 2, 3); } @@ -345,7 +351,8 @@ void BlocksRenderer::blockCustomModel( vertex.uv.x, vertex.uv.y, glm::vec4(d, d, d, d) * aoColor, - n + n, + 0.0f ); indexBuffer[indexCount++] = vertexOffset++; } diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 0bb9b31d..b017a3f3 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -44,7 +44,14 @@ class BlocksRenderer { SortingMeshData sortingMesh; - void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light, const glm::vec3& normal); + void vertex( + const glm::vec3& coord, + float u, + float v, + const glm::vec4& light, + const glm::vec3& normal, + float emission + ); void index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f); void vertexAO( From b04dbd5809a92a726fb9f7d1f9e9745c57ed1293 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 21:36:27 +0300 Subject: [PATCH 40/47] add 'graphics.ssao' setting --- res/layouts/pages/settings_graphics.xml.lua | 1 + res/shaders/effects/deferred_lighting.glsl | 17 ++++++++++++----- src/graphics/render/WorldRenderer.cpp | 14 +++++++++++--- src/graphics/render/WorldRenderer.hpp | 1 + src/io/settings_io.cpp | 1 + src/settings.hpp | 2 ++ 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/res/layouts/pages/settings_graphics.xml.lua b/res/layouts/pages/settings_graphics.xml.lua index 32c26fd5..99ba6609 100644 --- a/res/layouts/pages/settings_graphics.xml.lua +++ b/res/layouts/pages/settings_graphics.xml.lua @@ -43,5 +43,6 @@ function on_open() create_checkbox("graphics.backlight", "Backlight", "graphics.backlight.tooltip") create_checkbox("graphics.dense-render", "Dense blocks render", "graphics.dense-render.tooltip") create_checkbox("graphics.advanced-render", "Advanced render", "graphics.advanced-render.tooltip") + create_checkbox("graphics.ssao", "SSAO", "graphics.ssao.tooltip") create_setting("graphics.shadows-quality", "Shadows quality", 1) end diff --git a/res/shaders/effects/deferred_lighting.glsl b/res/shaders/effects/deferred_lighting.glsl index 5df6b148..27488911 100644 --- a/res/shaders/effects/deferred_lighting.glsl +++ b/res/shaders/effects/deferred_lighting.glsl @@ -2,23 +2,30 @@ #include vec4 effect() { - float ssao = 0.0; vec4 pos = texture(u_position, v_uv); + float light = 1.0; + +#ifdef ENABLE_SSAO + light = 0.0; float z = pos.z; for (int y = -2; y <= 2; y++) { for (int x = -2; x <= 2; x++) { vec2 offset = vec2(x, y) / u_screenSize; - ssao += texture(u_ssao, v_uv + offset * 2.0).r; + light += texture(u_ssao, v_uv + offset * 2.0).r; } } - ssao /= 24.0; + light /= 24.0; +#endif // ENABLE_SSAO + vec4 modelpos = u_inverseView * pos; vec3 normal = transpose(mat3(u_view)) * texture(u_normal, v_uv).xyz; vec3 dir = modelpos.xyz - u_cameraPos; + #ifdef ENABLE_SHADOWS - ssao *= max(calc_shadow(modelpos, normal, length(pos)), texture(u_emission, v_uv).r); + light *= max(calc_shadow(modelpos, normal, length(pos)), texture(u_emission, v_uv).r); #endif + vec3 fogColor = texture(u_skybox, dir).rgb; float fog = calc_fog(length(u_view * vec4((modelpos.xyz - u_cameraPos) * FOG_POS_SCALE, 0.0)) / 256.0); - return vec4(mix(texture(u_screen, v_uv).rgb * mix(1.0, ssao, 1.0), fogColor, fog), 1.0); + return vec4(mix(texture(u_screen, v_uv).rgb * mix(1.0, light, 1.0), fogColor, fog), 1.0); } diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 5a1fe21a..7d7bc79f 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -445,11 +445,13 @@ void WorldRenderer::draw( } CompileTimeShaderSettings currentSettings { - gbufferPipeline, shadows - }; + gbufferPipeline, + shadows, + settings.graphics.ssao.get() && gbufferPipeline}; if ( prevCTShaderSettings.advancedRender != currentSettings.advancedRender || - prevCTShaderSettings.shadows != currentSettings.shadows + prevCTShaderSettings.shadows != currentSettings.shadows || + prevCTShaderSettings.ssao != currentSettings.ssao ) { if (shadows) { Shader::preprocessor->define("ENABLE_SHADOWS", "true"); @@ -457,6 +459,12 @@ void WorldRenderer::draw( Shader::preprocessor->undefine("ENABLE_SHADOWS"); } + if (currentSettings.ssao) { + Shader::preprocessor->define("ENABLE_SSAO", "true"); + } else { + Shader::preprocessor->undefine("ENABLE_SSAO"); + } + if (gbufferPipeline) { Shader::preprocessor->define("ADVANCED_RENDER", "true"); } else { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index ec159012..5d33f8cd 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -38,6 +38,7 @@ struct EngineSettings; struct CompileTimeShaderSettings { bool advancedRender = false; bool shadows = false; + bool ssao = false; }; class WorldRenderer { diff --git a/src/io/settings_io.cpp b/src/io/settings_io.cpp index a968d9e0..000e965b 100644 --- a/src/io/settings_io.cpp +++ b/src/io/settings_io.cpp @@ -75,6 +75,7 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) { builder.add("chunk-max-vertices-dense", &settings.graphics.chunkMaxVerticesDense); builder.add("chunk-max-renderers", &settings.graphics.chunkMaxRenderers); builder.add("advanced-render", &settings.graphics.advancedRender); + builder.add("ssao", &settings.graphics.ssao); builder.add("shadows-quality", &settings.graphics.shadowsQuality); builder.section("ui"); diff --git a/src/settings.hpp b/src/settings.hpp index 699d2b28..e8826800 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -77,6 +77,8 @@ struct GraphicsSettings { IntegerSetting chunkMaxRenderers {6, -4, 32}; /// @brief Advanced render pipeline FlagSetting advancedRender {true}; + /// @brief Screen space ambient occlusion + FlagSetting ssao {true}; /// @brief Shadows quality IntegerSetting shadowsQuality {0, 0, 3}; }; From a0b87764779d277b842c8986139532b8fa246f27 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 21:45:22 +0300 Subject: [PATCH 41/47] minor refactor --- src/coders/GLSLExtension.cpp | 8 ++++++++ src/coders/GLSLExtension.hpp | 1 + src/graphics/render/WorldRenderer.cpp | 24 +++++------------------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/coders/GLSLExtension.cpp b/src/coders/GLSLExtension.cpp index 27ec7b63..8105b09e 100644 --- a/src/coders/GLSLExtension.cpp +++ b/src/coders/GLSLExtension.cpp @@ -76,6 +76,14 @@ void GLSLExtension::undefine(const std::string& name) { } } +void GLSLExtension::setDefined(const std::string& name, bool defined) { + if (defined) { + define(name, "TRUE"); + } else { + undefine(name); + } +} + inline std::runtime_error parsing_error( const io::path& file, uint linenum, const std::string& message ) { diff --git a/src/coders/GLSLExtension.hpp b/src/coders/GLSLExtension.hpp index 2d795d2c..b61ca512 100644 --- a/src/coders/GLSLExtension.hpp +++ b/src/coders/GLSLExtension.hpp @@ -22,6 +22,7 @@ public: void define(const std::string& name, std::string value); void undefine(const std::string& name); + void setDefined(const std::string& name, bool defined); void addHeader(const std::string& name, ProcessingResult header); const ProcessingResult& getHeader(const std::string& name) const; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 7d7bc79f..9a8d1aea 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -447,30 +447,16 @@ void WorldRenderer::draw( CompileTimeShaderSettings currentSettings { gbufferPipeline, shadows, - settings.graphics.ssao.get() && gbufferPipeline}; + settings.graphics.ssao.get() && gbufferPipeline + }; if ( prevCTShaderSettings.advancedRender != currentSettings.advancedRender || prevCTShaderSettings.shadows != currentSettings.shadows || prevCTShaderSettings.ssao != currentSettings.ssao ) { - if (shadows) { - Shader::preprocessor->define("ENABLE_SHADOWS", "true"); - } else { - Shader::preprocessor->undefine("ENABLE_SHADOWS"); - } - - if (currentSettings.ssao) { - Shader::preprocessor->define("ENABLE_SSAO", "true"); - } else { - Shader::preprocessor->undefine("ENABLE_SSAO"); - } - - if (gbufferPipeline) { - Shader::preprocessor->define("ADVANCED_RENDER", "true"); - } else { - Shader::preprocessor->undefine("ADVANCED_RENDER"); - } - + Shader::preprocessor->setDefined("ENABLE_SHADOWS", currentSettings.shadows); + Shader::preprocessor->setDefined("ENABLE_SSAO", currentSettings.ssao); + Shader::preprocessor->setDefined("ADVANCED_RENDER", currentSettings.advancedRender); mainShader.recompile(); entityShader.recompile(); deferredShader.recompile(); From bcdb891321a3a846c4d1cbf4638318925a8d5768 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 22:10:42 +0300 Subject: [PATCH 42/47] fix gbuffer resizing --- src/graphics/core/GBuffer.cpp | 74 +++++++++-------------------------- src/graphics/core/GBuffer.hpp | 14 +++---- 2 files changed, 25 insertions(+), 63 deletions(-) diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index 6307a353..d466f1e9 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -11,7 +11,8 @@ static debug::Logger logger("gl-gbuffer"); // TODO: REFACTOR void GBuffer::createColorBuffer() { - glGenTextures(1, &colorBuffer); + if (colorBuffer == 0) + glGenTextures(1, &colorBuffer); glBindTexture(GL_TEXTURE_2D, colorBuffer); glTexImage2D( GL_TEXTURE_2D, @@ -34,7 +35,8 @@ void GBuffer::createColorBuffer() { } void GBuffer::createPositionsBuffer() { - glGenTextures(1, &positionsBuffer); + if (positionsBuffer == 0) + glGenTextures(1, &positionsBuffer); glBindTexture(GL_TEXTURE_2D, positionsBuffer); glTexImage2D( GL_TEXTURE_2D, @@ -57,7 +59,8 @@ void GBuffer::createPositionsBuffer() { } void GBuffer::createNormalsBuffer() { - glGenTextures(1, &normalsBuffer); + if (normalsBuffer == 0) + glGenTextures(1, &normalsBuffer); glBindTexture(GL_TEXTURE_2D, normalsBuffer); glTexImage2D( GL_TEXTURE_2D, @@ -80,7 +83,8 @@ void GBuffer::createNormalsBuffer() { } void GBuffer::createEmissionBuffer() { - glGenTextures(1, &emissionBuffer); + if (emissionBuffer == 0) + glGenTextures(1, &emissionBuffer); glBindTexture(GL_TEXTURE_2D, emissionBuffer); glTexImage2D( GL_TEXTURE_2D, @@ -103,7 +107,8 @@ void GBuffer::createEmissionBuffer() { } void GBuffer::createDepthBuffer() { - glGenRenderbuffers(1, &depthBuffer); + if (depthBuffer == 0) + glGenRenderbuffers(1, &depthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); glFramebufferRenderbuffer( @@ -112,7 +117,8 @@ void GBuffer::createDepthBuffer() { } void GBuffer::createSSAOBuffer() { - glGenTextures(1, &ssaoBuffer); + if (ssaoBuffer == 0) + glGenTextures(1, &ssaoBuffer); glBindTexture(GL_TEXTURE_2D, ssaoBuffer); glTexImage2D( GL_TEXTURE_2D, @@ -233,61 +239,17 @@ void GBuffer::resize(uint width, uint height) { glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - - glBindTexture(GL_TEXTURE_2D, colorBuffer); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGB, - width, - height, - 0, - GL_RGB, - GL_UNSIGNED_BYTE, - nullptr - ); - glFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0 - ); - - glBindTexture(GL_TEXTURE_2D, positionsBuffer); - glTexImage2D( - GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr - ); - glFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positionsBuffer, 0 - ); - - glBindTexture(GL_TEXTURE_2D, normalsBuffer); - glTexImage2D( - GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr - ); - glFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normalsBuffer, 0 - ); - - glBindTexture(GL_TEXTURE_2D, emissionBuffer); - glTexImage2D( - GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, GL_LUMINANCE, GL_FLOAT, nullptr - ); - glFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, emissionBuffer, 0 - ); + createDepthBuffer(); + createColorBuffer(); + createPositionsBuffer(); + createNormalsBuffer(); + createEmissionBuffer(); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, ssaoFbo); - glBindTexture(GL_TEXTURE_2D, ssaoBuffer); - glTexImage2D( - GL_TEXTURE_2D, 0, GL_R16F, width, height, 0, GL_RED, GL_FLOAT, nullptr - ); - glFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoBuffer, 0 - ); + createSSAOBuffer(); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/src/graphics/core/GBuffer.hpp b/src/graphics/core/GBuffer.hpp index fa3e13b3..ae433c87 100644 --- a/src/graphics/core/GBuffer.hpp +++ b/src/graphics/core/GBuffer.hpp @@ -29,13 +29,13 @@ private: uint height; uint fbo; - uint colorBuffer; - uint positionsBuffer; - uint normalsBuffer; - uint emissionBuffer; - uint depthBuffer; - uint ssaoFbo; - uint ssaoBuffer; + uint colorBuffer = 0; + uint positionsBuffer = 0; + uint normalsBuffer = 0; + uint emissionBuffer = 0; + uint depthBuffer = 0; + uint ssaoFbo = 0; + uint ssaoBuffer = 0; void createColorBuffer(); void createPositionsBuffer(); From 668d1d522f94c759908c3067dd58425cb776de37 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 22:38:13 +0300 Subject: [PATCH 43/47] cleanup & fix entities sky light brightness --- res/shaders/entity.glslv | 8 ++-- src/graphics/core/PostProcessing.cpp | 63 ++++----------------------- src/graphics/core/PostProcessing.hpp | 21 ++------- src/graphics/render/WorldRenderer.cpp | 24 +--------- 4 files changed, 18 insertions(+), 98 deletions(-) diff --git a/res/shaders/entity.glslv b/res/shaders/entity.glslv index 24a8a714..3afed236 100644 --- a/res/shaders/entity.glslv +++ b/res/shaders/entity.glslv @@ -31,6 +31,8 @@ uniform float u_torchlightDistance; #include #include +#define SKY_LIGHT_BRIGHTNESS_COMPENSATION 0.1 + void main() { a_modelpos = u_model * vec4(v_position, 1.0); vec3 pos3d = a_modelpos.xyz - u_cameraPos; @@ -42,12 +44,12 @@ void main() { vec3 light = v_light.rgb; float torchlight = calc_torch_light(a_realnormal, a_modelpos.xyz); light += torchlight * u_torchlightColor; - a_color = vec4(pow(light, vec3(u_gamma)),1.0f); + a_color = vec4(pow(light, vec3(u_gamma)), 1.0f); a_texCoord = v_texCoord; a_dir = a_modelpos.xyz - u_cameraPos; - vec3 skyLightColor = pick_sky_color(u_skybox); - a_color.rgb = max(a_color.rgb, skyLightColor.rgb*v_light.a) * v_color; + vec3 skyLightColor = pick_sky_color(u_skybox) + SKY_LIGHT_BRIGHTNESS_COMPENSATION; + a_color.rgb = max(a_color.rgb, skyLightColor.rgb * v_light.a) * v_color; a_color.a = u_opacity; mat4 viewmodel = u_view * u_model; diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index 85b56067..ec491c52 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -89,12 +89,7 @@ void PostProcessing::configureEffect( PostEffect& effect, Shader& shader, float timer, - const Camera& camera, - uint shadowMap, - uint shadowMap2, - const glm::mat4& shadowMatrix, - const glm::mat4& shadowMatrix2, - uint shadowMapResolution + const Camera& camera ) { const auto& viewport = context.getViewport(); shader.uniform1i("u_screen", TARGET_COLOR); @@ -106,18 +101,9 @@ void PostProcessing::configureEffect( } shader.uniform1i("u_noise", TARGET_SSAO); // used in SSAO pass shader.uniform1i("u_ssao", TARGET_SSAO); - - shader.uniform1i("u_shadows[0]", TARGET_SHADOWS0); - shader.uniform1i("u_shadows[1]", TARGET_SHADOWS1); - shader.uniformMatrix("u_shadowsMatrix[0]", shadowMatrix); - shader.uniformMatrix("u_shadowsMatrix[1]", shadowMatrix2); - shader.uniform1f("u_shadowsOpacity", 1.0f); - shader.uniform1f("u_shadowsSoftness", 1.0f); - shader.uniform1i("u_shadowsRes", shadowMapResolution); shader.uniform2i("u_screenSize", viewport); shader.uniform3f("u_cameraPos", camera.position); shader.uniform1f("u_timer", timer); - shader.uniform1i("u_enableShadows", shadowMap != 0); shader.uniformMatrix("u_projection", camera.getProjection()); shader.uniformMatrix("u_view", camera.getView()); shader.uniformMatrix("u_inverseView", glm::inverse(camera.getView())); @@ -127,23 +113,11 @@ void PostProcessing::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 + const Camera& camera ) { if (gbuffer == nullptr) { throw std::runtime_error("gbuffer is not initialized"); } - - glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS0); - glBindTexture(GL_TEXTURE_2D, shadowMap); - - glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS1); - glBindTexture(GL_TEXTURE_2D, shadowMap2); - // Generating ssao gbuffer->bindBuffers(); @@ -159,12 +133,7 @@ void PostProcessing::renderDeferredShading( ssaoEffect, shader, timer, - camera, - shadowMap, - shadowMap2, - shadowMatrix, - shadowMatrix2, - shadowMapResolution + camera ); gbuffer->bindSSAO(); quadMesh->draw(); @@ -184,7 +153,6 @@ void PostProcessing::renderDeferredShading( gbuffer->bindBuffers(); - // TODO: move upper & move skybox->draw(...) here auto& effect = assets.require("deferred_lighting"); auto& shader = effect.use(); configureEffect( @@ -192,12 +160,7 @@ void PostProcessing::renderDeferredShading( effect, shader, timer, - camera, - shadowMap, - shadowMap2, - shadowMatrix, - shadowMatrix2, - shadowMapResolution + camera ); quadMesh->draw(); } @@ -207,12 +170,7 @@ 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 + const Camera& camera ) { if (fbo == nullptr) { throw std::runtime_error("'use(...)' was never called"); @@ -231,11 +189,11 @@ void PostProcessing::render( fbo->getTexture()->bind(); if (totalPasses == 0) { - // TODO: move upper & move skybox->draw(...) here + // replace 'default' blit shader with glBlitFramebuffer? auto& effect = assets.require("default"); auto& shader = effect.use(); configureEffect( - context, effect, shader, timer, camera, 0, 0, {}, {}, 0 + context, effect, shader, timer, camera ); quadMesh->draw(); return; @@ -255,12 +213,7 @@ void PostProcessing::render( *effect, shader, timer, - camera, - shadowMap, - shadowMap2, - shadowMatrix, - shadowMatrix2, - shadowMapResolution + camera ); if (currentPass > 1) { diff --git a/src/graphics/core/PostProcessing.hpp b/src/graphics/core/PostProcessing.hpp index 556699db..f9d50b75 100644 --- a/src/graphics/core/PostProcessing.hpp +++ b/src/graphics/core/PostProcessing.hpp @@ -39,12 +39,7 @@ public: 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 + const Camera& camera ); /// @brief Render fullscreen quad using the passed shader @@ -55,12 +50,7 @@ public: 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 + const Camera& camera ); void setEffect(size_t slot, std::shared_ptr effect); @@ -78,12 +68,7 @@ private: PostEffect& effect, Shader& shader, float timer, - const Camera& camera, - uint shadowMap, - uint shadowMap2, - const glm::mat4& shadowMatrix, - const glm::mat4& shadowMatrix2, - uint shadowMapResolution + const Camera& camera ); void refreshFbos(uint width, uint height); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 9a8d1aea..f6ed57e9 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -517,17 +517,7 @@ void WorldRenderer::draw( 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 - ); + postProcessing.renderDeferredShading(pctx, assets, timer, camera); } { DrawContext ctx = pctx.sub(); @@ -558,17 +548,7 @@ void WorldRenderer::draw( glBindFramebuffer(GL_FRAMEBUFFER, 0); } - postProcessing.render( - pctx, - assets, - timer, - camera, - shadows ? shadowMap->getDepthMap() : 0, - shadows ? wideShadowMap->getDepthMap() : 0, - shadowCamera.getProjView(), - wideShadowCamera.getProjView(), - shadows ? shadowMap->getResolution() : 0 - ); + postProcessing.render(pctx, assets, timer, camera); skybox->unbind(); if (player.currentCamera == player.fpCamera) { From 3f3f48eb6d07ea0a153dcf53d4679ca8aab4f589 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 22:53:33 +0300 Subject: [PATCH 44/47] fix --- res/shaders/effects/deferred_lighting.glsl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/res/shaders/effects/deferred_lighting.glsl b/res/shaders/effects/deferred_lighting.glsl index 27488911..f8f10401 100644 --- a/res/shaders/effects/deferred_lighting.glsl +++ b/res/shaders/effects/deferred_lighting.glsl @@ -21,10 +21,14 @@ vec4 effect() { vec3 normal = transpose(mat3(u_view)) * texture(u_normal, v_uv).xyz; vec3 dir = modelpos.xyz - u_cameraPos; + float emission = texture(u_emission, v_uv).r; + #ifdef ENABLE_SHADOWS - light *= max(calc_shadow(modelpos, normal, length(pos)), texture(u_emission, v_uv).r); + light *= calc_shadow(modelpos, normal, length(pos)); #endif + light = max(light, emission); + vec3 fogColor = texture(u_skybox, dir).rgb; float fog = calc_fog(length(u_view * vec4((modelpos.xyz - u_cameraPos) * FOG_POS_SCALE, 0.0)) / 256.0); return vec4(mix(texture(u_screen, v_uv).rgb * mix(1.0, light, 1.0), fogColor, fog), 1.0); From 2831d1c963632a1d6f2b9e0aa132847e01cc8f54 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 23:28:38 +0300 Subject: [PATCH 45/47] fix emission buffer writing & fix entity shader --- res/shaders/entity.glslf | 6 +++--- res/shaders/entity.glslv | 6 +++--- res/shaders/main.glslf | 2 +- src/graphics/render/MainBatch.hpp | 25 +++++++++++++++-------- src/graphics/render/ModelBatch.cpp | 9 +++++++- src/graphics/render/ParticlesRenderer.cpp | 4 ++-- 6 files changed, 34 insertions(+), 18 deletions(-) diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index f9675708..4d4fadba 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -12,6 +12,7 @@ in vec3 a_position; in vec3 a_realnormal; in vec4 a_color; in vec4 a_modelpos; +in float a_emission; uniform sampler2D u_texture0; uniform samplerCube u_skybox; @@ -24,14 +25,13 @@ uniform vec3 u_sunDir; #include void main() { - float shadow = calc_shadow(a_modelpos, a_realnormal, a_distance); 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 * texColor * shadow; + f_color = a_color * texColor; #ifndef ADVANCED_RENDER vec3 fogColor = texture(u_skybox, a_dir).rgb; @@ -41,5 +41,5 @@ void main() { f_color.a = alpha; f_position = vec4(a_position, 1.0); f_normal = vec4(a_normal, 1.0); - f_emission = vec4(0.0); + f_emission = vec4(vec3(a_emission), 1.0); } diff --git a/res/shaders/entity.glslv b/res/shaders/entity.glslv index 3afed236..d7b6d3e0 100644 --- a/res/shaders/entity.glslv +++ b/res/shaders/entity.glslv @@ -15,6 +15,7 @@ out vec3 a_position; out vec3 a_realnormal; out vec4 a_color; out vec4 a_modelpos; +out float a_emission; uniform mat4 u_model; uniform mat4 u_proj; @@ -31,8 +32,6 @@ uniform float u_torchlightDistance; #include #include -#define SKY_LIGHT_BRIGHTNESS_COMPENSATION 0.1 - void main() { a_modelpos = u_model * vec4(v_position, 1.0); vec3 pos3d = a_modelpos.xyz - u_cameraPos; @@ -48,13 +47,14 @@ void main() { a_texCoord = v_texCoord; a_dir = a_modelpos.xyz - u_cameraPos; - vec3 skyLightColor = pick_sky_color(u_skybox) + SKY_LIGHT_BRIGHTNESS_COMPENSATION; + vec3 skyLightColor = pick_sky_color(u_skybox); a_color.rgb = max(a_color.rgb, skyLightColor.rgb * v_light.a) * v_color; a_color.a = u_opacity; mat4 viewmodel = u_view * u_model; a_distance = length(viewmodel * vec4(pos3d, 0.0)); a_fog = calc_fog(length(viewmodel * vec4(pos3d * FOG_POS_SCALE, 0.0)) / 256.0); + a_emission = v_normal.w; vec4 viewmodelpos = u_view * a_modelpos; a_position = viewmodelpos.xyz; diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index 39797aa0..f7336d9a 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -52,5 +52,5 @@ void main() { f_color.a = alpha; f_position = vec4(a_position, 1.0); f_normal = vec4(a_normal, 1.0); - f_emission = vec4(a_emission); + f_emission = vec4(vec3(a_emission), 1.0); } diff --git a/src/graphics/render/MainBatch.hpp b/src/graphics/render/MainBatch.hpp index 2c22412e..fae9f904 100644 --- a/src/graphics/render/MainBatch.hpp +++ b/src/graphics/render/MainBatch.hpp @@ -64,7 +64,8 @@ public: const glm::vec2& uv, const glm::vec4& light, const glm::vec3& tint, - const glm::vec3& normal + const glm::vec3& normal, + float emission ) { MainBatchVertex* buffer = this->buffer.get(); buffer[index].position = pos; @@ -79,6 +80,7 @@ public: buffer[index].normal[0] = static_cast(normal.x * 128 + 127); buffer[index].normal[1] = static_cast(normal.y * 128 + 127); buffer[index].normal[2] = static_cast(normal.z * 128 + 127); + buffer[index].normal[3] = static_cast(emission * 255); index++; } @@ -90,7 +92,8 @@ public: const glm::vec2& size, const glm::vec4& light, const glm::vec3& tint, - const UVRegion& subregion + const UVRegion& subregion, + float emission = 0.0f ) { prepare(6); vertex( @@ -98,21 +101,24 @@ public: {subregion.u1, subregion.v1}, light, tint, - normal + normal, + emission ); vertex( pos + right * size.x * 0.5f - up * size.y * 0.5f, {subregion.u2, subregion.v1}, light, tint, - normal + normal, + emission ); vertex( pos + right * size.x * 0.5f + up * size.y * 0.5f, {subregion.u2, subregion.v2}, light, tint, - normal + normal, + emission ); vertex( @@ -120,21 +126,24 @@ public: {subregion.u1, subregion.v1}, light, tint, - normal + normal, + emission ); vertex( pos + right * size.x * 0.5f + up * size.y * 0.5f, {subregion.u2, subregion.v2}, light, tint, - normal + normal, + emission ); vertex( pos - right * size.x * 0.5f + up * size.y * 0.5f, {subregion.u1, subregion.v2}, light, tint, - normal + normal, + emission ); } diff --git a/src/graphics/render/ModelBatch.cpp b/src/graphics/render/ModelBatch.cpp index 77e948e7..61123232 100644 --- a/src/graphics/render/ModelBatch.cpp +++ b/src/graphics/render/ModelBatch.cpp @@ -85,7 +85,14 @@ void ModelBatch::draw( d = glm::dot(norm, SUN_VECTOR); d = 0.8f + d * 0.2f; } - batch->vertex(matrix * glm::vec4(vert.coord, 1.0f), vert.uv, lights*d, tint, norm); + batch->vertex( + matrix * glm::vec4(vert.coord, 1.0f), + vert.uv, + lights * d, + tint, + norm, + mesh.lighting ? 0.0f : 1.0f + ); } } } diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 23b7a857..4788d0f4 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -117,7 +117,6 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { light *= 0.9f + (particle.random % 100) * 0.001f; } - glm::vec3 localRight = right; glm::vec3 localUp = preset.globalUpVector ? glm::vec3(0, 1, 0) : up; float angle = particle.angle; @@ -138,7 +137,8 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { preset.size * scale, light, glm::vec3(1.0f), - particle.region + particle.region, + preset.lighting ? 0.0f : 1.0f ); if (particle.lifetime <= 0.0f) { iter = vec.erase(iter); From 3225393636c1444f066f45c95417d86420dd1725 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 12 Jul 2025 23:55:17 +0300 Subject: [PATCH 46/47] update hud.lua --- res/scripts/hud.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua index cfeaad66..3fd1375c 100644 --- a/res/scripts/hud.lua +++ b/res/scripts/hud.lua @@ -1,7 +1,7 @@ local function configure_SSAO() + -- Temporary using slot to configure built-in SSAO effect local slot = gfx.posteffects.index("core:default") gfx.posteffects.set_effect(slot, "ssao") - -- gfx.posteffects.set_intensity(slot, 1.0) -- Generating random SSAO samples local buffer = Bytearray(0) @@ -18,6 +18,8 @@ local function configure_SSAO() Bytearray.append(buffer, byteutil.pack("fff", x, y, z)) end gfx.posteffects.set_array(slot, "u_ssaoSamples", Bytearray_as_string(buffer)) + -- SSAO effect configured, so 'core:default' slot may be reused now + -- for test purposes end function on_hud_open() From 3e98b2c15854104eb329fbb7f9b5c14240cdb50c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 13 Jul 2025 00:22:04 +0300 Subject: [PATCH 47/47] fix --- src/graphics/render/WorldRenderer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index f6ed57e9..1e77272b 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -358,7 +358,11 @@ void WorldRenderer::generateShadowsMap( float shadowMapSize = resolution * shadowMapScale; glm::vec3 basePos = glm::floor(camera.position / 4.0f) * 4.0f; - shadowCamera = Camera(basePos, shadowMapSize); + glm::vec3 prevPos = shadowCamera.position; + shadowCamera = Camera( + glm::distance2(prevPos, basePos) > 25.0f ? basePos : prevPos, + shadowMapSize + ); shadowCamera.near = 0.1f; shadowCamera.far = 1000.0f; shadowCamera.perspective = false;