diff options
-rw-r--r-- | doc/classes/DirectionalLight3D.xml | 1 | ||||
-rw-r--r-- | doc/classes/SpotLight3D.xml | 3 | ||||
-rw-r--r-- | scene/3d/light_3d.cpp | 9 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_rd.cpp | 10 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl | 25 | ||||
-rw-r--r-- | servers/rendering/renderer_scene_cull.cpp | 75 |
6 files changed, 20 insertions, 103 deletions
diff --git a/doc/classes/DirectionalLight3D.xml b/doc/classes/DirectionalLight3D.xml index 4f51adb8fc..0060368207 100644 --- a/doc/classes/DirectionalLight3D.xml +++ b/doc/classes/DirectionalLight3D.xml @@ -36,7 +36,6 @@ <member name="directional_shadow_split_3" type="float" setter="set_param" getter="get_param" default="0.5"> The distance from shadow split 2 to split 3. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [code]SHADOW_PARALLEL_4_SPLITS[/code]. </member> - <member name="shadow_bias" type="float" setter="set_param" getter="get_param" override="true" default="0.05" /> <member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" override="true" default="1.0" /> <member name="use_in_sky_only" type="bool" setter="set_sky_only" getter="is_sky_only" default="false"> If [code]true[/code], this [DirectionalLight3D] will not be used for anything except sky shaders. Use this for lights that impact your sky shader that you may want to hide from affecting the rest of the scene. For example, you may want to enable this when the sun in your sky shader falls below the horizon. diff --git a/doc/classes/SpotLight3D.xml b/doc/classes/SpotLight3D.xml index f868503bbd..fde40ba6de 100644 --- a/doc/classes/SpotLight3D.xml +++ b/doc/classes/SpotLight3D.xml @@ -13,8 +13,7 @@ <methods> </methods> <members> - <member name="shadow_bias" type="float" setter="set_param" getter="get_param" override="true" default="0.02" /> - <member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" override="true" default="1.0" /> + <member name="shadow_bias" type="float" setter="set_param" getter="get_param" override="true" default="0.03" /> <member name="spot_angle" type="float" setter="set_param" getter="get_param" default="45.0"> The spotlight's angle in degrees. </member> diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 328cb8b22b..508f8a70df 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -212,6 +212,10 @@ void Light3D::_validate_property(PropertyInfo &property) const { property.usage = PROPERTY_USAGE_NONE; } + if (get_light_type() == RS::LIGHT_SPOT && property.name == "shadow_normal_bias") { + property.usage = PROPERTY_USAGE_NONE; + } + if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_projector") { property.usage = PROPERTY_USAGE_NONE; } @@ -340,7 +344,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) { set_param(PARAM_SHADOW_FADE_START, 0.8); set_param(PARAM_SHADOW_PANCAKE_SIZE, 20.0); set_param(PARAM_SHADOW_BLUR, 1.0); - set_param(PARAM_SHADOW_BIAS, 0.02); + set_param(PARAM_SHADOW_BIAS, 0.03); set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0); set_param(PARAM_TRANSMITTANCE_BIAS, 0.05); set_param(PARAM_SHADOW_VOLUMETRIC_FOG_FADE, 0.1); @@ -422,7 +426,8 @@ DirectionalLight3D::DirectionalLight3D() : set_param(PARAM_SHADOW_FADE_START, 0.8); // Increase the default shadow bias to better suit most scenes. // Leave normal bias untouched as it doesn't benefit DirectionalLight3D as much as OmniLight3D. - set_param(PARAM_SHADOW_BIAS, 0.05); + set_param(PARAM_SHADOW_BIAS, 0.1); + set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0); set_shadow_mode(SHADOW_PARALLEL_4_SPLITS); blend_splits = false; } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index fd797b1cab..057d108578 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2777,7 +2777,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const CameraMatrix shadow_mtx = rectm * bias * matrix * modelview; light_data.shadow_split_offsets[j] = split; float bias_scale = li->shadow_transform[j].bias_scale; - light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_scale; + light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale; light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size; light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale; light_data.shadow_z_range[j] = li->shadow_transform[j].farplane; @@ -2948,14 +2948,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.shadow_enabled = true; if (type == RS::LIGHT_SPOT) { - light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0); - float shadow_texel_size = Math::tan(Math::deg2rad(spot_angle)) * radius * 2.0; - shadow_texel_size *= light_instance_get_shadow_texel_size(li->self, p_shadow_atlas); - - light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size; + light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0); } else { //omni - light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0; + light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0; float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas); light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 2.0; // applied in -1 .. 1 space } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index 5920444f7a..4a41c66ef3 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -410,14 +410,8 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { vec4 v = vec4(vertex, 1.0); vec4 splane = (omni_lights.data[idx].shadow_matrix * v); - float shadow_len = length(splane.xyz); //need to remember shadow len from here - { - vec3 nofs = normal_interp * omni_lights.data[idx].shadow_normal_bias / omni_lights.data[idx].inv_radius; - nofs *= (1.0 - max(0.0, dot(normalize(light_rel_vec), normalize(normal_interp)))); - v.xyz += nofs; - splane = (omni_lights.data[idx].shadow_matrix * v); - } + float shadow_len = length(splane.xyz); //need to remember shadow len from here float shadow; @@ -526,7 +520,8 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { splane.xy /= splane.z; splane.xy = splane.xy * 0.5 + 0.5; - splane.z = (shadow_len - omni_lights.data[idx].shadow_bias) * omni_lights.data[idx].inv_radius; + splane.z = shadow_len * omni_lights.data[idx].inv_radius; + splane.z -= omni_lights.data[idx].shadow_bias; splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; splane.w = 1.0; //needed? i think it should be 1 already shadow = sample_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane); @@ -702,27 +697,17 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { //there is a shadowmap vec4 v = vec4(vertex, 1.0); - v.xyz -= spot_dir * spot_lights.data[idx].shadow_bias; - - float z_norm = dot(spot_dir, -light_rel_vec) * spot_lights.data[idx].inv_radius; - - float depth_bias_scale = 1.0 / (max(0.0001, z_norm)); //the closer to the light origin, the more you have to offset to reach 1px in the map - vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(spot_dir, -normalize(normal_interp)))) * spot_lights.data[idx].shadow_normal_bias * depth_bias_scale; - normal_bias -= spot_dir * dot(spot_dir, normal_bias); //only XY, no Z - v.xyz += normal_bias; - - //adjust with bias - z_norm = dot(spot_dir, v.xyz - spot_lights.data[idx].position) * spot_lights.data[idx].inv_radius; - float shadow; vec4 splane = (spot_lights.data[idx].shadow_matrix * v); splane /= splane.w; + splane.z -= spot_lights.data[idx].shadow_bias; if (sc_use_light_soft_shadows && spot_lights.data[idx].soft_shadow_size > 0.0) { //soft shadow //find blocker + float z_norm = dot(spot_dir, -light_rel_vec) * spot_lights.data[idx].inv_radius; vec2 shadow_uv = splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 6357a6f4c2..4a4976718c 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -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; } |