You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
6.8 KiB
191 lines
6.8 KiB
//========== 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 )
|