#ifndef DForce32b typedef half fpart; typedef half2 fpart2; typedef half3 fpart3; typedef half4 fpart4; typedef half4x3 fpart4x3; #else typedef float fpart; typedef float2 fpart2; typedef float3 fpart3; typedef float4 fpart4; typedef float4x3 fpart4x3; #endif uniform const float4 GbxLightAmbient; uniform const float4 GbxLightDirRgb0; uniform const float4 GbxLightDirDir0; uniform const float4 GbxShadowSoftCorners1[4]; uniform const float4 GbxEyeInWorld; uniform const float4 GbxDayTime; uniform const float4 GbxWorldToWaterDepth; uniform const float4 GbxWaterDepthMax_yInv; uniform const float4x2 GbxSamplerBilinearCorners_ShadowBuffer; uniform const float4 GbxSampler_W_H_0x5_1_ShadowBuffer; //////// static inline float3 LightAD_Dir1(in float3 Normal, in float3 LightDirDir0) { // TAG "dot" compiler bug workaround (*1.00001) return min(GbxLightAmbient + GbxLightDirRgb0*max(0, dot(Normal*1.00001, -LightDirDir0)), 1); } //////// static inline fpart3 NormalFrom_4Heights( in sampler2D MapHeight, in float2 TcHeight, in float2 TexelSizeU, in float2 TexelSizeV) { fpart H_UPos = tex2D(MapHeight, TcHeight+TexelSizeU); fpart H_UNeg = tex2D(MapHeight, TcHeight-TexelSizeU); fpart H_VPos = tex2D(MapHeight, TcHeight+TexelSizeV); fpart H_VNeg = tex2D(MapHeight, TcHeight-TexelSizeV); return fpart3(H_UNeg-H_UPos, H_VNeg-H_VPos, 1); } //////// static inline fpart3 NormalFrom_3Heights( in sampler2D MapHeight, in float2 TcHeight, in float2 TexelSizeU, in float2 TexelSizeV) { fpart H_Cent = tex2D(MapHeight, TcHeight); fpart H_UPos = tex2D(MapHeight, TcHeight+TexelSizeU); fpart H_VPos = tex2D(MapHeight, TcHeight+TexelSizeV); return fpart3(H_Cent-H_UPos, H_Cent-H_VPos, 1); } //////// static inline fpart3 NormalFrom_3ScaledHeights( in sampler2D MapHeight, in float2 TcHeight, in float2 TexelSizeU, in float2 TexelSizeV, in fpart Scale) { fpart H_Cent = tex2D(MapHeight, TcHeight); fpart H_UPos = tex2D(MapHeight, TcHeight+TexelSizeU); fpart H_VPos = tex2D(MapHeight, TcHeight+TexelSizeV); return fpart3(Scale*(H_Cent-H_UPos), Scale*(H_Cent-H_VPos), 1); } ////////// static inline float4 Tc2Dproj_FromVec3Z(in float3 Vector) // Prepare a tex2Dproj lookup equivalent with a texCUBE lookup (on ZPos face only) // project & convert from [-1,1] to [0,1] { return Vector.z+Vector.xyzz; // EnvMap must be Y inverted // = ( Vector.z+Vector.x, Vector.z+Vector.y, 2*Vector.z, 2*Vector.z) // after projection = (0.5+0.5*Vector.x/Vector.z, 0.5+0.5*Vector.y/Vector.z) } //////////// static inline float3 Reflec_NotNormalized(in float3 EyeVector, in float3 Normal) // Works with unNormalized Eye & Normal, since // Reflec_NotNormalized(a*Eye, b*Normal) = a*b*b*Reflec_NotNormalized(Eye, Normal) // (obviously, the vector returned is not normalized) { return 2*dot(Normal,EyeVector)*Normal - dot(Normal,Normal)*EyeVector; } static inline half3 Reflec_NotNormalized(in half3 EyeVector, in half3 Normal) // Works with unNormalized Eye & Normal, since // Reflec_NotNormalized(a*Eye, b*Normal) = a*b*b*Reflec_NotNormalized(Eye, Normal) // (obviously, the vector returned is not normalized) { return 2*dot(Normal,EyeVector)*Normal - dot(Normal,Normal)*EyeVector; } /////////// static inline void NormalSetZpos_FromXY(in out float3 Normal) // Compute z = sqrt(1-x^2-y^2) // usefull for NxNy->NxNyNz MapBump unpacking { Normal.z = sqrt(1-Normal.x*Normal.x-Normal.y*Normal.y); } // TAG TO REMOVE #ifndef DGbxGenLoadPC3_PS_Shadow #define DGbxGenLoadPC3_PS_Shadow #endif #ifndef DGbxGenCodePC3_PS_Shadow #define DGbxGenCodePC3_PS_Shadow fpart ShadowDiffus = 1; fpart ShadowSpecular = 1; #endif // TAG END #ifndef DGbxPSetDeclPC3_Shadow_Count3 #define DGbxPSetDeclPC3_Shadow_Count3 static fpart ShadowDiffs[3] = {1,1,1}; static fpart ShadowSpecs[3] = {1,1,1}; #endif #ifndef DGbxPGenLoadPC3_Shadow #define DGbxPGenLoadPC3_Shadow #endif #ifndef DGbxPGenCodePC3_Shadow #define DGbxPGenCodePC3_Shadow fpart ShadowDiffus = 1; fpart ShadowSpecular = 1; #endif #ifndef DGbxShadowSoftPC3_DichotomyCount #define DGbxShadowSoftPC3_DichotomyCount 1 #endif #ifndef DGbxPGenLoadPC3_Projector #define DGbxPGenLoadPC3_Projector #endif #ifndef DGbxPGenCodePC3_Projector #define DGbxPGenCodePC3_Projector fpart ProjectorMask = 0; fpart ProjectorAmbient = 0; fpart ProjectorDiffus = 0; fpart ProjectorSpecular = 0; #endif #ifndef DGbxPGenLoadPC3_Projector_TcInPS #define DGbxPGenLoadPC3_Projector_TcInPS #endif #ifndef DGbxPGenCodePC3_Projector_TcInPS #define DGbxPGenCodePC3_Projector_TcInPS fpart ProjectorMask = 0; fpart ProjectorAmbient = 0; fpart ProjectorDiffus = 0; fpart ProjectorSpecular = 0; #endif #ifndef DGbxPGenLoadPC3_Projector_NoDot #define DGbxPGenLoadPC3_Projector_NoDot #endif #ifndef DGbxPGenCodePC3_Projector_NoDot #define DGbxPGenCodePC3_Projector_NoDot fpart ProjectorMask = 0; fpart ProjectorAmbient = 0; fpart ProjectorDiffus = 0; fpart ProjectorSpecular = 0; #endif #ifndef DGbxPGenInputPC3_MrtEffects #define DGbxPGenInputPC3_MrtEffects #endif #ifndef DGbxPGenOutputPC3_MrtEffects #define DGbxPGenOutputPC3_MrtEffects #endif #ifndef DGbxPGenLoadPC3_MrtEffects #define DGbxPGenLoadPC3_MrtEffects #endif #ifndef DGbxPGenCodePC3_MrtEffects #define DGbxPGenCodePC3_MrtEffects #endif #ifndef DGbxPMrtDepthBlurPC3_TapCount #define DGbxPMrtDepthBlurPC3_TapCount 12 #endif #ifndef DGbxPGlobalSet_ExtraTexCoordStartAt0 #define DGbxPGlobalSet_ExtraTexCoordStartAt0 #endif #ifndef DGbxPGlobalSet_ExtraTexCoordStartAt1 #define DGbxPGlobalSet_ExtraTexCoordStartAt1 #endif #ifndef DGbxPGlobalSet_ExtraTexCoordStartAt2 #define DGbxPGlobalSet_ExtraTexCoordStartAt2 #endif #ifndef DGbxPGlobalSet_ExtraTexCoordStartAt3 #define DGbxPGlobalSet_ExtraTexCoordStartAt3 #endif #ifndef DGbxPGlobalSet_ExtraTexCoordStartAt4 #define DGbxPGlobalSet_ExtraTexCoordStartAt4 #endif #ifndef DGbxPGlobalSet_ExtraTexCoordStartAt5 #define DGbxPGlobalSet_ExtraTexCoordStartAt5 #endif #ifndef DGbxPGlobalSet_ExtraTexCoordStartAt6 #define DGbxPGlobalSet_ExtraTexCoordStartAt6 #endif #ifndef DGbxPGlobalSet_ExtraTexCoordStartAt7 #define DGbxPGlobalSet_ExtraTexCoordStartAt7 #endif // // GbxSamplerGetBilinearCorners = (-0.5/W, +0.5/W, -0.5/H, +0.5/H) // static inline fpart BilinearDepthCmp(sampler2D MapShadowBuffer, float4 tc, float4x2 BilinearCorners, float4 W_H_0x5_1) { /* tc.x /= tc.w; // TAG TODO : Handle projective depth shadow with a #define here, and check projective depth-bias... tc.y /= tc.w;*/ float2 tlbl; float2 trbr; // Store Corners like .xywz to use .xy & .wz (ps_2_0) swizzles tlbl.x = (tex2D(MapShadowBuffer, tc+BilinearCorners._11_21).r - tc.z) > 0; trbr.x = (tex2D(MapShadowBuffer, tc+BilinearCorners._41_31).r - tc.z) > 0; tlbl.y = (tex2D(MapShadowBuffer, tc+BilinearCorners._12_22).r - tc.z) > 0; trbr.y = (tex2D(MapShadowBuffer, tc+BilinearCorners._42_32).r - tc.z) > 0; // enable "mad" by using same cX register (ps_2_0 can use only 1 cX register /instr) float2 weights = frac(W_H_0x5_1.z + tc.xy*W_H_0x5_1); float2 tb; tb = lerp(tlbl, trbr, weights.xx); return lerp(tb.x, tb.y, weights.y); } static inline fpart SoftShadow(in sampler2D MapShadowBuffer, in float4 TcShadowBuffer, in float4x2 BilinearCorners, in float4 W_H_0x5_1) { #ifdef DShadow_NeedCmp float ReceiverToOccluder = tex2Dproj(MapShadowBuffer, TcShadowBuffer).x-TcShadowBuffer.z; float ShadeInLight = ReceiverToOccluder>0; #else float ShadeInLight = tex2Dproj(MapShadowBuffer, TcShadowBuffer); #endif if (DGbxShadowSoftPC3_DichotomyCount==0) { #if defined(DShadow_NeedCmp) && defined(DGbxPDefinedPC3_Shadow_Bilinear) if (DGbxPDefinedPC3_Shadow_Bilinear>0) { ShadeInLight = BilinearDepthCmp(MapShadowBuffer, TcShadowBuffer, BilinearCorners, W_H_0x5_1); } #endif return ShadeInLight; } bool InLight = ShadeInLight; if (InLight) { return 1; } else { // Here ReceiverToOccluder<0 // SoftSize scale by ReceiverToOccluder does not work well (the dist. is always the min. Z, others Z are lost...) // float MaxTcDelta = TcShadowBuffer.w*-ReceiverToOccluder; float MaxTcDelta = TcShadowBuffer.w; float4 TcCorners[4] = GbxShadowSoftCorners1; float4 TcDeltaLens = 0.5*MaxTcDelta; float4 StepDelta = 0.5*MaxTcDelta; float4 InLights; const int cDico = DGbxShadowSoftPC3_DichotomyCount; for (int i=0; i in cXX // TcDeltaLens depend. of ReceiverToOccluder => in rXX // => the following can use "mad" float4 TcSamples[4] = { TcShadowBuffer+TcCorners[0]*TcDeltaLens.x, TcShadowBuffer+TcCorners[1]*TcDeltaLens.y, TcShadowBuffer+TcCorners[2]*TcDeltaLens.z, TcShadowBuffer+TcCorners[3]*TcDeltaLens.w, }; #ifdef DShadow_NeedCmp InLights.x = tex2Dproj(MapShadowBuffer, TcSamples[0]).x>TcShadowBuffer.z; InLights.y = tex2Dproj(MapShadowBuffer, TcSamples[1]).x>TcShadowBuffer.z; InLights.z = tex2Dproj(MapShadowBuffer, TcSamples[2]).x>TcShadowBuffer.z; InLights.w = tex2Dproj(MapShadowBuffer, TcSamples[3]).x>TcShadowBuffer.z; #else InLights.x = tex2Dproj(MapShadowBuffer, TcSamples[0]); InLights.y = tex2Dproj(MapShadowBuffer, TcSamples[1]); InLights.z = tex2Dproj(MapShadowBuffer, TcSamples[2]); InLights.w = tex2Dproj(MapShadowBuffer, TcSamples[3]); #endif StepDelta *= 0.5; TcDeltaLens += InLights ? -StepDelta : +StepDelta; } float4 DistToEdges = TcDeltaLens; float DistToEdge = min(DistToEdges.x, min(DistToEdges.y, min(DistToEdges.z, DistToEdges.w))); // float DistToEdge = DistToEdges.w; fpart DistToEdge01 = saturate(1-(DistToEdge)/(MaxTcDelta-StepDelta)); return DistToEdge01; } } static inline void GetEyeWaterLen_QuotientInV(out float _EyeWaterLen_ToDiv, out float _EyeWaterLen_Div, in float4 _PosInW) { float Depth = max(0,mul(_PosInW,GbxWorldToWaterDepth)); float3 EyeToPos = _PosInW-GbxEyeInWorld; float EyeToPosLength = length(EyeToPos); float EyeToPosDepth = mul(EyeToPos,GbxWorldToWaterDepth); _EyeWaterLen_ToDiv = EyeToPosLength*Depth; _EyeWaterLen_Div = EyeToPosDepth; } fpart3 ParallaxSphere_GetTexCoord(in float3 _PosIn01, in fpart3 _DirInCube, in fpart4 _Rotate, in fpart _SphereScale) { fpart3 PosIn01Frac = frac(_PosIn01); // Grid scale to get relative center fpart3 PosInCube = PosIn01Frac*2-1; // Sphere scale PosInCube = PosInCube*_SphereScale; fpart3 Inter; fpart InterF; fpart PosDotDir = dot(PosInCube, _DirInCube); fpart PosDotPos = dot(PosInCube, PosInCube); InterF = sqrt(PosDotDir*PosDotDir + 1-PosDotPos) - PosDotDir; Inter = PosInCube + InterF*_DirInCube; fpart3 TcRefrac; TcRefrac.x = dot(Inter.zx, _Rotate.xy); TcRefrac.y = Inter.y; TcRefrac.z = dot(Inter.zx, _Rotate.wz); return TcRefrac; }