Use bounding sphere instead of AABB to calculate projection matrix for CSM split
This reduces flickering somewhat because shadow map resolution doesn't change so much
This commit is contained in:
parent
7600db3dca
commit
a865ea4ab7
@ -24,7 +24,7 @@ pub const CSM_SPLITS = 4;
|
||||
// 0 - uniform
|
||||
// 1 - exponential
|
||||
// 0.5 - mix between the two
|
||||
pub const CSM_EXPO_UNIFORM_FACTOR = 0.9;
|
||||
pub const CSM_EXPO_UNIFORM_FACTOR = 0.5;
|
||||
|
||||
pub const Render = @This();
|
||||
|
||||
@ -553,7 +553,23 @@ pub fn finish(self: *Render) void {
|
||||
dir_aabb_min = pos.min(dir_aabb_min);
|
||||
dir_aabb_max = pos.max(dir_aabb_max);
|
||||
}
|
||||
projection = math.orthographic(dir_aabb_min.x(), dir_aabb_max.x(), dir_aabb_min.y(), dir_aabb_max.y(), -dir_aabb_max.z(), -dir_aabb_min.z());
|
||||
// Flip z because it's negative in view space, but near, far is positive
|
||||
{
|
||||
const min_z = dir_aabb_min.z();
|
||||
dir_aabb_min.zMut().* = -dir_aabb_max.z();
|
||||
dir_aabb_max.zMut().* = -min_z;
|
||||
}
|
||||
const b_sphere = math.AABB.fromMinMax(dir_aabb_min, dir_aabb_max).toSphere();
|
||||
|
||||
// NOTE: Use bounding sphere instead of AABB to prevent split size changing with rotation
|
||||
projection = math.orthographic(
|
||||
b_sphere.origin.x() - b_sphere.radius,
|
||||
b_sphere.origin.x() + b_sphere.radius,
|
||||
b_sphere.origin.y() - b_sphere.radius,
|
||||
b_sphere.origin.y() + b_sphere.radius,
|
||||
b_sphere.origin.z() - b_sphere.radius,
|
||||
b_sphere.origin.z() + b_sphere.radius,
|
||||
);
|
||||
}
|
||||
|
||||
camera_matrix.* = .{
|
||||
|
@ -188,9 +188,9 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
||||
|
||||
_ = globals.g_mem.world.addEntity(.{
|
||||
.flags = .{ .dir_light = true, .rotate = true },
|
||||
.transform = .{ .rot = Quat.fromEulerAngles(Vec3.new(89, 0, 0)) },
|
||||
.transform = .{ .rot = Quat.fromEulerAngles(Vec3.new(20, 0, 0)) },
|
||||
.light = .{ .color_intensity = Vec4.new(1, 1, 0.83, 0.7) },
|
||||
.rotate = .{ .axis = Vec3.up(), .rate = -45 },
|
||||
.rotate = .{ .axis = Vec3.up(), .rate = -10 },
|
||||
});
|
||||
|
||||
// const light_root = globals.g_mem.world.addEntity(.{
|
||||
@ -345,7 +345,7 @@ export fn game_update() bool {
|
||||
c.SDL_SCANCODE_F7 => {
|
||||
if (event.type == c.SDL_KEYDOWN) {
|
||||
if (gmem.render.camera.far == 10) {
|
||||
gmem.render.camera.far = 100;
|
||||
gmem.render.camera.far = 50;
|
||||
} else {
|
||||
gmem.render.camera.far = 10;
|
||||
}
|
||||
|
13
src/math.zig
13
src/math.zig
@ -98,6 +98,19 @@ pub const AABB = struct {
|
||||
|
||||
return AABB.fromMinMax(min, max);
|
||||
}
|
||||
|
||||
pub fn toSphere(self: *const AABB) BoundingSphere {
|
||||
const max_extent = @max(@max(self.extents.x(), self.extents.y()), self.extents.z());
|
||||
return BoundingSphere{
|
||||
.origin = self.origin,
|
||||
.radius = max_extent,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const BoundingSphere = struct {
|
||||
origin: Vec3 = Vec3.zero(),
|
||||
radius: f32 = 0,
|
||||
};
|
||||
|
||||
pub const Frustum = struct {
|
||||
|
Loading…
x
Reference in New Issue
Block a user