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
|
// 0 - uniform
|
||||||
// 1 - exponential
|
// 1 - exponential
|
||||||
// 0.5 - mix between the two
|
// 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();
|
pub const Render = @This();
|
||||||
|
|
||||||
@ -553,7 +553,23 @@ pub fn finish(self: *Render) void {
|
|||||||
dir_aabb_min = pos.min(dir_aabb_min);
|
dir_aabb_min = pos.min(dir_aabb_min);
|
||||||
dir_aabb_max = pos.max(dir_aabb_max);
|
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.* = .{
|
camera_matrix.* = .{
|
||||||
|
@ -188,9 +188,9 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
|||||||
|
|
||||||
_ = globals.g_mem.world.addEntity(.{
|
_ = globals.g_mem.world.addEntity(.{
|
||||||
.flags = .{ .dir_light = true, .rotate = true },
|
.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) },
|
.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(.{
|
// const light_root = globals.g_mem.world.addEntity(.{
|
||||||
@ -345,7 +345,7 @@ export fn game_update() bool {
|
|||||||
c.SDL_SCANCODE_F7 => {
|
c.SDL_SCANCODE_F7 => {
|
||||||
if (event.type == c.SDL_KEYDOWN) {
|
if (event.type == c.SDL_KEYDOWN) {
|
||||||
if (gmem.render.camera.far == 10) {
|
if (gmem.render.camera.far == 10) {
|
||||||
gmem.render.camera.far = 100;
|
gmem.render.camera.far = 50;
|
||||||
} else {
|
} else {
|
||||||
gmem.render.camera.far = 10;
|
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);
|
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 {
|
pub const Frustum = struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user