|
|
//========== Copyright (c) Valve Corporation, All rights reserved. ==========//
// ps2b cascaded shadow mapping
// can be used for OSX in absence of GL3.x
// 1 2 1
// 2 4 2
// 1 2 1
float CSMSampleShadowBuffer( sampler DepthSampler, const float3 shadowMapPos ) { float fTexelEpsilon = g_flInvCascadeResolution;
float3 shadowMapCenter_objDepth = shadowMapPos.xyz;
float3 shadowMapCenter = shadowMapCenter_objDepth.xyz; // Center of shadow filter
float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space
float4 vUV0 = shadowMapCenter.xyzx + float4( fTexelEpsilon, fTexelEpsilon, 0.0f, -fTexelEpsilon ); float4 vUV1 = shadowMapCenter.xyzx + float4( fTexelEpsilon, -fTexelEpsilon, 0.0f, -fTexelEpsilon );
float4 vOneTaps; vOneTaps.x = tex2Dproj( DepthSampler, float4( vUV0.xyz, 1 ) ).x; vOneTaps.y = tex2Dproj( DepthSampler, float4( vUV0.wyz, 1 ) ).x; vOneTaps.z = tex2Dproj( DepthSampler, float4( vUV1.xyz, 1 ) ).x; vOneTaps.w = tex2Dproj( DepthSampler, float4( vUV1.wyz, 1 ) ).x; float flSum = dot( vOneTaps, 1.0f );
float4 vUV2 = shadowMapCenter.xyzx + float4( fTexelEpsilon, 0.0f, 0.0f, -fTexelEpsilon ); float4 vUV3 = shadowMapCenter.xyzy + float4( 0.0f, -fTexelEpsilon, 0.0f, fTexelEpsilon );
float4 vTwoTaps; vTwoTaps.x = tex2Dproj( DepthSampler, float4( vUV2.xyz, 1 ) ).x; vTwoTaps.y = tex2Dproj( DepthSampler, float4( vUV2.wyz, 1 ) ).x; vTwoTaps.z = tex2Dproj( DepthSampler, float4( vUV3.xyz, 1 ) ).x; vTwoTaps.w = tex2Dproj( DepthSampler, float4( vUV3.xwz, 1 ) ).x; flSum += dot( vTwoTaps, 2.0f );
flSum += tex2Dproj( DepthSampler, float4( shadowMapCenter, 1 ) ).x * 4.0f;
// Sum all 9 Taps
return flSum * ( 1.0f / 16.0f ); }
float CSMSampleShadowBuffer1Tap( float2 vPositionLs, float flComparisonDepth ) { #if ( CSM_VIEWMODELQUALITY == 0 )
return tex2Dproj( CSMDepthAtlasSampler, float4( vPositionLs.x, vPositionLs.y, flComparisonDepth.x, 1.0f) ).x; #else
return CSMSampleShadowBuffer( CSMDepthAtlasSampler, float3( vPositionLs.x, vPositionLs.y, flComparisonDepth ) ); #endif
}
float CSMSampleShadowBuffer( float2 vPositionLs, float flComparisonDepth ) { return CSMSampleShadowBuffer1Tap( vPositionLs, flComparisonDepth ); }
int CSMRangeTestExpanded( float2 vCoords ) { // Returns true if the coordinates are within [.02,.98] - purposely a little sloppy to prevent the shadow filter kernel from leaking outside the cascade's portion of the atlas.
vCoords = vCoords * ( 1.0f / .96f ) - float2( .02f / .96f, .02f / .96f ); return ( dot( saturate( vCoords.xy ) - vCoords.xy, float2( 1, 1 ) ) == 0.0f ); }
int CSMRangeTestNonExpanded( float2 vCoords ) { return ( dot( saturate( vCoords.xy ) - vCoords.xy, float2( 1, 1 ) ) == 0.0f ); }
float4 CSMTransformLightToTexture( float4 pos, float4x4 mat ) { #if defined(_PS3)
return mul( mat, pos ); #else
return mul( pos, mat ); #endif
}
float CSMTransformLightToTexture_Element( float4 pos, float4 matRow ) { return mul( pos, matRow ); }
#if ( CASCADE_SIZE == 0 )
float CSMComputeShadowing( float3 vPositionWs ) { return 1.0f; } #elif ( CSM_MODE >= 1 )
#error Invalid CSM_MODE
#else
// CSM shader quality level 0 (the only supported level on gameconsole or ps_2_b)
#if defined( CSM_LIGHTMAPPEDGENERIC )
float CSMComputeShadowing( float3 vPositionWs ) { float flShadowScalar = 1.0f;
float4 vPosition4Ws = float4( vPositionWs.xyz, 1.0f );
// float3 vPositionToSampleLs = float3( 0.0f, 0.0f, CSMTransformLightToTexture( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices[0] ).z );
float3 vPositionToSampleLs = float3( 0.0f, 0.0f, CSMTransformLightToTexture_Element( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices0z ) );
// only consider cascade 1 and 2 for console/ps_2_b perf
float2 cascadeAtlasUVScale = float2(0.5, 0.5); float2 cascadeAtlasUVOffset = float2(0.5, 0.0); // offset cascade 1
vPositionToSampleLs.x = CSMTransformLightToTexture_Element( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices1x ); vPositionToSampleLs.y = CSMTransformLightToTexture_Element( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices1y );
if ( !CSMRangeTestExpanded( vPositionToSampleLs.xy ) ) { // vPositionToSampleLs.xy = CSMTransformLightToTexture( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices[2] ).xy;
vPositionToSampleLs.x = CSMTransformLightToTexture_Element( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices2x ); vPositionToSampleLs.y = CSMTransformLightToTexture_Element( vPosition4Ws.xyzw, g_matWorldToShadowTexMatrices2y );
// cascadeAtlasUVOffset = cascadeAtlasUVOffsets_2;
cascadeAtlasUVOffset = float2(0.0, 0.5); }
vPositionToSampleLs.xy = saturate( vPositionToSampleLs.xy ) * cascadeAtlasUVScale + cascadeAtlasUVOffset;
float3 vCamDelta = vPositionWs - g_vCamPosition.xyz; float flZLerpFactor = saturate( dot( vCamDelta, vCamDelta ) * g_flSunShadowingZLerpFactorRange + g_flSunShadowingZLerpFactorBase );
flShadowScalar = CSMSampleShadowBuffer( vPositionToSampleLs.xy, vPositionToSampleLs.z ); flShadowScalar = lerp( flShadowScalar, 1.0f, flZLerpFactor );
return flShadowScalar; }
#elif defined( CSM_VERTEXLIT_AND_UNLIT_GENERIC ) || defined( CSM_VERTEXLIT_AND_UNLIT_GENERIC_BUMP ) || defined( CSM_PHONG ) || defined( CSM_CHARACTER )
float CSMComputeShadowing( float3 vPositionWs, float2 lightToTextureXform0or1, float2 lightToTextureXform2, float lightToTextureXform0z ) { float flShadowScalar = 1.0f;
float4 vPosition4Ws = float4( vPositionWs.xyz, 1.0f );
float3 vPositionToSampleLs = float3( 0.0f, 0.0f, lightToTextureXform0z );
#if ( CSM_VIEWMODELQUALITY == 0 )
// only consider cascade 1 and 2 for console/ps_2_b perf
float2 cascadeAtlasUVScale = float2(0.5, 0.5); float2 cascadeAtlasUVOffset = float2(0.5, 0.0); // offset cascade 1
vPositionToSampleLs.xy = lightToTextureXform0or1.xy;
if ( !CSMRangeTestExpanded( vPositionToSampleLs.xy ) ) { vPositionToSampleLs.xy = lightToTextureXform2.xy; cascadeAtlasUVOffset = float2(0.0, 0.5); }
vPositionToSampleLs.xy = saturate( vPositionToSampleLs.xy ) * cascadeAtlasUVScale + cascadeAtlasUVOffset;
float3 vCamDelta = vPositionWs - g_vCamPosition.xyz; float flZLerpFactor = saturate( dot( vCamDelta, vCamDelta ) * g_flSunShadowingZLerpFactorRange + g_flSunShadowingZLerpFactorBase );
flShadowScalar = CSMSampleShadowBuffer( vPositionToSampleLs.xy, vPositionToSampleLs.z ); flShadowScalar = lerp( flShadowScalar, 1.0f, flZLerpFactor ); #else
// Viewmodel shadowing
// only use cascade 0 for viewmodel rendering
vPositionToSampleLs.xy = lightToTextureXform0or1.xy; vPositionToSampleLs.xy = saturate( vPositionToSampleLs.xy ) * float2(0.5, 0.5) + float2(0.5, 0.5); // cascade 3 for viewmodel
flShadowScalar = CSMSampleShadowBuffer( vPositionToSampleLs.xy, vPositionToSampleLs.z ); #endif // CSM_VIEWMODELQUALITY == 0
return flShadowScalar; }
#else
#error This shader does not support CSM
#endif
#endif // #if ( CSM_MODE == 0 )
|