DepthShadowmap.hlsl
上传用户:xhbjoy
上传日期:2014-10-07
资源大小:38068k
文件大小:9k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /* This file implements standard programs for depth shadow mapping. 
  2.    These particular ones are suitable for additive lighting models, and
  3.    include 3 techniques to reduce depth fighting on self-shadowed surfaces,
  4.    constant bias, gradient (slope-scale) bias, and a fuzzy shadow map comparison*/
  5. // Shadow caster vertex program.
  6. void casterVP(
  7. float4 position : POSITION,
  8. out float4 outPos : POSITION,
  9. out float2 outDepth : TEXCOORD0,
  10. uniform float4x4 worldViewProj,
  11. uniform float4 texelOffsets,
  12. uniform float4 depthRange
  13. )
  14. {
  15. outPos = mul(worldViewProj, position);
  16. // fix pixel / texel alignment
  17. outPos.xy += texelOffsets.zw * outPos.w;
  18. // linear depth storage
  19. // offset / scale range output
  20. #if LINEAR_RANGE
  21. outDepth.x = (outPos.z - depthRange.x) * depthRange.w;
  22. #else
  23. outDepth.x = outPos.z;
  24. #endif
  25. outDepth.y = outPos.w;
  26. }
  27. // Shadow caster fragment program for high-precision single-channel textures
  28. void casterFP(
  29. float2 depth : TEXCOORD0,
  30. out float4 result : COLOR)
  31. {
  32. #if LINEAR_RANGE
  33. float finalDepth = depth.x;
  34. #else
  35. float finalDepth = depth.x / depth.y;
  36. #endif
  37. // just smear across all components 
  38. // therefore this one needs high individual channel precision
  39. result = float4(finalDepth, finalDepth, finalDepth, 1);
  40. }
  41. void receiverVP(
  42. float4 position : POSITION,
  43. float4 normal : NORMAL,
  44. out float4 outPos : POSITION,
  45. out float4 outColour : COLOR,
  46. out float4 outShadowUV : TEXCOORD0,
  47. uniform float4x4 world,
  48. uniform float4x4 worldIT,
  49. uniform float4x4 worldViewProj,
  50. uniform float4x4 texViewProj,
  51. uniform float4 lightPosition,
  52. uniform float4 lightColour,
  53. uniform float4 shadowDepthRange
  54. )
  55. {
  56. float4 worldPos = mul(world, position);
  57. outPos = mul(worldViewProj, position);
  58. float3 worldNorm = mul(worldIT, normal).xyz;
  59. // calculate lighting (simple vertex lighting)
  60. float3 lightDir = normalize(
  61. lightPosition.xyz -  (worldPos.xyz * lightPosition.w));
  62. outColour = lightColour * max(dot(lightDir, worldNorm), 0.0);
  63. // calculate shadow map coords
  64. outShadowUV = mul(texViewProj, worldPos);
  65. #if LINEAR_RANGE
  66. // adjust by fixed depth bias, rescale into range
  67. outShadowUV.z = (outShadowUV.z - shadowDepthRange.x) * shadowDepthRange.w;
  68. #endif
  69. }
  70. void receiverFP(
  71. float4 position : POSITION,
  72. float4 shadowUV : TEXCOORD0,
  73. float4 vertexColour : COLOR,
  74. uniform sampler2D shadowMap : register(s0),
  75. uniform float inverseShadowmapSize,
  76. uniform float fixedDepthBias,
  77. uniform float gradientClamp,
  78. uniform float gradientScaleBias,
  79. uniform float shadowFuzzyWidth,
  80. out float4 result : COLOR)
  81. {
  82. // point on shadowmap
  83. #if LINEAR_RANGE
  84. shadowUV.xy = shadowUV.xy / shadowUV.w;
  85. #else
  86. shadowUV = shadowUV / shadowUV.w;
  87. #endif
  88. float centerdepth = tex2D(shadowMap, shadowUV.xy).x;
  89.     
  90.     // gradient calculation
  91.    float pixeloffset = inverseShadowmapSize;
  92.     float4 depths = float4(
  93.      tex2D(shadowMap, shadowUV.xy + float2(-pixeloffset, 0)).x,
  94.      tex2D(shadowMap, shadowUV.xy + float2(+pixeloffset, 0)).x,
  95.      tex2D(shadowMap, shadowUV.xy + float2(0, -pixeloffset)).x,
  96.      tex2D(shadowMap, shadowUV.xy + float2(0, +pixeloffset)).x);
  97. float2 differences = abs( depths.yw - depths.xz );
  98. float gradient = min(gradientClamp, max(differences.x, differences.y));
  99. float gradientFactor = gradient * gradientScaleBias;
  100. // visibility function
  101. float depthAdjust = gradientFactor + (fixedDepthBias * centerdepth);
  102. float finalCenterDepth = centerdepth + depthAdjust;
  103. // shadowUV.z contains lightspace position of current object
  104. #if FUZZY_TEST
  105. // fuzzy test - introduces some ghosting in result and doesn't appear to be needed?
  106. //float visibility = saturate(1 + delta_z / (gradient * shadowFuzzyWidth));
  107. float visibility = saturate(1 + (finalCenterDepth - shadowUV.z) * shadowFuzzyWidth * shadowUV.w);
  108. result = vertexColour * visibility;
  109. #else
  110. // hard test
  111. #if PCF
  112. // use depths from prev, calculate diff
  113. depths += depthAdjust.xxxx;
  114. float final = (finalCenterDepth > shadowUV.z) ? 1.0f : 0.0f;
  115. final += (depths.x > shadowUV.z) ? 1.0f : 0.0f;
  116. final += (depths.y > shadowUV.z) ? 1.0f : 0.0f;
  117. final += (depths.z > shadowUV.z) ? 1.0f : 0.0f;
  118. final += (depths.w > shadowUV.z) ? 1.0f : 0.0f;
  119. final *= 0.2f;
  120. result = float4(vertexColour.xyz * final, 1);
  121. #else
  122. result = (finalCenterDepth > shadowUV.z) ? vertexColour : float4(0,0,0,1);
  123. #endif
  124. #endif
  125.    
  126. }
  127. // Expand a range-compressed vector
  128. float3 expand(float3 v)
  129. {
  130. return (v - 0.5) * 2;
  131. }
  132. /* Normal mapping plus depth shadowmapping receiver programs
  133. */
  134. void normalMapShadowReceiverVp(float4 position : POSITION,
  135.  float3 normal : NORMAL,
  136.  float2 uv : TEXCOORD0,
  137.  float3 tangent     : TANGENT0,
  138.  
  139.  // outputs
  140.  out float4 outPos      : POSITION,
  141.  out float4 outShadowUV  : TEXCOORD0,
  142.  out float2 oUv    : TEXCOORD1,
  143.  out float3 oTSLightDir  : TEXCOORD2,
  144.  // parameters
  145.  uniform float4 lightPosition, // object space
  146.  uniform float4x4 world,
  147.  uniform float4x4 worldViewProj,
  148.  uniform float4x4 texViewProj)
  149. {
  150. float4 worldPos = mul(world, position);
  151. outPos = mul(worldViewProj, position);
  152. // calculate shadow map coords
  153. outShadowUV = mul(texViewProj, worldPos);
  154. #if LINEAR_RANGE
  155. // adjust by fixed depth bias, rescale into range
  156. outShadowUV.z = (outShadowUV.z - shadowDepthRange.x) * shadowDepthRange.w;
  157. #endif
  158. // pass the main uvs straight through unchanged
  159. oUv = uv;
  160. // calculate tangent space light vector
  161. // Get object space light direction
  162. // Non-normalised since we'll do that in the fragment program anyway
  163. float3 lightDir = lightPosition.xyz -  (position * lightPosition.w);
  164. // Calculate the binormal (NB we assume both normal and tangent are
  165. // already normalised)
  166. // NB looks like nvidia cross params are BACKWARDS to what you'd expect
  167. // this equates to NxT, not TxN
  168. float3 binormal = cross(tangent, normal);
  169. // Form a rotation matrix out of the vectors
  170. float3x3 rotation = float3x3(tangent, binormal, normal);
  171. // Transform the light vector according to this matrix
  172. oTSLightDir = mul(rotation, lightDir);
  173. }
  174. void normalMapShadowReceiverFp(
  175.   float4 shadowUV : TEXCOORD0,
  176.   float2 uv : TEXCOORD1,
  177.   float3 TSlightDir : TEXCOORD2,
  178.   out float4 result : COLOR,
  179.   uniform float4 lightColour,
  180.   uniform float inverseShadowmapSize,
  181.   uniform float fixedDepthBias,
  182.   uniform float gradientClamp,
  183.   uniform float gradientScaleBias,
  184.   uniform float shadowFuzzyWidth,
  185.   
  186.   uniform sampler2D   shadowMap : register(s0),
  187.   uniform sampler2D   normalMap : register(s1),
  188.   uniform samplerCUBE normalCubeMap : register(s2))
  189. {
  190. // retrieve normalised light vector, expand from range-compressed
  191. float3 lightVec = expand(texCUBE(normalCubeMap, TSlightDir).xyz);
  192. // get bump map vector, again expand from range-compressed
  193. float3 bumpVec = expand(tex2D(normalMap, uv).xyz);
  194. // Calculate dot product
  195. float4 vertexColour = lightColour * dot(bumpVec, lightVec);
  196. // point on shadowmap
  197. #if LINEAR_RANGE
  198. shadowUV.xy = shadowUV.xy / shadowUV.w;
  199. #else
  200. shadowUV = shadowUV / shadowUV.w;
  201. #endif
  202. float centerdepth = tex2D(shadowMap, shadowUV.xy).x;
  203.     
  204.     // gradient calculation
  205.    float pixeloffset = inverseShadowmapSize;
  206.     float4 depths = float4(
  207.      tex2D(shadowMap, shadowUV.xy + float2(-pixeloffset, 0)).x,
  208.      tex2D(shadowMap, shadowUV.xy + float2(+pixeloffset, 0)).x,
  209.      tex2D(shadowMap, shadowUV.xy + float2(0, -pixeloffset)).x,
  210.      tex2D(shadowMap, shadowUV.xy + float2(0, +pixeloffset)).x);
  211. float2 differences = abs( depths.yw - depths.xz );
  212. float gradient = min(gradientClamp, max(differences.x, differences.y));
  213. float gradientFactor = gradient * gradientScaleBias;
  214. // visibility function
  215. float depthAdjust = gradientFactor + (fixedDepthBias * centerdepth);
  216. float finalCenterDepth = centerdepth + depthAdjust;
  217. // shadowUV.z contains lightspace position of current object
  218. #if FUZZY_TEST
  219. // fuzzy test - introduces some ghosting in result and doesn't appear to be needed?
  220. //float visibility = saturate(1 + delta_z / (gradient * shadowFuzzyWidth));
  221. float visibility = saturate(1 + (finalCenterDepth - shadowUV.z) * shadowFuzzyWidth * shadowUV.w);
  222. result = vertexColour * visibility;
  223. #else
  224. // hard test
  225. #if PCF
  226. // use depths from prev, calculate diff
  227. depths += depthAdjust.xxxx;
  228. float final = (finalCenterDepth > shadowUV.z) ? 1.0f : 0.0f;
  229. final += (depths.x > shadowUV.z) ? 1.0f : 0.0f;
  230. final += (depths.y > shadowUV.z) ? 1.0f : 0.0f;
  231. final += (depths.z > shadowUV.z) ? 1.0f : 0.0f;
  232. final += (depths.w > shadowUV.z) ? 1.0f : 0.0f;
  233. final *= 0.2f;
  234. result = float4(vertexColour.xyz * final, 1);
  235. #else
  236. result = (finalCenterDepth > shadowUV.z) ? vertexColour : float4(0,0,0,1);
  237. #endif
  238. #endif
  239. }