Add a shadow opacity property to Light3D
This can be used to make shadows translucent for a specific light. The light distance fade system also uses this to smoothly fade the shadow when the light fade transition distance is greater than 0.
This commit is contained in:
parent
f85a816965
commit
baaa7503c7
|
@ -37,13 +37,12 @@
|
||||||
[b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D].
|
[b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D].
|
||||||
</member>
|
</member>
|
||||||
<member name="distance_fade_length" type="float" setter="set_distance_fade_length" getter="get_distance_fade_length" default="10.0">
|
<member name="distance_fade_length" type="float" setter="set_distance_fade_length" getter="get_distance_fade_length" default="10.0">
|
||||||
Distance over which the light fades. The light's energy is progressively reduced over this distance and is completely invisible at the end.
|
Distance over which the light and its shadow fades. The light's energy and shadow's opacity is progressively reduced over this distance and is completely invisible at the end.
|
||||||
[b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D].
|
[b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D].
|
||||||
</member>
|
</member>
|
||||||
<member name="distance_fade_shadow" type="float" setter="set_distance_fade_shadow" getter="get_distance_fade_shadow" default="50.0">
|
<member name="distance_fade_shadow" type="float" setter="set_distance_fade_shadow" getter="get_distance_fade_shadow" default="50.0">
|
||||||
The distance from the camera at which the light's shadow cuts off (in 3D units). Set this to a value lower than [member distance_fade_begin] + [member distance_fade_length] to further improve performance, as shadow rendering is often more expensive than light rendering itself.
|
The distance from the camera at which the light's shadow cuts off (in 3D units). Set this to a value lower than [member distance_fade_begin] + [member distance_fade_length] to further improve performance, as shadow rendering is often more expensive than light rendering itself.
|
||||||
[b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D], and only when [member shadow_enabled] is [code]true[/code].
|
[b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D], and only when [member shadow_enabled] is [code]true[/code].
|
||||||
[b]Note:[/b] Due to a rendering engine limitation, shadows will be disabled instantly instead of fading smoothly according to [member distance_fade_length]. This may result in visible pop-in depending on the scene topography.
|
|
||||||
</member>
|
</member>
|
||||||
<member name="editor_only" type="bool" setter="set_editor_only" getter="is_editor_only" default="false">
|
<member name="editor_only" type="bool" setter="set_editor_only" getter="is_editor_only" default="false">
|
||||||
If [code]true[/code], the light only appears in the editor and will not be visible at runtime.
|
If [code]true[/code], the light only appears in the editor and will not be visible at runtime.
|
||||||
|
@ -95,6 +94,9 @@
|
||||||
<member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" default="1.0">
|
<member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" default="1.0">
|
||||||
Offsets the lookup into the shadow map by the object's normal. This can be used to reduce self-shadowing artifacts without using [member shadow_bias]. In practice, this value should be tweaked along with [member shadow_bias] to reduce artifacts as much as possible.
|
Offsets the lookup into the shadow map by the object's normal. This can be used to reduce self-shadowing artifacts without using [member shadow_bias]. In practice, this value should be tweaked along with [member shadow_bias] to reduce artifacts as much as possible.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="shadow_opacity" type="float" setter="set_param" getter="get_param" default="1.0">
|
||||||
|
The opacity to use when rendering the light's shadow map. Values lower than [code]1.0[/code] make the light appear through shadows. This can be used to fake global illumination at a low performance cost.
|
||||||
|
</member>
|
||||||
<member name="shadow_reverse_cull_face" type="bool" setter="set_shadow_reverse_cull_face" getter="get_shadow_reverse_cull_face" default="false">
|
<member name="shadow_reverse_cull_face" type="bool" setter="set_shadow_reverse_cull_face" getter="get_shadow_reverse_cull_face" default="false">
|
||||||
If [code]true[/code], reverses the backface culling of the mesh. This can be useful when you have a flat mesh that has a light behind it. If you need to cast a shadow on both sides of the mesh, set the mesh to use double-sided shadows with [constant GeometryInstance3D.SHADOW_CASTING_SETTING_DOUBLE_SIDED].
|
If [code]true[/code], reverses the backface culling of the mesh. This can be useful when you have a flat mesh that has a light behind it. If you need to cast a shadow on both sides of the mesh, set the mesh to use double-sided shadows with [constant GeometryInstance3D.SHADOW_CASTING_SETTING_DOUBLE_SIDED].
|
||||||
</member>
|
</member>
|
||||||
|
@ -150,15 +152,19 @@
|
||||||
<constant name="PARAM_SHADOW_PANCAKE_SIZE" value="15" enum="Param">
|
<constant name="PARAM_SHADOW_PANCAKE_SIZE" value="15" enum="Param">
|
||||||
Constant for accessing [member DirectionalLight3D.directional_shadow_pancake_size].
|
Constant for accessing [member DirectionalLight3D.directional_shadow_pancake_size].
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="PARAM_SHADOW_BLUR" value="16" enum="Param">
|
<constant name="PARAM_SHADOW_OPACITY" value="16" enum="Param">
|
||||||
|
Constant for accessing [member shadow_opacity].
|
||||||
|
</constant>
|
||||||
|
<constant name="PARAM_SHADOW_BLUR" value="17" enum="Param">
|
||||||
Constant for accessing [member shadow_blur].
|
Constant for accessing [member shadow_blur].
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="17" enum="Param">
|
<constant name="PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="18" enum="Param">
|
||||||
|
Constant for accessing [member shadow_fog_fade].
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="PARAM_TRANSMITTANCE_BIAS" value="18" enum="Param">
|
<constant name="PARAM_TRANSMITTANCE_BIAS" value="19" enum="Param">
|
||||||
Constant for accessing [member shadow_transmittance_bias].
|
Constant for accessing [member shadow_transmittance_bias].
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="PARAM_MAX" value="19" enum="Param">
|
<constant name="PARAM_MAX" value="20" enum="Param">
|
||||||
Represents the size of the [enum Param] enum.
|
Represents the size of the [enum Param] enum.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="BAKE_DISABLED" value="0" enum="BakeMode">
|
<constant name="BAKE_DISABLED" value="0" enum="BakeMode">
|
||||||
|
|
|
@ -3777,6 +3777,7 @@
|
||||||
The light's energy.
|
The light's energy.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="LIGHT_PARAM_INDIRECT_ENERGY" value="1" enum="LightParam">
|
<constant name="LIGHT_PARAM_INDIRECT_ENERGY" value="1" enum="LightParam">
|
||||||
|
The light's indirect energy multiplier (final indirect energy is [constant LIGHT_PARAM_ENERGY] * [constant LIGHT_PARAM_INDIRECT_ENERGY]).
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="LIGHT_PARAM_SPECULAR" value="2" enum="LightParam">
|
<constant name="LIGHT_PARAM_SPECULAR" value="2" enum="LightParam">
|
||||||
The light's influence on specularity.
|
The light's influence on specularity.
|
||||||
|
@ -3820,14 +3821,17 @@
|
||||||
<constant name="LIGHT_PARAM_SHADOW_PANCAKE_SIZE" value="15" enum="LightParam">
|
<constant name="LIGHT_PARAM_SHADOW_PANCAKE_SIZE" value="15" enum="LightParam">
|
||||||
Sets the size of the directional shadow pancake. The pancake offsets the start of the shadow's camera frustum to provide a higher effective depth resolution for the shadow. However, a high pancake size can cause artifacts in the shadows of large objects that are close to the edge of the frustum. Reducing the pancake size can help. Setting the size to [code]0[/code] turns off the pancaking effect.
|
Sets the size of the directional shadow pancake. The pancake offsets the start of the shadow's camera frustum to provide a higher effective depth resolution for the shadow. However, a high pancake size can cause artifacts in the shadows of large objects that are close to the edge of the frustum. Reducing the pancake size can help. Setting the size to [code]0[/code] turns off the pancaking effect.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="LIGHT_PARAM_SHADOW_BLUR" value="16" enum="LightParam">
|
<constant name="LIGHT_PARAM_SHADOW_OPACITY" value="16" enum="LightParam">
|
||||||
|
The light's shadow opacity. Values lower than [code]1.0[/code] make the light appear through shadows. This can be used to fake global illumination at a low performance cost.
|
||||||
|
</constant>
|
||||||
|
<constant name="LIGHT_PARAM_SHADOW_BLUR" value="17" enum="LightParam">
|
||||||
Blurs the edges of the shadow. Can be used to hide pixel artifacts in low resolution shadow maps. A high value can make shadows appear grainy and can cause other unwanted artifacts. Try to keep as near default as possible.
|
Blurs the edges of the shadow. Can be used to hide pixel artifacts in low resolution shadow maps. A high value can make shadows appear grainy and can cause other unwanted artifacts. Try to keep as near default as possible.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="17" enum="LightParam">
|
<constant name="LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="18" enum="LightParam">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="LIGHT_PARAM_TRANSMITTANCE_BIAS" value="18" enum="LightParam">
|
<constant name="LIGHT_PARAM_TRANSMITTANCE_BIAS" value="19" enum="LightParam">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="LIGHT_PARAM_MAX" value="19" enum="LightParam">
|
<constant name="LIGHT_PARAM_MAX" value="20" enum="LightParam">
|
||||||
Represents the size of the [enum LightParam] enum.
|
Represents the size of the [enum LightParam] enum.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="LIGHT_BAKE_DISABLED" value="0" enum="LightBakeMode">
|
<constant name="LIGHT_BAKE_DISABLED" value="0" enum="LightBakeMode">
|
||||||
|
|
|
@ -1650,7 +1650,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
|
||||||
|
|
||||||
light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
|
light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
|
||||||
|
|
||||||
light_data.shadow_enabled = false;
|
light_data.shadow_opacity = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO, to avoid stalls, should rotate between 3 buffers based on frame index.
|
// TODO, to avoid stalls, should rotate between 3 buffers based on frame index.
|
||||||
|
|
|
@ -165,7 +165,7 @@ private:
|
||||||
float inv_spot_attenuation;
|
float inv_spot_attenuation;
|
||||||
float cos_spot_angle;
|
float cos_spot_angle;
|
||||||
float specular_amount;
|
float specular_amount;
|
||||||
uint32_t shadow_enabled;
|
float shadow_opacity;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(LightData) % 16 == 0, "LightData size must be a multiple of 16 bytes");
|
static_assert(sizeof(LightData) % 16 == 0, "LightData size must be a multiple of 16 bytes");
|
||||||
|
|
||||||
|
|
|
@ -495,7 +495,7 @@ struct LightData { //this structure needs to be as packed as possible
|
||||||
mediump float cone_attenuation;
|
mediump float cone_attenuation;
|
||||||
mediump float cone_angle;
|
mediump float cone_angle;
|
||||||
mediump float specular_amount;
|
mediump float specular_amount;
|
||||||
bool shadow_enabled;
|
mediump float shadow_opacity;
|
||||||
};
|
};
|
||||||
#ifndef DISABLE_LIGHT_OMNI
|
#ifndef DISABLE_LIGHT_OMNI
|
||||||
layout(std140) uniform OmniLightData { // ubo:5
|
layout(std140) uniform OmniLightData { // ubo:5
|
||||||
|
|
|
@ -70,6 +70,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
|
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
|
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
|
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
|
||||||
|
light.param[RS::LIGHT_PARAM_SHADOW_OPACITY] = 1.0;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
|
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
|
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
|
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
|
||||||
|
|
|
@ -224,7 +224,7 @@ bool Light3D::is_editor_only() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Light3D::_validate_property(PropertyInfo &property) const {
|
void Light3D::_validate_property(PropertyInfo &property) const {
|
||||||
if (!shadow && (property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_blur" || property.name == "distance_fade_shadow")) {
|
if (!shadow && (property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_opacity" || property.name == "shadow_blur" || property.name == "distance_fade_shadow")) {
|
||||||
property.usage = PROPERTY_USAGE_NO_EDITOR;
|
property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,6 +299,7 @@ void Light3D::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
|
||||||
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_OPACITY);
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BLUR);
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BLUR);
|
||||||
|
|
||||||
ADD_GROUP("Distance Fade", "distance_fade_");
|
ADD_GROUP("Distance Fade", "distance_fade_");
|
||||||
|
@ -328,6 +329,7 @@ void Light3D::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE);
|
||||||
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_OPACITY);
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR);
|
||||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
|
BIND_ENUM_CONSTANT(PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
|
||||||
BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS);
|
BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS);
|
||||||
|
@ -375,6 +377,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
|
||||||
set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
|
set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
|
||||||
set_param(PARAM_SHADOW_FADE_START, 0.8);
|
set_param(PARAM_SHADOW_FADE_START, 0.8);
|
||||||
set_param(PARAM_SHADOW_PANCAKE_SIZE, 20.0);
|
set_param(PARAM_SHADOW_PANCAKE_SIZE, 20.0);
|
||||||
|
set_param(PARAM_SHADOW_OPACITY, 1.0);
|
||||||
set_param(PARAM_SHADOW_BLUR, 1.0);
|
set_param(PARAM_SHADOW_BLUR, 1.0);
|
||||||
set_param(PARAM_SHADOW_BIAS, 0.03);
|
set_param(PARAM_SHADOW_BIAS, 0.03);
|
||||||
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
|
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
|
PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
|
||||||
PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS,
|
PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS,
|
||||||
PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
|
PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
|
||||||
|
PARAM_SHADOW_OPACITY = RS::LIGHT_PARAM_SHADOW_OPACITY,
|
||||||
PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR,
|
PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR,
|
||||||
PARAM_SHADOW_VOLUMETRIC_FOG_FADE = RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
|
PARAM_SHADOW_VOLUMETRIC_FOG_FADE = RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
|
||||||
PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS,
|
PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS,
|
||||||
|
|
|
@ -2869,7 +2869,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
|
||||||
WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
|
WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
light_data.shadow_enabled = p_using_shadows && light_storage->light_has_shadow(base);
|
light_data.shadow_opacity = p_using_shadows && light_storage->light_has_shadow(base) ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) : 0.0;
|
||||||
|
|
||||||
float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
|
float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
|
||||||
if (angular_diameter > 0.0) {
|
if (angular_diameter > 0.0) {
|
||||||
|
@ -2886,7 +2886,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
|
||||||
angular_diameter = 0.0;
|
angular_diameter = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (light_data.shadow_enabled) {
|
if (light_data.shadow_opacity > 0.001) {
|
||||||
RS::LightDirectionalShadowMode smode = light_storage->light_directional_get_shadow_mode(base);
|
RS::LightDirectionalShadowMode smode = light_storage->light_directional_get_shadow_mode(base);
|
||||||
|
|
||||||
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
|
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
|
||||||
|
@ -3040,19 +3040,26 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
|
||||||
|
|
||||||
// Reuse fade begin, fade length and distance for shadow LOD determination later.
|
// Reuse fade begin, fade length and distance for shadow LOD determination later.
|
||||||
float fade_begin = 0.0;
|
float fade_begin = 0.0;
|
||||||
|
float fade_shadow = 0.0;
|
||||||
float fade_length = 0.0;
|
float fade_length = 0.0;
|
||||||
real_t distance = 0.0;
|
real_t distance = 0.0;
|
||||||
|
|
||||||
float fade = 1.0;
|
float fade = 1.0;
|
||||||
|
float shadow_opacity_fade = 1.0;
|
||||||
if (light_storage->light_is_distance_fade_enabled(li->light)) {
|
if (light_storage->light_is_distance_fade_enabled(li->light)) {
|
||||||
fade_begin = light_storage->light_get_distance_fade_begin(li->light);
|
fade_begin = light_storage->light_get_distance_fade_begin(li->light);
|
||||||
|
fade_shadow = light_storage->light_get_distance_fade_shadow(li->light);
|
||||||
fade_length = light_storage->light_get_distance_fade_length(li->light);
|
fade_length = light_storage->light_get_distance_fade_length(li->light);
|
||||||
distance = camera_plane.distance_to(li->transform.origin);
|
distance = camera_plane.distance_to(li->transform.origin);
|
||||||
|
|
||||||
|
// Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
|
||||||
if (distance > fade_begin) {
|
if (distance > fade_begin) {
|
||||||
// Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
|
|
||||||
fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
|
fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (distance > fade_shadow) {
|
||||||
|
shadow_opacity_fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_shadow) / fade_length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
|
float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
|
||||||
|
@ -3120,7 +3127,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
|
||||||
|
|
||||||
bool in_shadow_range = true;
|
bool in_shadow_range = true;
|
||||||
if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) {
|
if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) {
|
||||||
if (distance > light_storage->light_get_distance_fade_shadow(li->light)) {
|
if (distance > light_storage->light_get_distance_fade_shadow(li->light) + light_storage->light_get_distance_fade_length(li->light)) {
|
||||||
// Out of range, don't draw shadows to improve performance.
|
// Out of range, don't draw shadows to improve performance.
|
||||||
in_shadow_range = false;
|
in_shadow_range = false;
|
||||||
}
|
}
|
||||||
|
@ -3129,7 +3136,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
|
||||||
if (needs_shadow && in_shadow_range) {
|
if (needs_shadow && in_shadow_range) {
|
||||||
// fill in the shadow information
|
// fill in the shadow information
|
||||||
|
|
||||||
light_data.shadow_enabled = true;
|
light_data.shadow_opacity = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) * shadow_opacity_fade;
|
||||||
|
|
||||||
float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
|
float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
|
||||||
light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
|
light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
|
||||||
|
@ -3189,7 +3196,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
light_data.shadow_enabled = false;
|
light_data.shadow_opacity = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
li->cull_mask = light_storage->light_get_cull_mask(base);
|
li->cull_mask = light_storage->light_get_cull_mask(base);
|
||||||
|
@ -3637,7 +3644,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
|
||||||
if (p_render_data->render_buffers.is_valid()) {
|
if (p_render_data->render_buffers.is_valid()) {
|
||||||
bool directional_shadows = false;
|
bool directional_shadows = false;
|
||||||
for (uint32_t i = 0; i < directional_light_count; i++) {
|
for (uint32_t i = 0; i < directional_light_count; i++) {
|
||||||
if (cluster.directional_lights[i].shadow_enabled) {
|
if (cluster.directional_lights[i].shadow_opacity > 0.001) {
|
||||||
directional_shadows = true;
|
directional_shadows = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -608,7 +608,7 @@ private:
|
||||||
float inv_spot_attenuation;
|
float inv_spot_attenuation;
|
||||||
float cos_spot_angle;
|
float cos_spot_angle;
|
||||||
float specular_amount;
|
float specular_amount;
|
||||||
uint32_t shadow_enabled;
|
float shadow_opacity;
|
||||||
|
|
||||||
float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
|
float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
|
||||||
float shadow_matrix[16];
|
float shadow_matrix[16];
|
||||||
|
@ -633,7 +633,7 @@ private:
|
||||||
float softshadow_angle;
|
float softshadow_angle;
|
||||||
float soft_shadow_scale;
|
float soft_shadow_scale;
|
||||||
uint32_t blend_splits;
|
uint32_t blend_splits;
|
||||||
uint32_t shadow_enabled;
|
float shadow_opacity;
|
||||||
float fade_from;
|
float fade_from;
|
||||||
float fade_to;
|
float fade_to;
|
||||||
uint32_t pad[2];
|
uint32_t pad[2];
|
||||||
|
|
|
@ -377,7 +377,7 @@ void main() {
|
||||||
for (uint i = 0; i < params.directional_light_count; i++) {
|
for (uint i = 0; i < params.directional_light_count; i++) {
|
||||||
vec3 shadow_attenuation = vec3(1.0);
|
vec3 shadow_attenuation = vec3(1.0);
|
||||||
|
|
||||||
if (directional_lights.data[i].shadow_enabled) {
|
if (directional_lights.data[i].shadow_opacity > 0.001) {
|
||||||
float depth_z = -view_pos.z;
|
float depth_z = -view_pos.z;
|
||||||
|
|
||||||
vec4 pssm_coord;
|
vec4 pssm_coord;
|
||||||
|
@ -486,7 +486,7 @@ void main() {
|
||||||
|
|
||||||
vec3 light = omni_lights.data[light_index].color;
|
vec3 light = omni_lights.data[light_index].color;
|
||||||
|
|
||||||
if (omni_lights.data[light_index].shadow_enabled) {
|
if (omni_lights.data[light_index].shadow_opacity > 0.001) {
|
||||||
//has shadow
|
//has shadow
|
||||||
vec4 uv_rect = omni_lights.data[light_index].atlas_rect;
|
vec4 uv_rect = omni_lights.data[light_index].atlas_rect;
|
||||||
vec2 flip_offset = omni_lights.data[light_index].direction.xy;
|
vec2 flip_offset = omni_lights.data[light_index].direction.xy;
|
||||||
|
@ -572,7 +572,7 @@ void main() {
|
||||||
|
|
||||||
vec3 light = spot_lights.data[light_index].color;
|
vec3 light = spot_lights.data[light_index].color;
|
||||||
|
|
||||||
if (spot_lights.data[light_index].shadow_enabled) {
|
if (spot_lights.data[light_index].shadow_opacity > 0.001) {
|
||||||
//has shadow
|
//has shadow
|
||||||
vec4 uv_rect = spot_lights.data[light_index].atlas_rect;
|
vec4 uv_rect = spot_lights.data[light_index].atlas_rect;
|
||||||
vec2 flip_offset = spot_lights.data[light_index].direction.xy;
|
vec2 flip_offset = spot_lights.data[light_index].direction.xy;
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct LightData { //this structure needs to be as packed as possible
|
||||||
mediump float cone_attenuation;
|
mediump float cone_attenuation;
|
||||||
mediump float cone_angle;
|
mediump float cone_angle;
|
||||||
mediump float specular_amount;
|
mediump float specular_amount;
|
||||||
bool shadow_enabled;
|
mediump float shadow_opacity;
|
||||||
|
|
||||||
highp vec4 atlas_rect; // rect in the shadow atlas
|
highp vec4 atlas_rect; // rect in the shadow atlas
|
||||||
highp mat4 shadow_matrix;
|
highp mat4 shadow_matrix;
|
||||||
|
@ -60,7 +60,7 @@ struct DirectionalLightData {
|
||||||
highp float softshadow_angle;
|
highp float softshadow_angle;
|
||||||
highp float soft_shadow_scale;
|
highp float soft_shadow_scale;
|
||||||
bool blend_splits;
|
bool blend_splits;
|
||||||
bool shadow_enabled;
|
mediump float shadow_opacity;
|
||||||
highp float fade_from;
|
highp float fade_from;
|
||||||
highp float fade_to;
|
highp float fade_to;
|
||||||
uvec2 pad;
|
uvec2 pad;
|
||||||
|
|
|
@ -1417,7 +1417,7 @@ void fragment_shader(in SceneData scene_data) {
|
||||||
|
|
||||||
float shadow = 1.0;
|
float shadow = 1.0;
|
||||||
|
|
||||||
if (directional_lights.data[i].shadow_enabled) {
|
if (directional_lights.data[i].shadow_opacity > 0.001) {
|
||||||
float depth_z = -vertex.z;
|
float depth_z = -vertex.z;
|
||||||
vec3 light_dir = directional_lights.data[i].direction;
|
vec3 light_dir = directional_lights.data[i].direction;
|
||||||
vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
|
vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
|
||||||
|
@ -1626,7 +1626,7 @@ void fragment_shader(in SceneData scene_data) {
|
||||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||||
float transmittance_z = transmittance_depth;
|
float transmittance_z = transmittance_depth;
|
||||||
|
|
||||||
if (directional_lights.data[i].shadow_enabled) {
|
if (directional_lights.data[i].shadow_opacity > 0.001) {
|
||||||
float depth_z = -vertex.z;
|
float depth_z = -vertex.z;
|
||||||
|
|
||||||
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
|
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
|
||||||
|
@ -1681,6 +1681,8 @@ void fragment_shader(in SceneData scene_data) {
|
||||||
} else {
|
} else {
|
||||||
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
|
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shadow = shadow * directional_lights.data[i].shadow_opacity + 1.0 - directional_lights.data[i].shadow_opacity;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
blur_shadow(shadow);
|
blur_shadow(shadow);
|
||||||
|
|
|
@ -395,7 +395,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||||
|
|
||||||
float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
|
float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
|
||||||
#ifndef SHADOWS_DISABLED
|
#ifndef SHADOWS_DISABLED
|
||||||
if (omni_lights.data[idx].shadow_enabled) {
|
if (omni_lights.data[idx].shadow_opacity > 0.001) {
|
||||||
// there is a shadowmap
|
// there is a shadowmap
|
||||||
vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
|
vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
|
||||||
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
|
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
|
||||||
|
@ -498,6 +498,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
shadow /= float(sc_penumbra_shadow_samples);
|
shadow /= float(sc_penumbra_shadow_samples);
|
||||||
|
shadow = mix(1.0, shadow, omni_lights.data[idx].shadow_opacity);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//no blockers found, so no shadow
|
//no blockers found, so no shadow
|
||||||
|
@ -516,7 +517,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
|
||||||
vec2 pos = shadow_sample.xy / shadow_sample.z;
|
vec2 pos = shadow_sample.xy / shadow_sample.z;
|
||||||
float depth = shadow_len - omni_lights.data[idx].shadow_bias;
|
float depth = shadow_len - omni_lights.data[idx].shadow_bias;
|
||||||
depth *= omni_lights.data[idx].inv_radius;
|
depth *= omni_lights.data[idx].inv_radius;
|
||||||
shadow = sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth);
|
shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth), omni_lights.data[idx].shadow_opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return shadow;
|
return shadow;
|
||||||
|
@ -674,7 +675,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
||||||
|
|
||||||
float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
|
float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
|
||||||
#ifndef SHADOWS_DISABLED
|
#ifndef SHADOWS_DISABLED
|
||||||
if (spot_lights.data[idx].shadow_enabled) {
|
if (spot_lights.data[idx].shadow_opacity > 0.001) {
|
||||||
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
|
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
|
||||||
float light_length = length(light_rel_vec);
|
float light_length = length(light_rel_vec);
|
||||||
vec3 spot_dir = spot_lights.data[idx].direction;
|
vec3 spot_dir = spot_lights.data[idx].direction;
|
||||||
|
@ -735,6 +736,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
shadow /= float(sc_penumbra_shadow_samples);
|
shadow /= float(sc_penumbra_shadow_samples);
|
||||||
|
shadow = mix(1.0, shadow, spot_lights.data[idx].shadow_opacity);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//no blockers found, so no shadow
|
//no blockers found, so no shadow
|
||||||
|
@ -743,7 +745,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
|
||||||
} else {
|
} else {
|
||||||
//hard shadow
|
//hard shadow
|
||||||
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
|
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
|
||||||
shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv);
|
shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv), spot_lights.data[idx].shadow_opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return shadow;
|
return shadow;
|
||||||
|
|
|
@ -1134,7 +1134,7 @@ void main() {
|
||||||
|
|
||||||
#ifdef USE_SOFT_SHADOWS
|
#ifdef USE_SOFT_SHADOWS
|
||||||
//version with soft shadows, more expensive
|
//version with soft shadows, more expensive
|
||||||
if (directional_lights.data[i].shadow_enabled) {
|
if (directional_lights.data[i].shadow_opacity > 0.001) {
|
||||||
float depth_z = -vertex.z;
|
float depth_z = -vertex.z;
|
||||||
|
|
||||||
vec4 pssm_coord;
|
vec4 pssm_coord;
|
||||||
|
@ -1286,7 +1286,7 @@ void main() {
|
||||||
#else
|
#else
|
||||||
// Soft shadow disabled version
|
// Soft shadow disabled version
|
||||||
|
|
||||||
if (directional_lights.data[i].shadow_enabled) {
|
if (directional_lights.data[i].shadow_opacity > 0.001) {
|
||||||
float depth_z = -vertex.z;
|
float depth_z = -vertex.z;
|
||||||
|
|
||||||
vec4 pssm_coord;
|
vec4 pssm_coord;
|
||||||
|
|
|
@ -88,6 +88,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
|
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
|
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
|
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
|
||||||
|
light.param[RS::LIGHT_PARAM_SHADOW_OPACITY] = 1.0;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
|
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
|
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
|
||||||
light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
|
light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
|
||||||
|
|
|
@ -1911,6 +1911,7 @@ void RenderingServer::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
|
||||||
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_OPACITY);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BLUR);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BLUR);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PARAM_TRANSMITTANCE_BIAS);
|
BIND_ENUM_CONSTANT(LIGHT_PARAM_TRANSMITTANCE_BIAS);
|
||||||
|
|
|
@ -425,6 +425,7 @@ public:
|
||||||
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
|
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
|
||||||
LIGHT_PARAM_SHADOW_BIAS,
|
LIGHT_PARAM_SHADOW_BIAS,
|
||||||
LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
|
LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
|
||||||
|
LIGHT_PARAM_SHADOW_OPACITY,
|
||||||
LIGHT_PARAM_SHADOW_BLUR,
|
LIGHT_PARAM_SHADOW_BLUR,
|
||||||
LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
|
LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
|
||||||
LIGHT_PARAM_TRANSMITTANCE_BIAS,
|
LIGHT_PARAM_TRANSMITTANCE_BIAS,
|
||||||
|
|
Loading…
Reference in New Issue