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;