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() {
//return vec4(vec3(pow(texture(u_shadows, v_uv).r, 5.0) * 1000.0), 1.0);
return texture(u_screen, v_uv);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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<Shader>("lines");
/* World render scope with diegetic HUD included */ {

View File

@ -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 {

View File

@ -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;
}

View File

@ -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);
};