improve shadow map stability

This commit is contained in:
MihailRis 2025-05-11 20:55:35 +03:00
parent b272d86619
commit ad0396b31e
7 changed files with 68 additions and 14 deletions

View File

@ -1,3 +1,4 @@
vec4 effect() { vec4 effect() {
//return vec4(vec3(pow(texture(u_shadows, v_uv).r, 5.0) * 1000.0), 1.0);
return texture(u_screen, v_uv); return texture(u_screen, v_uv);
} }

View File

@ -1,10 +1,22 @@
#ifndef SHADOWS_GLSL_ #ifndef SHADOWS_GLSL_
#define 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 calc_shadow() {
float shadow = 1.0; float shadow = 1.0;
if (u_enableShadows) { 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; vec3 projCoords = mpos.xyz / mpos.w;
projCoords = projCoords * 0.5 + 0.5; projCoords = projCoords * 0.5 + 0.5;
projCoords.z -= 0.0001; projCoords.z -= 0.0001;
@ -22,6 +34,7 @@ float calc_shadow() {
shadow += texture(u_shadows, projCoords.xyz + offsets[i] / u_shadowsRes); shadow += texture(u_shadows, projCoords.xyz + offsets[i] / u_shadowsRes);
} }
shadow /= 4; shadow /= 4;
//shadow = sample_shadow(projCoords, normalize(vec3(1.0, 1.0, 0.0)) * 0.5);
shadow = shadow * 0.5 + 0.5; shadow = shadow * 0.5 + 0.5;
} else { } else {
shadow = 0.5; shadow = 0.5;

View File

@ -203,14 +203,21 @@ void BlocksRenderer::blockXSprite(
const float w = size.x / 1.41f; const float w = size.x / 1.41f;
const glm::vec4 tint (0.8f); 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); 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); 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); 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); texface2, lights1, tint);
} }

View File

@ -345,23 +345,41 @@ void WorldRenderer::generateShadowsMap(const Camera& camera, const DrawContext&
const auto& settings = engine.getSettings(); const auto& settings = engine.getSettings();
int resolution = shadowMap->getResolution(); 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; 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.near = 0.1f;
shadowCamera.far = 800.0f; shadowCamera.far = 800.0f;
shadowCamera.perspective = false; shadowCamera.perspective = false;
shadowCamera.setAspectRatio(1.0f); shadowCamera.setAspectRatio(1.0f);
float sunAngle = glm::radians(fmod(90.0f - worldInfo.daytime * 360.0f, 180.0f));
shadowCamera.rotate( shadowCamera.rotate(
glm::radians(fmod(90.0f - worldInfo.daytime * 360.0f, 180.0f)), sunAngle,
glm::radians(-40.0f), glm::radians(-45.0f),
glm::radians(-0.0f) glm::radians(-0.0f)
); );
shadowCamera.updateVectors(); shadowCamera.updateVectors();
shadowCamera.position -= shadowCamera.front * 200.0f; shadowCamera.position -= shadowCamera.front * 200.0f;
shadowCamera.position -= shadowCamera.right * (resolution * shadowMapScale) * 0.5f; shadowCamera.position += shadowCamera.up * 10.0f;
shadowCamera.position -= shadowCamera.up * (resolution * shadowMapScale) * 0.5f;
shadowCamera.position = glm::floor(shadowCamera.position * 0.25f) * 4.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()); frustumCulling->update(shadowCamera.getProjView());
auto sctx = pctx.sub(); auto sctx = pctx.sub();
@ -419,9 +437,11 @@ void WorldRenderer::draw(
chunks->update(); chunks->update();
if (shadows) { static int frameid = 0;
if (shadows && frameid % 2 == 0) {
generateShadowsMap(camera, pctx); generateShadowsMap(camera, pctx);
} }
frameid++;
auto& linesShader = assets.require<Shader>("lines"); auto& linesShader = assets.require<Shader>("lines");
/* World render scope with diegetic HUD included */ { /* World render scope with diegetic HUD included */ {

View File

@ -78,7 +78,7 @@ struct GraphicsSettings {
/// @brief Advanced render pipeline /// @brief Advanced render pipeline
FlagSetting advancedRender {true}; FlagSetting advancedRender {true};
/// @brief Shadows quality /// @brief Shadows quality
IntegerSetting shadowsQuality {0, 0, 2}; IntegerSetting shadowsQuality {0, 0, 3};
}; };
struct DebugSettings { struct DebugSettings {

View File

@ -28,6 +28,9 @@ void Camera::rotate(float x, float y, float z) {
} }
glm::mat4 Camera::getProjection() const { glm::mat4 Camera::getProjection() const {
if (projset) {
return projection;
}
if (perspective) { if (perspective) {
return glm::perspective(fov * zoom, ar, near, far); return glm::perspective(fov * zoom, ar, near, far);
} else if (flipped) { } else if (flipped) {
@ -62,6 +65,11 @@ float Camera::getFov() const {
return fov; return fov;
} }
void Camera::setProjection(const glm::mat4& matrix) {
projection = matrix;
projset = true;
}
float Camera::getAspectRatio() const { float Camera::getAspectRatio() const {
return ar; return ar;
} }

View File

@ -21,6 +21,9 @@ public:
float near = 0.05f; float near = 0.05f;
float far = 1500.0f; float far = 1500.0f;
bool projset = false;
glm::mat4 projection;
Camera() { Camera() {
updateVectors(); updateVectors();
} }
@ -36,6 +39,8 @@ public:
void setFov(float fov); void setFov(float fov);
float getFov() const; float getFov() const;
void setProjection(const glm::mat4& matrix);
float getAspectRatio() const; float getAspectRatio() const;
void setAspectRatio(float ar); void setAspectRatio(float ar);
}; };