Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- DECLARATIONS shadow_map_sampling
- {{
- #define SHADOW_EPSILON 14.f
- #define MIN_VARIANCE 4.f
- SAMPLER_CMPDECL( shadow_map_0 );
- SAMPLER_CMPDECL( shadow_map_1 );
- SAMPLER_CMPDECL( shadow_map_2 );
- SAMPLER_CMPDECL( shadow_map_3 );
- SamplerState genericSampler{
- Filter = MIN_MAG_MIP_LINEAR; //sets min/mag/mip filter to linear
- AddressU = Wrap;
- AddressV = Wrap;
- };
- CBUFFER_BEGIN( cshadow_map_sampling )
- float4x4 light_matrices_0;
- float4x4 light_matrices_1;
- float4x4 light_matrices_2;
- float4x4 light_matrices_3;
- float4 shadow_scale_0;
- float4 shadow_scale_1;
- float4 shadow_scale_2;
- float4 shadow_scale_3;
- float4 shadow_samples;
- CBUFFER_END
- float linstep( float min, float max, float v )
- {
- return saturate( ( v - min ) / (max - min ) );
- }
- float ReduceLightBleeding( float p_max, float amount )
- {
- return linstep( amount, 1, p_max );
- }
- float ChebyshevUpperBound( float2 Moments, float t )
- {
- //One tailed inequality valid if t > Moments.x
- float p = ( t <= Moments.x );
- float Variance = Moments.y - (Moments.x * Moments.x);
- Variance = max( Variance, MIN_VARIANCE );
- //Compute probabilistic upper bound.
- float d = t - Moments.x;
- float p_max = Variance / ( Variance + d * d );
- //return p;//_max;
- return max( p, p_max );
- }
- //Used for Varience shadow mapping only
- float ShadowContribution( SAMPLER_ARGCMPDECL( shadow_map ), float2 LightTexCoord, float DistanceToLight )
- {
- #ifdef VARIANCE_SHADOW_MAPPING
- //Read the moments from the variance shadow map
- float2 Moments = SAMPLE_TEX2D( shadow_map, LightTexCoord ).xy;
- // Compute the upper bound
- return ChebyshevUpperBound( Moments, DistanceToLight );
- #else
- return 1.0;
- #endif
- }
- float ShadowMap( float4 position, float4x4 light_matrix, float4 shadow_scale, SAMPLER_ARGCMPDECL( shadow_map ), uniform bool directional )
- {
- #ifndef VARIANCE_SHADOW_MAPPING
- #define SHADOW_MAP_SAMPLES 7
- float4 light_space_pos = mul( position, light_matrix );
- if(!directional)
- light_space_pos.z-=(light_space_pos.z*shadow_scale.z + 1.0f)/light_space_pos.w; // apply bias
- float blur_range=(directional ? 1.0f/5000.0f : 0.14f);
- blur_range*=8.14f;
- const float2 offsets[SHADOW_MAP_SAMPLES]=
- {
- float2(0.000, 0.000)*blur_range,
- float2(1.000, 0.000)*blur_range,
- float2(0.500, 0.866)*blur_range,
- float2(-0.500, 0.866)*blur_range,
- float2(-1.000, -0.000)*blur_range,
- float2(-0.500, -0.866)*blur_range,
- float2(0.500, -0.866)*blur_range,
- };
- float light=0;
- for(int i=0; i< SHADOW_MAP_SAMPLES; i++)
- {
- float4 pos=light_space_pos;
- if(directional)pos.xy+=offsets[i]*shadow_scale.xy;
- else pos.xy+=offsets[i];
- #if defined( DX11 ) || defined( GNMX )
- light += SAMPLE_CMPLEVELZERO( shadow_map, pos).x;
- #else
- light += SAMPLE_TEX2DPROJ(shadow_map, pos).x;
- #endif
- }
- #if ENABLE_SHADOW_FADING
- #if TEXTURE_BORDER_BASED
- const float fade_range=0.9f; // 0 .. 1 parameter, affecting range of shadows fading (0=fading occurs on whole shadow range, 1=no fading occurs)
- float2 shadow_map_uv=light_space_pos.xy/light_space_pos.w; // focus at 0 .. 1 range
- float2 delta=abs(shadow_map_uv-0.5f); // focus at 0 .. 0.5
- float fade=max(delta.x, delta.y); // focus at 0 .. 0.5
- fade=linstep(fade_range*0.5f, 0.5f, fade); // range 0 .. 1
- #else // pixel vs camera distance
- float fade=linstep(1200, 5000, length(position.xyz-camera_position.xyz));
- #endif
- return lerp(light*(1.0f/SHADOW_MAP_SAMPLES), 1, fade);
- #else
- return light*(1.0f/SHADOW_MAP_SAMPLES);
- #endif
- #else
- //Variance shadow mapping
- float4 light_space_pos = mul( position, light_matrix );
- light_space_pos.xy /= light_space_pos.w;
- const float distance = light_space_pos.z;
- return ShadowContribution( SAMPLER_ARG( shadow_map ), light_space_pos.xy, distance );
- #endif
- }
- }}
- DECLARATIONS shadow_map_generation
- {{
- CBUFFER_BEGIN( cshadow_map_generation )
- float4x4 shadow_map_view_projection;
- float4 shadow_map_view;
- CBUFFER_END
- float2 ComputeMoments( float Depth )
- {
- //Depth += 4.0f; //What is this for?
- float2 Moments;
- //First component is simple depth
- Moments.x = Depth;
- //Compute the partial derivatives of depth.
- float dx = ddx( Depth );
- float dy = ddy( Depth );
- Moments.y = Depth * Depth + 0.25*( dx * dx + dy * dy );
- return Moments;
- }
- }}
- FRAGMENT shadow_map_projection
- include shadow_map_generation
- in float4 iWorldPosition : world_position
- out float4 oProjectedPosition : POSITION
- out float4 oWorldPosition : TEXCOORD0
- {{
- oWorldPosition = iWorldPosition;
- oProjectedPosition = mul( iWorldPosition, shadow_map_view_projection );
- }}
- FRAGMENT shadow_map_output
- include shadow_map_generation
- in float3 iProjectedPosition : world_pos
- out float4 colour : PIXEL_RETURN_SEMANTIC
- {{
- #ifndef VARIANCE_SHADOW_MAPPING
- colour = 0.0f; // we don't need color for hardware shadow maps, as we read it back from the depth buffer
- #else
- //const float distance = length( shadow_map_view.xyz - iProjectedPosition.xyz );
- const float distance = iProjectedPosition.z;
- colour = float4( ComputeMoments( distance ), 0.0f, 0.0f );// / 1000.0f;
- #endif
- }}
- FRAGMENT kill_on_alpha_test
- include basic_materials
- in float2 iTextureUV : uv
- #ifdef COLOR_OUTPUT_ENABLED
- in float4 mod : COLOR0
- #endif
- {{
- #ifdef COLOR_OUTPUT_ENABLED
- // Used 0.49f instead of 0.5f to avoid issues when texture is fully opaque but blend mode is alpha test shadows
- clip( SAMPLE_TEX2D( basic_texture_map, iTextureUV ).a * mod.a - 0.49f );
- #else
- clip( SAMPLE_TEX2D( basic_texture_map, iTextureUV ).a - 0.5f );
- #endif
- }}
Advertisement
Add Comment
Please, Sign In to add comment