Lighting.hlsl 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #pragma warning(disable:3571)
  2. float GetDiffuseDir(float3 normal, float3 lightDir)
  3. {
  4. return saturate(dot(normal, lightDir));
  5. }
  6. float GetDiffusePointOrSpot(float3 normal, float3 lightVec, out float3 lightDir)
  7. {
  8. float lightDist = length(lightVec);
  9. lightDir = lightVec / lightDist;
  10. return saturate(dot(normal, lightDir)) * tex1D(sLightRampMap, lightDist).r;
  11. }
  12. float GetDiffuseDirVolumetric()
  13. {
  14. return 1.0;
  15. }
  16. float GetDiffusePointOrSpotVolumetric(float3 lightVec)
  17. {
  18. float lightDist = length(lightVec);
  19. return tex1D(sLightRampMap, lightDist).r;
  20. }
  21. float GetSpecular(float3 normal, float3 eyeVec, float3 lightDir, float specularPower)
  22. {
  23. float3 halfVec = normalize(normalize(eyeVec) + lightDir);
  24. return pow(dot(normal, halfVec), specularPower);
  25. }
  26. float3 GetAmbient(float zonePos)
  27. {
  28. return cAmbientStartColor + zonePos * cAmbientEndColor;
  29. }
  30. float GetIntensity(float3 color)
  31. {
  32. return dot(color, float3(0.333, 0.333, 0.333));
  33. }
  34. #ifdef NUMVERTEXLIGHTS
  35. float GetVertexLight(int index, float3 worldPos, float3 normal)
  36. {
  37. float3 lightDir = cVertexLights[index * 3 + 1].xyz;
  38. float3 lightPos = cVertexLights[index * 3 + 2].xyz;
  39. float invRange = cVertexLights[index * 3].w;
  40. float cutoff = cVertexLights[index * 3 + 1].w;
  41. float invCutoff = cVertexLights[index * 3 + 2].w;
  42. #ifndef BILLBOARD
  43. // Directional light
  44. if (invRange == 0.0)
  45. {
  46. float NdotL = max(dot(normal, lightDir), 0.0);
  47. return NdotL;
  48. }
  49. // Point/spot light
  50. else
  51. {
  52. float3 lightVec = (lightPos - worldPos) * invRange;
  53. float lightDist = length(lightVec);
  54. float3 localDir = lightVec / lightDist;
  55. float NdotL = max(dot(normal, localDir), 0.0);
  56. float atten = saturate(1.0 - lightDist * lightDist);
  57. float spotEffect = dot(localDir, lightDir);
  58. float spotAtten = saturate((spotEffect - cutoff) * invCutoff);
  59. return NdotL * atten * spotAtten;
  60. }
  61. #else
  62. // Directional light
  63. if (invRange == 0.0)
  64. return 1.0;
  65. // Point/spot light
  66. else
  67. {
  68. float3 lightVec = (lightPos - worldPos) * invRange;
  69. float lightDist = length(lightVec);
  70. float3 localDir = lightVec / lightDist;
  71. float atten = saturate(1.0 - lightDist * lightDist);
  72. float spotEffect = dot(localDir, lightDir);
  73. float spotAtten = saturate((spotEffect - cutoff) * invCutoff);
  74. return atten * spotAtten;
  75. }
  76. #endif
  77. }
  78. #endif
  79. #ifdef SHADOW
  80. float GetShadow(float4 shadowPos)
  81. {
  82. // Note: in case of sampling a point light cube shadow, we optimize out the w divide as it has already been performed
  83. #ifndef LQSHADOW
  84. // Take four samples and average them
  85. #ifndef POINTLIGHT
  86. float2 offsets = cShadowMapInvSize * shadowPos.w;
  87. #else
  88. float2 offsets = cShadowMapInvSize;
  89. #endif
  90. float4 inLight = float4(
  91. tex2Dproj(sShadowMap, shadowPos).r,
  92. tex2Dproj(sShadowMap, float4(shadowPos.x + offsets.x, shadowPos.yzw)).r,
  93. tex2Dproj(sShadowMap, float4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r,
  94. tex2Dproj(sShadowMap, float4(shadowPos.xy + offsets.xy, shadowPos.zw)).r
  95. );
  96. #ifdef HWSHADOW
  97. return cShadowIntensity.y + dot(inLight, cShadowIntensity.x);
  98. #else
  99. #ifndef POINTLIGHT
  100. return cShadowIntensity.y + dot(inLight * shadowPos.w > shadowPos.z, cShadowIntensity.x);
  101. #else
  102. return cShadowIntensity.y + dot(inLight > shadowPos.z, cShadowIntensity.x);
  103. #endif
  104. #endif
  105. #else
  106. // Take one sample
  107. float inLight = tex2Dproj(sShadowMap, shadowPos).r;
  108. #ifdef HWSHADOW
  109. return cShadowIntensity.y + cShadowIntensity.x * inLight;
  110. #else
  111. #ifndef POINTLIGHT
  112. return cShadowIntensity.y + cShadowIntensity.x * (inLight * shadowPos.w > shadowPos.z);
  113. #else
  114. return cShadowIntensity.y + cShadowIntensity.x * (inLight > shadowPos.z);
  115. #endif
  116. #endif
  117. #endif
  118. }
  119. float GetCubeShadow(float3 lightVec)
  120. {
  121. float3 axis = texCUBE(sFaceSelectCubeMap, lightVec).rgb;
  122. float depth = abs(dot(lightVec, axis));
  123. // Expand the maximum component of the light vector to get full 0.0 - 1.0 UV range from the cube map,
  124. // and to avoid sampling across faces. Some GPU's filter across faces, while others do not, and in this
  125. // case filtering across faces is wrong
  126. const float factor = 1.0 / 256.0;
  127. lightVec += factor * axis * lightVec;
  128. // Read the 2D UV coordinates, adjust according to shadow map size and add face offset
  129. float4 indirectPos = texCUBE(sIndirectionCubeMap, lightVec);
  130. indirectPos.xy *= cShadowCubeAdjust.xy;
  131. indirectPos.xy += float2(cShadowCubeAdjust.z + indirectPos.z * 0.5, cShadowCubeAdjust.w + indirectPos.w);
  132. float4 shadowPos = float4(indirectPos.xy, cShadowDepthFade.x + cShadowDepthFade.y / depth, 1.0);
  133. return GetShadow(shadowPos);
  134. }
  135. float GetShadowFade(float depth)
  136. {
  137. return saturate((depth - cShadowDepthFade.z) * cShadowDepthFade.w);
  138. }
  139. float4 GetDirShadowPos(const float4 iShadowPos[4], float depth)
  140. {
  141. if (depth < cShadowSplits.x)
  142. return iShadowPos[0];
  143. else if (depth < cShadowSplits.y)
  144. return iShadowPos[1];
  145. else if (depth < cShadowSplits.z)
  146. return iShadowPos[2];
  147. else
  148. return iShadowPos[3];
  149. }
  150. #ifdef SM3
  151. float4 GetDirShadowPosDeferred(const float4x4 matrices[4], float4 projWorldPos, float depth)
  152. {
  153. if (depth < cShadowSplits.x)
  154. return mul(projWorldPos, matrices[0]);
  155. else if (depth < cShadowSplits.y)
  156. return mul(projWorldPos, matrices[1]);
  157. else if (depth < cShadowSplits.z)
  158. return mul(projWorldPos, matrices[2]);
  159. else
  160. return mul(projWorldPos, matrices[3]);
  161. }
  162. #else
  163. float4 GetDirShadowPosDeferred(const float4x4 matrices[3], float4 projWorldPos, float depth)
  164. {
  165. if (depth < cShadowSplits.x)
  166. return mul(projWorldPos, matrices[0]);
  167. else if (depth < cShadowSplits.y)
  168. return mul(projWorldPos, matrices[1]);
  169. else
  170. return mul(projWorldPos, matrices[2]);
  171. }
  172. #endif
  173. #endif