You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Fix directional shadow bias
* Simplified code a lot, bias based on normalized cascade size. * Lets scale cascades, max distance, etc. without creating acne. * Fixed normal biasing in directional shadows. I removed normal biasing in both omni and spot shadows, since the technique can't be easily implemented there. Will need to be replaced by something else.
This commit is contained in:
@@ -1955,10 +1955,6 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
|
||||
|
||||
bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
|
||||
|
||||
real_t first_radius = 0.0;
|
||||
|
||||
real_t min_distance_bias_scale = distances[1];
|
||||
|
||||
cull.shadow_count = p_shadow_index + 1;
|
||||
cull.shadows[p_shadow_index].cascade_count = splits;
|
||||
cull.shadows[p_shadow_index].light_instance = light->instance;
|
||||
@@ -2006,8 +2002,8 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
|
||||
real_t z_min_cam = 0.f;
|
||||
//real_t z_max_cam = 0.f;
|
||||
|
||||
real_t bias_scale = 1.0;
|
||||
real_t aspect_bias_scale = 1.0;
|
||||
//real_t bias_scale = 1.0;
|
||||
//real_t aspect_bias_scale = 1.0;
|
||||
|
||||
//used for culling
|
||||
|
||||
@@ -2061,12 +2057,6 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
|
||||
|
||||
radius *= texture_size / (texture_size - 2.0); //add a texel by each side
|
||||
|
||||
if (i == 0) {
|
||||
first_radius = radius;
|
||||
} else {
|
||||
bias_scale = radius / first_radius;
|
||||
}
|
||||
|
||||
z_min_cam = z_vec.dot(center) - radius;
|
||||
|
||||
{
|
||||
@@ -2110,64 +2100,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
|
||||
|
||||
// a pre pass will need to be needed to determine the actual z-near to be used
|
||||
|
||||
if (pancake_size > 0) {
|
||||
z_max = z_vec.dot(center) + radius + pancake_size;
|
||||
}
|
||||
|
||||
if (aspect != 1.0) {
|
||||
// if the aspect is different, then the radius will become larger.
|
||||
// if this happens, then bias needs to be adjusted too, as depth will increase
|
||||
// to do this, compare the depth of one that would have resulted from a square frustum
|
||||
|
||||
CameraMatrix camera_matrix_square;
|
||||
if (p_cam_orthogonal) {
|
||||
Vector2 vp_he = camera_matrix.get_viewport_half_extents();
|
||||
if (p_cam_vaspect) {
|
||||
camera_matrix_square.set_orthogonal(vp_he.x * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
|
||||
} else {
|
||||
camera_matrix_square.set_orthogonal(vp_he.y * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
|
||||
}
|
||||
} else {
|
||||
Vector2 vp_he = camera_matrix.get_viewport_half_extents();
|
||||
if (p_cam_vaspect) {
|
||||
camera_matrix_square.set_frustum(vp_he.x * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
|
||||
} else {
|
||||
camera_matrix_square.set_frustum(vp_he.y * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 endpoints_square[8]; // frustum plane endpoints
|
||||
res = camera_matrix_square.get_endpoints(p_cam_transform, endpoints_square);
|
||||
ERR_CONTINUE(!res);
|
||||
Vector3 center_square;
|
||||
|
||||
for (int j = 0; j < 8; j++) {
|
||||
center_square += endpoints_square[j];
|
||||
}
|
||||
|
||||
center_square /= 8.0;
|
||||
|
||||
real_t radius_square = 0;
|
||||
|
||||
for (int j = 0; j < 8; j++) {
|
||||
real_t d = center_square.distance_to(endpoints_square[j]);
|
||||
if (d > radius_square) {
|
||||
radius_square = d;
|
||||
}
|
||||
}
|
||||
|
||||
radius_square *= texture_size / (texture_size - 2.0); //add a texel by each side
|
||||
|
||||
float z_max_square = z_vec.dot(center_square) + radius_square + pancake_size;
|
||||
|
||||
real_t z_min_cam_square = z_vec.dot(center_square) - radius_square;
|
||||
|
||||
aspect_bias_scale = (z_max - z_min_cam) / (z_max_square - z_min_cam_square);
|
||||
|
||||
// this is not entirely perfect, because the cull-adjusted z-max may be different
|
||||
// but at least it's warranted that it results in a greater bias, so no acne should be present either way.
|
||||
// pancaking also helps with this.
|
||||
}
|
||||
z_max = z_vec.dot(center) + radius + pancake_size;
|
||||
|
||||
{
|
||||
CameraMatrix ortho_camera;
|
||||
@@ -2188,7 +2121,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
|
||||
cull.shadows[p_shadow_index].cascades[i].zfar = z_max - z_min_cam;
|
||||
cull.shadows[p_shadow_index].cascades[i].split = distances[i + 1];
|
||||
cull.shadows[p_shadow_index].cascades[i].shadow_texel_size = radius * 2.0 / texture_size;
|
||||
cull.shadows[p_shadow_index].cascades[i].bias_scale = bias_scale * aspect_bias_scale * min_distance_bias_scale;
|
||||
cull.shadows[p_shadow_index].cascades[i].bias_scale = (z_max - z_min_cam);
|
||||
cull.shadows[p_shadow_index].cascades[i].range_begin = z_max;
|
||||
cull.shadows[p_shadow_index].cascades[i].uv_scale = uv_scale;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user