diff options
author | x2048 <codeforsmile@gmail.com> | 2022-11-20 21:28:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-20 21:28:01 +0100 |
commit | 70a82b07844ce5187ba030110ea84c0e6c07c291 (patch) | |
tree | a6266a4eac4030a5312a4d790a9bf1aa57dea15d /src/client/shadows/dynamicshadows.cpp | |
parent | 5f24a3c0c7630b2bad530aab7deeaa9468c59fd9 (diff) | |
download | minetest-70a82b07844ce5187ba030110ea84c0e6c07c291.tar.xz |
Avoid shadow flicker at certain angles (#12961)
Change the way look direction and camera position are quantized when calculating light frustum
Diffstat (limited to 'src/client/shadows/dynamicshadows.cpp')
-rw-r--r-- | src/client/shadows/dynamicshadows.cpp | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/src/client/shadows/dynamicshadows.cpp b/src/client/shadows/dynamicshadows.cpp index 9f26ba94a..80db64286 100644 --- a/src/client/shadows/dynamicshadows.cpp +++ b/src/client/shadows/dynamicshadows.cpp @@ -41,10 +41,16 @@ static v3f quantizeDirection(v3f direction, float step) void DirectionalLight::createSplitMatrices(const Camera *cam) { - const float DISTANCE_STEP = BS * 2.0; // 2 meters + static const float COS_15_DEG = 0.965926f; v3f newCenter; - v3f look = cam->getDirection(); - look = quantizeDirection(look, M_PI / 12.0); // 15 degrees + v3f look = cam->getDirection().normalize(); + + // if current look direction is < 15 degrees away from the captured + // look direction then stick to the captured value, otherwise recapture. + if (look.dotProduct(last_look) >= COS_15_DEG) + look = last_look; + else + last_look = look; // camera view tangents float tanFovY = tanf(cam->getFovY() * 0.5f); @@ -56,10 +62,14 @@ void DirectionalLight::createSplitMatrices(const Camera *cam) // adjusted camera positions v3f cam_pos_world = cam->getPosition(); - cam_pos_world = v3f( - floor(cam_pos_world.X / DISTANCE_STEP) * DISTANCE_STEP, - floor(cam_pos_world.Y / DISTANCE_STEP) * DISTANCE_STEP, - floor(cam_pos_world.Z / DISTANCE_STEP) * DISTANCE_STEP); + + // if world position is less than 1 block away from the captured + // world position then stick to the captured value, otherwise recapture. + if (cam_pos_world.getDistanceFromSQ(last_cam_pos_world) < BS * BS) + cam_pos_world = last_cam_pos_world; + else + last_cam_pos_world = cam_pos_world; + v3f cam_pos_scene = v3f(cam_pos_world.X - cam->getOffset().X * BS, cam_pos_world.Y - cam->getOffset().Y * BS, cam_pos_world.Z - cam->getOffset().Z * BS); |