- Home /
[SOLVED!] Darken Shadows over distance - Deferred Shading question
Hi everyone,
I am trying to adjust shadow strength over distance. This is because I want cave entrances and shadows in general to be full strength when they are far away -and I can hide all interior geometry inside such caves until the player comes close enough for shadow strength to be greater than 0,0,0 black. For this particular project it would give a very big performance boost without resorting to dithered LOD fading or other unity techniques (which I have given a fair bit of testing already).
I have already identified the right part of the Internal-ScreenSpaceShadows code that needs to be changed.
The problem is finding the distance from the camera to the target pixel. I want to avoid reading the camera depth texture again, but I can't seem to make it work.
float someDistanceNumber = 100;
float shadowDarken = smoothstep( 0, someDistanceNumber, distance( vpos, i.pos ));
These lines of code (specifically the shadowDarken float) right at the end of the shader seems to be returning either 1 or 0 no matter what I do. What am I doing wrong here?
The full frag shader from Internal-ScreenSpaceShadows is pasted here for convenience (just the pcf5x5 is relevant to me):
fixed4 frag_pcf5x5(v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); // required for sampling the correct slice of the shadow map render texture array
float3 vpos = computeCameraSpacePosFromDepth(i);
// sample the cascade the pixel belongs to
float4 wpos = mul(unity_CameraToWorld, float4(vpos,1));
fixed4 cascadeWeights = GET_CASCADE_WEIGHTS(wpos, vpos.z);
float4 coord = GET_SHADOW_COORDINATES(wpos, cascadeWeights);
float2 receiverPlaneDepthBiasCascade0 = 0.0;
float2 receiverPlaneDepthBias = 0.0;
#if UNITY_USE_RECEIVER_PLANE_BIAS
// Reveiver plane depth bias: need to calculate it based on shadow coordinate
// as it would be in first cascade; otherwise derivatives
// at cascade boundaries will be all wrong. So compute
// it from cascade 0 UV, and scale based on which cascade we're in.
//
float3 coordCascade0 = getShadowCoord_SingleCascade(wpos);
receiverPlaneDepthBiasCascade0 = getReceiverPlaneDepthBias(coordCascade0.xyz);
float biasMultiply = dot(cascadeWeights,unity_ShadowCascadeScales);
receiverPlaneDepthBias = receiverPlaneDepthBiasCascade0 * biasMultiply;
// Static depth biasing to make up for incorrect fractional
// sampling on the shadow map grid; from "A Sampling of Shadow Techniques"
// (http://mynameismjp.wordpress.com/2013/09/10/shadow-maps/)
float fractionalSamplingError = 2 * dot(_ShadowMapTexture_TexelSize.xy, abs(receiverPlaneDepthBias));
coord.z -= min(fractionalSamplingError, UNITY_RECEIVER_PLANE_MIN_FRACTIONAL_ERROR);
#endif
half shadow = sampleShadowmap_PCF5x5(coord, receiverPlaneDepthBias);
// Blend between shadow cascades if enabled
//
// Not working yet with split spheres, and no need when 1 cascade
#if UNITY_USE_CASCADE_BLENDING && !defined(SHADOWS_SPLIT_SPHERES) && !defined(SHADOWS_SINGLE_CASCADE)
half4 z4 = (float4(vpos.z,vpos.z,vpos.z,vpos.z) - _LightSplitsNear) / (_LightSplitsFar - _LightSplitsNear);
half alpha = dot(z4 * cascadeWeights, half4(1,1,1,1));
UNITY_BRANCH
if (alpha > 1 - UNITY_CASCADE_BLEND_DISTANCE)
{
// get alpha to 0..1 range over the blend distance
alpha = (alpha - (1 - UNITY_CASCADE_BLEND_DISTANCE)) / UNITY_CASCADE_BLEND_DISTANCE;
// sample next cascade
cascadeWeights = fixed4(0, cascadeWeights.xyz);
coord = GET_SHADOW_COORDINATES(wpos, cascadeWeights);
#if UNITY_USE_RECEIVER_PLANE_BIAS
biasMultiply = dot(cascadeWeights,unity_ShadowCascadeScales);
receiverPlaneDepthBias = receiverPlaneDepthBiasCascade0 * biasMultiply;
fractionalSamplingError = 2 * dot(_ShadowMapTexture_TexelSize.xy, abs(receiverPlaneDepthBias));
coord.z -= min(fractionalSamplingError, UNITY_RECEIVER_PLANE_MIN_FRACTIONAL_ERROR);
#endif
half shadowNextCascade = sampleShadowmap_PCF3x3(coord, receiverPlaneDepthBias);
shadow = lerp(shadow, shadowNextCascade, alpha);
}
#endif
float someDistanceNumber = 100;
float shadowDarken = smoothstep( 0, someDistanceNumber, distance( vpos, i.pos ));
shadow = lerp(shadow, 0.5 + 0.5 * shadow, shadowDarken);
return shadow;
}
It may be of interest that passing the fade/distance as a TEXCOORD from the vertex shader also seems to not be working, and I'm not sure why this is happening either.
Answer by David-Lindsay · Jun 26, 2017 at 06:04 AM
Sorry to disturb anyone. It was a very silly error
In case you wanted to use this idea for yourself, please go ahead.
float someDistanceNumber = 50; //(meters)
float shadowDarken = smoothstep( 1, 0, vpos.z / someDistanceNumber ); //(because vpos.z is depth)
shadow = lerp(shadow, 0.1 + 0.9 * shadow, shadowDarken);
Hope it helps someone out there! :-)
Your answer
![](https://koobas.hobune.stream/wayback/20220612124910im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Problem with Point lights and defered lighting on walls 2 Answers
Turned on deferred lighting, no shadow 0 Answers
Deferred Rendering lighting bug. 0 Answers
Light artifacts 0 Answers
Large scene with point lights 1 Answer