From 83b9d6423554bcbf5d0c08789b9283eb7225b495 Mon Sep 17 00:00:00 2001 From: sergeypdev Date: Mon, 4 Mar 2024 16:10:15 +0400 Subject: [PATCH] Add shadowmap frustum culling. Fix too large shadow bias --- assets/shaders/mesh.glsl | 5 ++--- src/Render.zig | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/assets/shaders/mesh.glsl b/assets/shaders/mesh.glsl index f088d9b..a39a1a5 100644 --- a/assets/shaders/mesh.glsl +++ b/assets/shaders/mesh.glsl @@ -186,9 +186,9 @@ vec3 microfacetModel(Material mat, int light_idx, Light light, vec3 P, vec3 N) { float NDotV = dot(N, V); float normal_offset_scale = clamp(1 - NDotL, 0, 1); - normal_offset_scale *= 12; // constant + normal_offset_scale *= 10; // constant - float constant_bias = 0.003; + float constant_bias = 0.001; float shadow_mult = 1; vec4 shadow_offset = vec4(VertexOut.wNormal * normal_offset_scale, 0); if (point == 1) { @@ -229,7 +229,6 @@ vec3 microfacetModel(Material mat, int light_idx, Light light, vec3 P, vec3 N) { texcoord.z = 0; // First shadow map float sum = 0; - for (float y = -1.5; y <= 1.5; y += 1) { for (float x = -1.5; x <= 1.5; x += 1) { sum += texture(shadow_maps, vec4(texcoord.xy + vec2(x, y) * shadow_map_texel_size, texcoord.zw)); diff --git a/src/Render.zig b/src/Render.zig index 50d0b5a..e149687 100644 --- a/src/Render.zig +++ b/src/Render.zig @@ -318,7 +318,10 @@ pub fn finish(self: *Render) void { Vec3.up(), ), }; - light.shadow_vp = camera_matrix.projection.mul(camera_matrix.view); + + const shadow_view_proj = camera_matrix.projection.mul(camera_matrix.view); + const light_frustum = math.Frustum.new(shadow_view_proj); + light.shadow_vp = shadow_view_proj; gl.namedBufferSubData(self.shadow_matrices_buffer, 0, @sizeOf(CameraMatrices), std.mem.asBytes(&self.shadow_matrices)); checkGLError(); @@ -326,7 +329,7 @@ pub fn finish(self: *Render) void { gl.clear(gl.DEPTH_BUFFER_BIT); gl.bindBufferBase(gl.UNIFORM_BUFFER, UBO.CameraMatrices.value(), self.shadow_matrices_buffer); - self.renderShadow(); + self.renderShadow(&light_frustum); } else { // Point Light gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.cube_shadow).program); @@ -353,6 +356,9 @@ pub fn finish(self: *Render) void { cam_dir.up, ), }; + + const shadow_view_proj = camera_matrix.projection.mul(camera_matrix.view); + const light_frustum = math.Frustum.new(shadow_view_proj); light.near_far = near_far; gl.uniform2f(Uniform.NearFarPlanes.value(), near_far.x(), near_far.y()); @@ -362,7 +368,7 @@ pub fn finish(self: *Render) void { gl.clear(gl.DEPTH_BUFFER_BIT); gl.bindBufferBase(gl.UNIFORM_BUFFER, UBO.CameraMatrices.value(), self.shadow_matrices_buffer); - self.renderShadow(); + self.renderShadow(&light_frustum); } } } @@ -485,7 +491,7 @@ pub fn finish(self: *Render) void { ); } - std.log.debug("Total draws {}, frustum culled draws {}\n", .{ self.command_count, rendered_count }); + //std.log.debug("Total draws {}, frustum culled draws {}\n", .{ self.command_count, rendered_count }); self.gl_fences[self.tripple_buffer_index] = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0); c.SDL_GL_SwapWindow(ginit.window); @@ -531,9 +537,14 @@ const cube_camera_dirs = [6]CubeCameraDir{ }, }; -fn renderShadow(self: *Render) void { +fn renderShadow(self: *Render, frustum: *const math.Frustum) void { for (self.command_buffer[0..self.command_count]) |*cmd| { const mesh = self.assetman.resolveMesh(cmd.mesh); + const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max); + + if (!frustum.intersectAABB(aabb.transform(cmd.transform))) { + continue; + } gl.uniformMatrix4fv(Uniform.ModelMatrix.value(), 1, gl.FALSE, @ptrCast(&cmd.transform.data)); mesh.positions.bind(Render.Attrib.Position.value());