From 239c7e58d2cbe5ede8d1c40c674a1345d40c4bef Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 13 Dec 2022 21:48:39 +0000 Subject: [PATCH] Shadow tests only works on vectorLight (eg sun and scatter sky) for now --- .../advanced/advancedLightBinManager.cpp | 4 +- .../lighting/shadowMap/lightShadowMap.cpp | 16 +- .../lighting/shadowMap/lightShadowMap.h | 1 + .../scripts/advancedLighting_Shaders.tscript | 19 +- .../game/core/rendering/shaders/lighting.hlsl | 23 ++- .../lighting/advanced/pointLightP.hlsl | 5 +- .../shaders/lighting/advanced/softShadow.hlsl | 193 +++++++++--------- .../shaders/lighting/advanced/spotLightP.hlsl | 11 +- .../lighting/advanced/vectorLightP.hlsl | 31 ++- 9 files changed, 182 insertions(+), 121 deletions(-) diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index fd8cd6dc4..c14a3455b 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -807,7 +807,9 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light const F32 innerCone = getMin(lightInfo->getInnerConeAngle(), outerCone); const F32 outerCos = mCos(mDegToRad(outerCone / 2.0f)); const F32 innerCos = mCos(mDegToRad(innerCone / 2.0f)); - Point2F spotParams(outerCos,innerCos - outerCos); + const F32 lightAngleScale = 1.0f / getMax(0.001f, (innerCos - outerCos)); + const F32 lightAngleOffset = -outerCos * lightAngleScale; + Point2F spotParams(lightAngleScale, lightAngleOffset); matParams->setSafe( lightSpotParams, spotParams ); matParams->setSafe( lightDirection, lightInfo->getDirection()); diff --git a/Engine/source/lighting/shadowMap/lightShadowMap.cpp b/Engine/source/lighting/shadowMap/lightShadowMap.cpp index 9ecde8c97..09de74413 100644 --- a/Engine/source/lighting/shadowMap/lightShadowMap.cpp +++ b/Engine/source/lighting/shadowMap/lightShadowMap.cpp @@ -265,8 +265,16 @@ bool LightShadowMap::setTextureStage( U32 currTexFlag, LightingShaderConstants* { S32 reg = lsc->mShadowMapSC->getSamplerRegister(); - if ( reg != -1 ) - GFX->setTexture( reg, mShadowMapTex); + if (reg != -1) + { + GFX->setTexture(reg, mShadowMapTex); + } + + reg = lsc->mShadowMapCMPSC->getSamplerRegister(); + if (reg != -1) + { + GFX->setTexture(reg, mShadowMapTex); + } return true; } else if ( currTexFlag == Material::DynamicLightMask ) @@ -427,7 +435,8 @@ LightingShaderConstants::LightingShaderConstants() mVectorLightDirectionSC(NULL), mVectorLightColorSC(NULL), mVectorLightBrightnessSC(NULL), - mShadowMapSC(NULL), + mShadowMapSC(NULL), + mShadowMapCMPSC(NULL), mShadowMapSizeSC(NULL), mCookieMapSC(NULL), mRandomDirsConst(NULL), @@ -487,6 +496,7 @@ void LightingShaderConstants::init(GFXShader* shader) mVectorLightBrightnessSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightBrightness); mShadowMapSC = shader->getShaderConstHandle("$shadowMap"); + mShadowMapCMPSC = shader->getShaderConstHandle("$shadowMapCMP"); mShadowMapSizeSC = shader->getShaderConstHandle("$shadowMapSize"); mCookieMapSC = shader->getShaderConstHandle("$cookieMap"); diff --git a/Engine/source/lighting/shadowMap/lightShadowMap.h b/Engine/source/lighting/shadowMap/lightShadowMap.h index 57870ac62..ee1f5ac00 100644 --- a/Engine/source/lighting/shadowMap/lightShadowMap.h +++ b/Engine/source/lighting/shadowMap/lightShadowMap.h @@ -96,6 +96,7 @@ struct LightingShaderConstants GFXShaderConstHandle* mVectorLightBrightnessSC; GFXShaderConstHandle* mShadowMapSC; + GFXShaderConstHandle* mShadowMapCMPSC; GFXShaderConstHandle* mShadowMapSizeSC; GFXShaderConstHandle* mCookieMapSC; diff --git a/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Shaders.tscript b/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Shaders.tscript index 104056efe..dec7b527b 100644 --- a/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Shaders.tscript +++ b/Templates/BaseGame/game/core/lighting/scripts/advancedLighting_Shaders.tscript @@ -20,6 +20,14 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +singleton GFXSamplerStateData(ShadowSampler) +{ + addressModeU = GFXAddressMirror; + addressModeV = GFXAddressMirror; + magFilter = GFXTextureFilterLinear; + minFilter = GFXTextureFilterLinear; + samplerFunc = GFXCmpGreater; +}; // Vector Light State singleton GFXStateBlockData( AL_VectorLightState ) @@ -44,9 +52,10 @@ singleton GFXStateBlockData( AL_VectorLightState ) samplersDefined = true; samplerStates[0] = SamplerClampPoint; // G-buffer samplerStates[1] = SamplerClampPoint; // Shadow Map (Do not change this to linear, as all cards can not filter equally.) - samplerStates[3] = SamplerWrapPoint; // gTapRotationTex Random Direction Map - samplerStates[4] = SamplerClampPoint; // colorBuffer - samplerStates[5] = SamplerClampPoint; // matInfoBuffer + samplerStates[2] = SamplerWrapPoint; // gTapRotationTex Random Direction Map + samplerStates[3] = SamplerClampPoint; // colorBuffer + samplerStates[4] = SamplerClampPoint; // matInfoBuffer + samplerStates[5] = ShadowSampler; // Shadow Map (Do not change this to linear, as all cards can not filter equally.) cullDefined = true; cullMode = GFXCullNone; @@ -69,7 +78,8 @@ singleton shaderData( AL_VectorLightShader ) samplerNames[1] = "$shadowMap"; samplerNames[2] = "$gTapRotationTex"; samplerNames[3] = "$colorBuffer"; - samplerNames[4] = "$matInfoBuffer"; + samplerNames[4] = "$matInfoBuffer"; + samplerNames[5] = "$shadowMapCMP"; pixVersion = 3.0; }; @@ -83,6 +93,7 @@ singleton CustomMaterial( AL_VectorLightMaterial ) sampler["shadowMap"] = "$dynamiclight"; sampler["colorBuffer"] = "#color"; sampler["matInfoBuffer"] = "#matinfo"; + sampler["shadowMapCMP"] = "$dynamiclight"; target = "AL_FormatToken"; diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl index 3ddb51982..ccb9c6cff 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl @@ -204,23 +204,21 @@ float smoothDistanceAtt ( float squaredDistance , float invSqrAttRadius ) { float factor = squaredDistance * invSqrAttRadius ; float smoothFactor = saturate (1.0f - factor * factor ); - return sqr(smoothFactor); + return smoothFactor * smoothFactor; } float getDistanceAtt( float3 unormalizedLightVector , float invSqrAttRadius ) { - float sqrDist = dot ( unormalizedLightVector , unormalizedLightVector ); - float attenuation = 1.0 / (max ( sqrDist , 0.01*0.01) ); - attenuation *= smoothDistanceAtt ( sqrDist , invSqrAttRadius ); + float sqrDist = dot( unormalizedLightVector, unormalizedLightVector ); + float attenuation = 1.0 / sqrDist * smoothDistanceAtt ( sqrDist , invSqrAttRadius ); return attenuation; } - float getSpotAngleAtt( float3 normalizedLightVector , float3 lightDir , float2 lightSpotParams ) + float getSpotAngleAtt( float3 normalizedLightVector , float3 lightDir , float2 lightSpotParams, float exponent ) { - float cd = dot ( lightDir , normalizedLightVector ); - float attenuation = saturate ( ( cd - lightSpotParams.x ) / lightSpotParams.y ); + float attenuation = clamp(dot(lightDir, normalizedLightVector) * lightSpotParams.x + lightSpotParams.y, 0.0, 1.0); // smooth the transition - return sqr(attenuation); + return attenuation * attenuation; } float3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) @@ -250,8 +248,11 @@ float3 getDirectionalLight(Surface surface, SurfaceToLight surfaceToLight, float float3 getPunctualLight(Surface surface, SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float radius, float shadow) { - float attenuation = getDistanceAtt(surfaceToLight.Lu, radius); - float3 factor = lightColor * max(surfaceToLight.NdotL* shadow * lightIntensity * attenuation, 0.0f) ; + float attenuation = 1; + attenuation *= getDistanceAtt(surfaceToLight.Lu, radius); + float3 lCol = lightColor.rgb *(lightIntensity / (4.0 * 3.14159265359)); + float3 radince = lCol * attenuation; + float3 factor = saturate(surfaceToLight.NdotL) * shadow * radince; return evaluateStandardBRDF(surface,surfaceToLight) * factor; } @@ -310,7 +311,7 @@ float4 compute4Lights( Surface surface, //get Punctual light contribution lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed); //get spot angle attenuation - lighting *= getSpotAngleAtt(-surfaceToLight.L, inLightSpotDir[i].xyz, lightSpotParams[i].xy ); + lighting *= getSpotAngleAtt(-surfaceToLight.L, inLightSpotDir[i].xyz, lightSpotParams[i].xy, lightRange ); } } finalLighting += lighting; diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/pointLightP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/pointLightP.hlsl index 60d2f2d00..ad7bb23b1 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/pointLightP.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/pointLightP.hlsl @@ -101,7 +101,7 @@ TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0); #ifdef SHADOW_CUBE TORQUE_UNIFORM_SAMPLERCUBE(shadowMap, 1); #else -TORQUE_UNIFORM_SAMPLER2D(shadowMap, 1); +TORQUE_UNIFORM_SAMPLER2DCMP(shadowMap, 1); #endif //contains gTapRotationTex sampler #include "softShadow.hlsl" @@ -174,7 +174,8 @@ float4 main( ConvexConnectP IN ) : SV_TARGET #else float2 shadowCoord = decodeShadowCoord( mul( worldToLightProj, -surfaceToLight.L ) ).xy; - float shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap), ssPos.xy, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y); + float4 shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap), IN.pos.xy, ssPos.xy, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y); + float shadowed = shadowed_colors.a; #endif #endif // !NO_SHADOW diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/softShadow.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/softShadow.hlsl index ccc90f009..35fb3a160 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/softShadow.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/softShadow.hlsl @@ -22,83 +22,104 @@ #include "../../shaderModel.hlsl" -#if defined( SOFTSHADOW ) && defined( SOFTSHADOW_HIGH_QUALITY ) - -#define NUM_PRE_TAPS 4 -#define NUM_TAPS 12 - -/// The non-uniform poisson disk used in the -/// high quality shadow filtering. -static float2 sNonUniformTaps[NUM_TAPS] = -{ - // These first 4 taps are located around the edges - // of the disk and are used to predict fully shadowed - // or unshadowed areas. - { 0.992833, 0.979309 }, - { -0.998585, 0.985853 }, - { 0.949299, -0.882562 }, - { -0.941358, -0.893924 }, - - // The rest of the samples. - { 0.545055, -0.589072 }, - { 0.346526, 0.385821 }, - { -0.260183, 0.334412 }, - { 0.248676, -0.679605 }, - { -0.569502, -0.390637 }, - { -0.614096, 0.212577 }, - { -0.259178, 0.876272 }, - { 0.649526, 0.864333 }, -}; - -#else - -#define NUM_PRE_TAPS 5 - -/// The non-uniform poisson disk used in the -/// high quality shadow filtering. -static float2 sNonUniformTaps[NUM_PRE_TAPS] = -{ - { 0.892833, 0.959309 }, - { -0.941358, -0.873924 }, - { -0.260183, 0.334412 }, - { 0.348676, -0.679605 }, - { -0.569502, -0.390637 }, -}; - -#endif - +#define NUM_TAPS 16 /// The texture used to do per-pixel pseudorandom /// rotations of the filter taps. TORQUE_UNIFORM_SAMPLER2D(gTapRotationTex, 2); -float softShadow_sampleTaps( TORQUE_SAMPLER2D(shadowMap1), - float2 sinCos, +float2 VogelDisk(int sampleIndex, int sampleCount, float gradient) +{ + float gA = 2.4f; + float r = sqrt(sampleIndex + 0.5f) / sqrt(sampleCount); + float theta = sampleIndex * gA + gradient; + + float sine, cosine; + sincos(theta, sine, cosine); + + return float2(r * cosine, r * sine); +} + +float GradientNoise(float2 screenPos) +{ + float3 mag = float3(0.06711056f, 0.00583715f, 52.9829189f); + return frac(mag.z * frac(dot(screenPos, mag.xy))); +} + +float AvgOccluderDepthPenumbra(float zShadow, float avgDepth) +{ + float penumbra = (zShadow - avgDepth) / avgDepth; + penumbra *= penumbra; + return saturate(80.0f * penumbra); +} + +float AvgOccluderDepthPenumbra(float lightSize, float zShadow, float avgDepth) +{ + float penumbra = lightSize * (zShadow - avgDepth) / avgDepth; + return penumbra; +} + +float Penumbra(TORQUE_SAMPLER2D(shadowMap2), float gradient, float2 shadowUV, float zShadow, float filterRadius, float esmFactor, int sampleCount) +{ + float avgOccluderDepth = 0.0f; + float occluderCount = 0.0f; + float penumbraFilterMaxSize = 8.0 / 1024.0; + for(int i = 0; i < sampleCount; i++) + { + float2 sampleUV = VogelDisk(i, sampleCount, gradient) * penumbraFilterMaxSize; + sampleUV = shadowUV + sampleUV; + float occDepth = TORQUE_TEX2DLOD( shadowMap2, float4(sampleUV,0,0) ).r; + if(occDepth < zShadow) + { + avgOccluderDepth += occDepth; + occluderCount += 1.0f; + } + } + + if(occluderCount > 0.0f) + { + avgOccluderDepth /= occluderCount; + return AvgOccluderDepthPenumbra(1000.0f, zShadow, avgOccluderDepth); + } + else + { + return 0.0f; + } +} + +float softShadow_sampleTaps( TORQUE_SAMPLER2DCMP(shadowMap1), + float2 screenPos, + float2 vpos, float2 shadowPos, float filterRadius, float distToLight, float esmFactor, + float gradient, + float penumbra, int startTap, int endTap ) { float shadow = 0; float2 tap = 0; - for ( int t = startTap; t < endTap; t++ ) + + for ( int t = 0; t < NUM_TAPS; t++ ) { - tap.x = ( sNonUniformTaps[t].x * sinCos.y - sNonUniformTaps[t].y * sinCos.x ) * filterRadius; - tap.y = ( sNonUniformTaps[t].y * sinCos.y + sNonUniformTaps[t].x * sinCos.x ) * filterRadius; - float occluder = TORQUE_TEX2DLOD( shadowMap1, float4( shadowPos + tap, 0, 0 ) ).r; - - float esm = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); - shadow += esm / float( endTap - startTap ); + tap = VogelDisk(t, NUM_TAPS, gradient); + tap = shadowPos + tap * penumbra * filterRadius; + float occluder = TORQUE_TEX2DCMP( shadowMap1, tap, distToLight).r; + float esm = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + shadow += esm; } return shadow; } -float softShadow_filter( TORQUE_SAMPLER2D(shadowMap), +float softShadow_filter( +TORQUE_SAMPLER2D(shadowMap), +TORQUE_SAMPLER2DCMP(shadowMapCMP), + float2 screenPos, float2 vpos, float2 shadowPos, float filterRadius, @@ -111,46 +132,32 @@ float softShadow_filter( TORQUE_SAMPLER2D(shadowMap), // If softshadow is undefined then we skip any complex // filtering... just do a single sample ESM. - float occluder = TORQUE_TEX2DLOD(shadowMap, float4(shadowPos, 0, 0)).r; - float shadow = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + float occluder = TORQUE_TEX2DLOD( shadowMap, float4(shadowPos,0,0) ).r; + float shadow = occluder; #else - // Lookup the random rotation for this screen pixel. - float2 sinCos = ( TORQUE_TEX2DLOD(gTapRotationTex, float4(vpos * 16, 0, 0)).rg - 0.5) * 2; - - // Do the prediction taps first. - float shadow = softShadow_sampleTaps( TORQUE_SAMPLER2D_MAKEARG(shadowMap), - sinCos, - shadowPos, - filterRadius, - distToLight, - esmFactor, - 0, - NUM_PRE_TAPS ); - - // We live with only the pretap results if we don't - // have high quality shadow filtering enabled. - #ifdef SOFTSHADOW_HIGH_QUALITY - - // Only do the expensive filtering if we're really - // in a partially shadowed area. - if ( shadow * ( 1.0 - shadow ) * max( dotNL, 0 ) > 0.06 ) - { - shadow += softShadow_sampleTaps( TORQUE_SAMPLER2D_MAKEARG(shadowMap), - sinCos, - shadowPos, - filterRadius, - distToLight, - esmFactor, - NUM_PRE_TAPS, - NUM_TAPS ); - - // This averages the taps above with the results - // of the prediction samples. - shadow *= 0.5; - } - - #endif // SOFTSHADOW_HIGH_QUALITY + + float gradient = 6.28318530718 * GradientNoise(screenPos); + float penumbra = Penumbra(TORQUE_SAMPLER2D_MAKEARG(shadowMap), gradient, shadowPos, distToLight, filterRadius, esmFactor, NUM_TAPS); + if(penumbra < 1.0) + penumbra = 1.0; + + float shadow = softShadow_sampleTaps( TORQUE_SAMPLER2D_MAKEARG(shadowMapCMP), + screenPos, + vpos, + shadowPos, + filterRadius, + distToLight, + esmFactor, + gradient, + penumbra, + 0, + NUM_TAPS ); + + // This averages the taps above with the results + // of the prediction samples. + // if you change the number of taps, this value should be set to that. + shadow = 1.0 - shadow / float(NUM_TAPS); #endif // SOFTSHADOW diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl index a0459bfb2..167dffacd 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl @@ -153,9 +153,16 @@ float4 main( ConvexConnectP IN ) : SV_TARGET #endif //get Punctual light contribution - lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed); + //get spot angle attenuation - lighting *= getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams ); + float att = 1; + att *= getDistanceAtt(surfaceToLight.L, lightInvSqrRange); + att *= getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams, lightRange); + float3 lCol = lightColor.rgb *(lightBrightness / (4.0 * 3.14159265359)); + float3 radince = lCol * att; + float3 factor = saturate(surfaceToLight.NdotL) * shadowed * radince; + lighting = evaluateStandardBRDF(surface,surfaceToLight) * factor; + // } return float4(lighting, 0); diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl index 6046d6f00..9efff2ab9 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl @@ -30,11 +30,11 @@ TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0); TORQUE_UNIFORM_SAMPLER2D(shadowMap, 1); - //contains gTapRotationTex sampler #include "softShadow.hlsl" TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 3); TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 4); +TORQUE_UNIFORM_SAMPLER2DCMP(shadowMapCmp, 5); uniform float lightBrightness; uniform float3 lightDirection; @@ -65,6 +65,8 @@ uniform float4 offsetX; uniform float4 offsetY; float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap), + TORQUE_SAMPLER2DCMP(sourceShadowMapCMP), + float2 screenPos, float2 texCoord, float4x4 worldToLightProj, float3 worldPos, @@ -163,8 +165,16 @@ float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap), float farPlaneScale = dot( farPlaneScalePSSM, finalMask ); distToLight *= farPlaneScale; - return float4(debugColor, softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(sourceShadowMap), texCoord, shadowCoord, farPlaneScale * shadowSoftness, - distToLight, dotNL, dot( finalMask, overDarkPSSM ) ) ); + return float4(debugColor, softShadow_filter( + TORQUE_SAMPLER2D_MAKEARG(sourceShadowMap), + TORQUE_SAMPLER2D_MAKEARG(sourceShadowMapCMP), + screenPos, + texCoord, + shadowCoord, + farPlaneScale * shadowSoftness, + distToLight, + dotNL, + dot( finalMask, overDarkPSSM ) ) ); }; @@ -197,8 +207,19 @@ float4 main(FarFrustumQuadConnectP IN) : SV_TARGET float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * surface.depth); float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y; - float4 shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(shadowMap), IN.uv0.xy, worldToLightProj, surface.P, scaleX, scaleY, offsetX, offsetY, - farPlaneScalePSSM, surfaceToLight.NdotL); + float4 shadowed_colors = AL_VectorLightShadowCast( + TORQUE_SAMPLER2D_MAKEARG(shadowMap), + TORQUE_SAMPLER2D_MAKEARG(shadowMapCmp), + IN.hpos.xy, + IN.uv0.xy, + worldToLightProj, + surface.P, + scaleX, + scaleY, + offsetX, + offsetY, + farPlaneScalePSSM, + surfaceToLight.NdotL); float shadow = shadowed_colors.a;