home *** CD-ROM | disk | FTP | other *** search
- #ifndef QSSHADER_QSShadow_H
- #define QSSHADER_QSShadow_H
- #include "FunctionLib.h"
- #include "DepthUtil.h"
- #include "QSScreenSpaceDepth.h"
-
- //cascaded shadow map
- #if CSM_4
- #define CSM_INUSE_NUM 4
- #else
- #define CSM_INUSE_NUM 3
- #endif
-
- float4x4 ViewToLightSpace0;
- float4x4 ViewToLightSpace1;
- float4x4 ViewToLightSpace2;
- float4x4 ViewToLightSpace3;
- float4x4 ViewToLightSpace4;
-
- float4 CascadedInfo; //for pcf solution ----x:ShadowMapWidth, y:param/ShadowMapWidth, z:cascade 0 far, w:cascade 1 far
- //for evsm solution yzw cascaded 0,1,2 far
- float4 VestureSmBias; //x for bias on vesture shadow depth sampling(0.0f when no smooth transition, 1.0f when smooth transition)
- //y notify if the unify rt is for 4 or 5 rt merging
- //z vesture lerp ratio
- float2 Jittering; // already done some calculation, refer CPP code.
-
- /*
- * screen space shadow map
- */
-
- sampler2D SSSMSampler;
-
- float SampleScreenSpaceShadow(float2 uv)
- {
- return tex2D(SSSMSampler, uv).x;
- }
-
- /*
- * local light shadow
- */
- float4 ShadowMapIdxMask;
- sampler2D LocalLightShadowSampler;
- float2 SampleLocalLightShadow(float2 uv)
- {
- return dot(tex2D(LocalLightShadowSampler, uv), ShadowMapIdxMask).xx;
- }
- sampler2D sLightDepth;
- sampler2D sDynamicObjLightDepth;
- sampler2D sNoise;
- float4x4 cScreenToLight;
- float4 cNoiseSB;
-
- #define NUM_OFFSETS 4
- float4 offsets[NUM_OFFSETS];
-
- static const float2 offsets8[8] = {
- float2( -0.16076615, -0.16076620 ),
- float2( -0.52473867, -0.14628546 ),
- float2( -0.80486661, 0.51980901 ),
- float2( -0.14628546, 0.52473867 ),
- float2( 0.91154134, -0.17331968 ),
- float2( 0.44585308, -0.44585305 ),
- float2( 0.51980895, 0.80486661 ),
- float2( 0.17331968, -0.91154134 )
- };
- float FetchShadow(float4 uv)
- {
- return tex2Dproj(sLightDepth, uv).x;
- }
- float FetchShadow(float2 uv, float2 zw)
- {
- float4 lpos = { float3(uv, zw.x) * zw.y, zw.y };
- return tex2Dproj(sLightDepth, lpos).x;
- }
- float FilterShadow(float4 light_pos, float2 scrPos)
- {
- const int c_shadow_res = 1024;
- float2 evenOdd = (scrPos % 2) - 0.5;
-
- float c = FetchShadow(light_pos);
- /*for (int i = 0; i < 8; i++)
- {
- c += FetchShadow(light_pos + 2.5 * float4(offsets8[i] * evenOdd, 0, 0) / c_shadow_res);
- }
- c /= 8;*/
- return c;
- }
-
- float FilterShadow(float4 light_pos, float4 rotation)
- {
- light_pos.xyz /= light_pos.w;
-
- float c = 0;
-
- float2 uv = light_pos.xy;
-
- HLSL_ISOLATE
- {
- float4 uvs0, uvs1;
- uvs0 = rotation.xyxy * offsets[0] + uv.xyxy;
- uvs0 += rotation.zwzw * offsets[0];
-
- uvs1 = rotation.xyxy * offsets[1] + uv.xyxy;
- uvs1 += rotation.zwzw * offsets[1];
-
- float4 depths;
- depths.x = FetchShadow(uvs0.xy, light_pos.zw).x;
- depths.y = FetchShadow(uvs0.zw, light_pos.zw).x;
- depths.z = FetchShadow(uvs1.xy, light_pos.zw).x;
- depths.w = FetchShadow(uvs1.zw, light_pos.zw).x;
-
- c += dot(depths, 0.125);
- }
-
- HLSL_ISOLATE
- {
- float4 uvs0, uvs1;
- uvs0 = rotation.xyxy * offsets[2] + uv.xyxy;
- uvs0 += rotation.zwzw * offsets[2];
-
- uvs1 = rotation.xyxy * offsets[3] + uv.xyxy;
- uvs1 += rotation.zwzw * offsets[3];
-
- float4 depths;
- depths.x = FetchShadow(uvs0.xy, light_pos.zw).x;
- depths.y = FetchShadow(uvs0.zw, light_pos.zw).x;
- depths.z = FetchShadow(uvs1.xy, light_pos.zw).x;
- depths.w = FetchShadow(uvs1.zw, light_pos.zw).x;
-
-
- c += dot(depths, 0.125);
- }
-
- return c;
- }
-
- float SampleShadow(float2 sc_xy, float scene_z, float2 scrPos)
- {
- float4 screen_pos = float4(sc_xy, scene_z, 1);
-
- float4 light_pos = mul(screen_pos, cScreenToLight);
-
- return FilterShadow(light_pos, scrPos) /** cShadowFade.x + cShadowFade.y*/;
- }
-
- float SampleShadowBlur(float4 screen_pos, float4 rotation)
- {
- float4 light_pos = mul(screen_pos, cScreenToLight);
- return FilterShadow(light_pos, rotation)/* * cShadowFade.x + cShadowFade.y*/;
- }
-
- sampler2D LightViewDepthLinear;
- sampler2D LightViewDepthPoint;
-
- #if ENHANCED_BLUR
-
- #define PCF_NUM 12
- static const float2 crossPcf[PCF_NUM] =
- {
- float2( -1.0f, -1.0f) * 1,
- float2( 1.0f, -1.0f) * 1,
- float2( 1.0f, 1.0f) * 1,
- float2( -1.0f, 1.0f) * 1,
- float2( -1.0f, -1.0f) * 4,
- float2( 1.0f, -1.0f) * 4,
- float2( 1.0f, 1.0f) * 4,
- float2( -1.0f, 1.0f) * 4,
- float2( -1.0f, -1.0f) * 6,
- float2( 1.0f, -1.0f) * 6,
- float2( 1.0f, 1.0f) * 6,
- float2( -1.0f, 1.0f) * 6,
- };
-
- #else
-
- #define PCF_NUM 4
- static const float2 crossPcf[PCF_NUM] =
- {
- float2( -1.0f, -1.0f),
- float2( 1.0f, -1.0f),
- float2( 1.0f, 1.0f),
- float2( -1.0f, 1.0f),
- };
-
- #endif //ENHANCED_BLUR
-
- float FilterShadow(sampler2D shadowMap, float2 uv, float halfInvSmRes, float bias, float viewZ)
- {
- float shadowValue = 0.0f;
-
- for(int i=0; i<PCF_NUM; i++)
- {
- float2 pcfUV = uv + halfInvSmRes*crossPcf[i].xy;
- {
- float4 uvt = float4(pcfUV,viewZ-bias, 1.0f);
- shadowValue+=tex2Dproj(shadowMap, uvt).r;
- }
- }
-
- return shadowValue/PCF_NUM;
- }
-
- float RegularHwPcf(sampler2D shadowMap, float2 uv, float halfInvSmRes, float bias, float viewZ,float2 bound, float scale)
- {
- float shadowValue = 0.0f;
- float2 halfInvRes = float2(halfInvSmRes*scale, halfInvSmRes);
- uv += halfInvRes;
-
- for(int i=0; i<PCF_NUM; i++)
- {
- float2 pcfUV = uv + halfInvRes*crossPcf[i].xy;
- if(pcfUV.x<bound.x||pcfUV.x>=bound.y||pcfUV.y<0.0f||pcfUV.y>1.0f)
- {
- shadowValue+=1.0f;
- }
- else
- {
- float4 uvt = float4(pcfUV,viewZ-bias, 1.0f);
- shadowValue+=tex2Dproj(shadowMap, uvt).r;
- }
- }
-
- return shadowValue/PCF_NUM;
- }
-
- float SingleHwPcf(sampler2D shadowMap, float2 uv, float halfInvSmRes, float bias, float viewZ,float2 bound, float scale)
- {
- float shadowValue = 0.0f;
- float2 halfInvRes = float2(halfInvSmRes*scale, halfInvSmRes);
- uv += halfInvRes;
-
- {
- float2 pcfUV = uv;
- if(pcfUV.x<bound.x||pcfUV.x>=bound.y||pcfUV.y<0.0f||pcfUV.y>1.0f)
- {
- shadowValue+=1.0f;
- }
- else
- {
- float4 uvt = float4(pcfUV,viewZ-bias, 1.0f);
- shadowValue+=tex2Dproj(shadowMap, uvt).r;
- }
- }
-
- return shadowValue;
- }
-
- float3 ScreenPosToLightViewPos(float4 screenPos, float4x4 viewToLightView)
- {
- float viewSpaceZ = CalcViewZFromDeviceZ(screenPos.z);
- float viewSpaceX = (screenPos.x-0.5f)*viewSpaceZ*ProjParam.x;
- float viewSpaceY = (0.5f-screenPos.y)*viewSpaceZ*ProjParam.y;
- float4 viewPos = float4(viewSpaceX, viewSpaceZ, viewSpaceY, 1.0f);
-
- float4 homoPosLightView = mul(viewPos, viewToLightView);
- homoPosLightView.xyz /= homoPosLightView.w;
- homoPosLightView.xy = homoPosLightView.xy*0.5f+0.5f;
- homoPosLightView.y = 1-homoPosLightView.y;
-
- return homoPosLightView.xyz;
- }
-
- float SampleShadow(float3 lightViewPos, float halfInvSmRes, float bias, float xBias, float scale)
- {
- float result;
-
- result = RegularHwPcf(LightViewDepthLinear, lightViewPos.xy, halfInvSmRes, bias, lightViewPos.z,float2(xBias, xBias+scale), scale);
-
- //the 4th shadow pass needs darken
- #if CSM_INUSE_NUM>3
- if(xBias>=scale*(CSM_INUSE_NUM-1))
- {
- result *= result;
- }
- #endif
- return result;
- }
-
- bool LightViewCoordValid(float2 v)
- {
- return v.x>=0.0f && v.x<=1.0f && v.y>=0.0f && v.y<=1.0f;
- }
-
- void CalcCascadeUv(float4 screenPos, float3 distBound, float scale, float vestureBias, inout float3 lightViewPos0, inout float3 lightViewPos1, out float xBias, inout float xbias2, inout float lerpRatio)
- {
- //light view pos calc
- float3 lightViewPosSrc[CSM_INUSE_NUM];
-
- lightViewPosSrc[0] = ScreenPosToLightViewPos(screenPos, ViewToLightSpace0);
- lightViewPosSrc[1] = ScreenPosToLightViewPos(screenPos, ViewToLightSpace1);
- lightViewPosSrc[2] = ScreenPosToLightViewPos(screenPos, ViewToLightSpace2);
- #if CSM_INUSE_NUM>3
- lightViewPosSrc[3] = ScreenPosToLightViewPos(screenPos, ViewToLightSpace3);
- #endif//CSM_INUSE_NUM>3
-
- float scaleSrc[4] = {1.0f,2.0f,0.0f,3.0f+vestureBias};
- float lerpThreshold = 0.09f;
- float epsilon = 0.002f;
- float invEplison = 1.0f-epsilon;
-
- for(int idx=0; idx<CSM_INUSE_NUM; idx++)
- {
- float minDelta = lightViewPosSrc[idx].x-epsilon;
- minDelta = min(minDelta, invEplison-lightViewPosSrc[idx].x);
- minDelta = min(minDelta, lightViewPosSrc[idx].y-epsilon);
- minDelta = min(minDelta, invEplison-lightViewPosSrc[idx].y);
-
- if(minDelta>0.0f)
- {
- xBias = scaleSrc[idx]*scale;
-
- lightViewPos0.yz = lightViewPosSrc[idx].yz;
- lightViewPos0.x = xBias+lightViewPosSrc[idx].x*scale;
-
- #if CASCADE_LERP
- if(minDelta<lerpThreshold)
- {
- lerpRatio = minDelta/lerpThreshold;
-
- if(idx<CSM_INUSE_NUM-1)
- {
- int dstIdx = LightViewCoordValid(lightViewPosSrc[idx+1].xy) ? idx+1 : idx+2;
- dstIdx = min(dstIdx, CSM_INUSE_NUM-1);
- xbias2 = scaleSrc[dstIdx]*scale;
- lightViewPos1.yz = lightViewPosSrc[dstIdx].yz;
- lightViewPos1.x = xbias2+lightViewPosSrc[dstIdx].x*scale;
- }
- //give an invalid value, so that we'll have 1.0f shadow
- else
- {
- xbias2 = 2.0f;
- }
- }
- #endif//CASCADE_LERP
-
- return;
- }
- }
- }
-
- float CascadedShadowMap(float4 screenPos, out float xBias, out float2 smUv)
- {
- //const
- float unifySmRtNum = VestureSmBias.y+CSM_INUSE_NUM;
- float scale = 1.0f/unifySmRtNum;
-
- float bias = 0;
-
- float halfInvSmRes = CascadedInfo.x;
- float3 distBound = CascadedInfo.yzw;
- float vestureBias = VestureSmBias.x;
-
- float3 lightViewPos = float3(0.0f,0.0f,0.0f);
- float xbias2=0.0f, lerpRatio=1.0f;
- float3 lightViewPos2 = float3(0.0f,0.0f,0.0f);
-
- CalcCascadeUv(screenPos, distBound, scale, vestureBias, lightViewPos, lightViewPos2, xBias, xbias2, lerpRatio);
-
- smUv = lightViewPos.xy;
-
- float result = SampleShadow(lightViewPos, halfInvSmRes, bias, xBias, scale);
-
- #if VESTURE_LERP
- if(xBias>=scale*(CSM_INUSE_NUM-1))
- {
- float3 dstLightViewPos = ScreenPosToLightViewPos(screenPos, ViewToLightSpace4);
-
- float dstXBias = xBias;
- dstXBias += VestureSmBias.x>0.0f ? -scale : scale;
- dstLightViewPos.x = dstXBias+dstLightViewPos.x*scale;
- float dstResult = SampleShadow(dstLightViewPos, halfInvSmRes, bias, dstXBias, scale);
- result = lerp(result, dstResult, VestureSmBias.z);
- }
- #endif
-
- #if CASCADE_LERP
- if(lerpRatio<1.0f)
- {
- float lerpDst;
-
- if(xbias2<=1.0f)
- {
- lerpDst = SampleShadow(lightViewPos2, halfInvSmRes, bias, xbias2, scale);
- }
- else
- {
- lerpDst = 1.0f;
- }
-
- result = lerp(lerpDst, result, lerpRatio);
- }
- #endif//CASCADE_LERP
-
- return result;
- }
-
- #endif//QSSHADER_QSShadow_H