Shadow fixes
This commit is contained in:
@@ -131,7 +131,7 @@ Editor :: struct {
|
||||
|
||||
init_editor :: () {
|
||||
aspect_ratio := cast(float)engine.renderer.render_target_width / cast(float)engine.renderer.render_target_height;
|
||||
engine.editor.camera = create_perspective_camera(.{0, 10, -10}, yaw=0, pitch=-40, roll=0.0, fov=40, aspect=aspect_ratio);
|
||||
engine.editor.camera = create_perspective_camera(.{0, 10, -10}, yaw=0, pitch=-40, roll=0.0, fov=40, z_far=100.0, aspect=aspect_ratio);
|
||||
|
||||
init_transform_gizmo();
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ Engine_Core :: struct {
|
||||
directional_light_buffer : Buffer_Handle;
|
||||
point_light_buffer : Buffer_Handle;
|
||||
|
||||
on_frustum_render: (Vector3, Vector3);
|
||||
|
||||
procs: struct {
|
||||
on_scene_loaded: (*Scene, Engine_Mode);
|
||||
on_pre_scene_loaded: (*Scene, Engine_Mode);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
calc_tight_light_projection :: (camera: Camera, light_direction: Vector3) -> Matrix4 {
|
||||
// View space camera frustum
|
||||
aspect_ratio := cast(float)engine.renderer.render_target_height / cast(float)engine.renderer.render_target_width;
|
||||
frustum := get_frustum(camera.fov, aspect_ratio, camera.z_near, camera.z_far);
|
||||
frustum := get_frustum(camera.fov, aspect_ratio, camera.z_near-20.0, camera.z_far+20);
|
||||
|
||||
// View frustum back to world space
|
||||
success :, inv_camera_view := inverse(camera.view_matrix);
|
||||
@@ -22,6 +22,9 @@ calc_tight_light_projection :: (camera: Camera, light_direction: Vector3) -> Mat
|
||||
light_space_frustum = transform(view_frustum_in_world_space, light_view);
|
||||
|
||||
final_aabb := get_frustum_aabb(light_space_frustum);
|
||||
// Padding
|
||||
//final_aabb.min -= .{8,5,8};
|
||||
//final_aabb.max += .{20,0,20};
|
||||
|
||||
// Texel size calculation based on shadow map resolution (e.g., 2048x2048)
|
||||
texel_size_x := (final_aabb.max.x - final_aabb.min.x) / 4096.0;
|
||||
@@ -35,15 +38,76 @@ calc_tight_light_projection :: (camera: Camera, light_direction: Vector3) -> Mat
|
||||
final_aabb.max.x = final_aabb.min.x + (texel_size_x * 4096.0);
|
||||
final_aabb.max.y = final_aabb.min.y + (texel_size_y * 4096.0);
|
||||
|
||||
// Padding
|
||||
final_aabb.min -= .{8,5,8};
|
||||
final_aabb.max += .{8,50, 8};
|
||||
|
||||
light_projection := orthographic_lh_projection_matrix(final_aabb.min.x, final_aabb.max.x, final_aabb.min.y, final_aabb.max.y, final_aabb.min.z, final_aabb.max.z);
|
||||
|
||||
return light_projection * light_view;
|
||||
}
|
||||
|
||||
calculate_sun_transform :: (camera: Camera, light_direction: Vector3) -> Matrix4 {
|
||||
success, inv_viewproj := inverse(camera.projection_matrix * camera.view_matrix);
|
||||
|
||||
view : Matrix4;
|
||||
proj : Matrix4;
|
||||
|
||||
ndc : [8] Vector4 = .[
|
||||
.{-1, -1, 0, 1}, .{1, -1, 0, 1}, .{-1, 1, 0, 1}, .{1, 1, 0, 1}, // near plane
|
||||
.{-1, -1, 1, 1}, .{1, -1, 1, 1}, .{-1, 1, 1, 1}, .{1, 1, 1, 1} // far plane
|
||||
];
|
||||
|
||||
corners : [8] Vector3;
|
||||
center : Vector3;
|
||||
|
||||
for i: 0..7 {
|
||||
world := inv_viewproj * ndc[i];
|
||||
corners[i] = world.xyz / world.w;
|
||||
center += corners[i];
|
||||
}
|
||||
|
||||
center /= 8.0;
|
||||
|
||||
{
|
||||
// Build light basis
|
||||
forward := normalize(-light_direction);
|
||||
up := ifx abs(forward.y) > 0.99 then Vector3.{0, 0, 1} else .{0, 1, 0};
|
||||
right := normalize(cross(up, forward));
|
||||
up = cross(forward, right);
|
||||
|
||||
// Build view matrix manually (row-major layout)
|
||||
view = Matrix4_Identity;
|
||||
view.v[0] = Vector4.{right.x, right.y, right.z, 0.0};
|
||||
view.v[1] = Vector4.{up.x, up.y, up.z, 0.0};
|
||||
view.v[2] = Vector4.{forward.x, forward.y, forward.z, 0.0};
|
||||
view.v[3] = Vector4.{-dot(right, center),
|
||||
-dot(up, center),
|
||||
-dot(forward, center),
|
||||
1.0};
|
||||
}
|
||||
|
||||
{
|
||||
min_bounds : Vector3 = .{FLOAT32_MAX, FLOAT32_MAX, FLOAT32_MAX};
|
||||
max_bounds : Vector3 = .{-FLOAT32_MAX, -FLOAT32_MAX, -FLOAT32_MAX};
|
||||
|
||||
for i: 0..7 {
|
||||
ls := transform_position(corners[i], view);
|
||||
min_bounds = min(min_bounds, ls);
|
||||
max_bounds = max(max_bounds, ls);
|
||||
}
|
||||
|
||||
// Step 5: Build orthographic projection (DX11 Z: 0..1)
|
||||
left := min_bounds.x;
|
||||
right := max_bounds.x;
|
||||
bottom := min_bounds.y;
|
||||
top := max_bounds.y;
|
||||
near_z := min_bounds.z;
|
||||
far_z := max_bounds.z;
|
||||
|
||||
proj = orthographic_lh_projection_matrix(left, right, bottom, top, near_z, far_z);
|
||||
}
|
||||
|
||||
return proj * view;
|
||||
}
|
||||
|
||||
update_light_buffer :: () {
|
||||
scene := engine.current_scene;
|
||||
|
||||
|
||||
@@ -90,11 +90,12 @@ set_render_pass_clear_color :: (rp: Render_Pass_Handle, input_index: s32, color:
|
||||
execute_render_pass :: (render_pass: Render_Pass) { // @Incomplete: Add command buffer as parameter
|
||||
if render_pass.render_targets.count == 0 {
|
||||
if render_pass.has_depth_stencil {
|
||||
push_cmd_set_render_targets(engine.renderer, depth_stencil_enabled=render_pass.has_depth_stencil, depth_stencil_buffer=render_pass.depth_stencil);
|
||||
push_cmd_clear_depth_stencil(engine.renderer, render_pass.depth_stencil, 1.0);
|
||||
width := ifx render_pass.width == SWAPCHAIN_SIZE then engine.renderer.render_target_width else render_pass.width;
|
||||
height := ifx render_pass.height == SWAPCHAIN_SIZE then engine.renderer.render_target_height else render_pass.height;
|
||||
push_cmd_set_viewport(engine.renderer, width, height);
|
||||
|
||||
push_cmd_set_render_targets(engine.renderer, depth_stencil_enabled=render_pass.has_depth_stencil, depth_stencil_buffer=render_pass.depth_stencil);
|
||||
push_cmd_clear_depth_stencil(engine.renderer, render_pass.depth_stencil, 1.0);
|
||||
} else {
|
||||
assert(render_pass.uses_backbuffer);
|
||||
push_cmd_set_backbuffer(engine.renderer);
|
||||
|
||||
Reference in New Issue
Block a user