Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
9.5 KiB

  1. //---------------------------------------------------------------------------------//
  2. // Parallax occlusion mapping algorithm implementation. Pixel shader.
  3. //---------------------------------------------------------------------------------//
  4. //..........................................................................................
  5. // Uniform shader parameters declaration
  6. //..........................................................................................
  7. const float4 g_ParallaxParms : register( c0 );
  8. float fShadowSoftening = 0.59f; // fixme: should be a vmt param
  9. float fHeightMapRange = 0.02f; // fixme: should be a vmt param
  10. // unused stuff
  11. float fSpecularExponent = 100.0f; // fixme: should be a vmt param
  12. float fDiffuseBrightness = 1.0f;
  13. float4 cAmbientColor = float4( 1.0f, 1.0f, 1.0f, 1.0f );
  14. float4 cDiffuseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f );
  15. float4 cSpecularColor = float4( 1.0f, 1.0f, 1.0f, 1.0f );
  16. // texture samplers
  17. sampler tBaseMap;
  18. sampler tNormalMap;
  19. //..........................................................................................
  20. // Note: centroid is specified if multisampling is enabled through RenderMonkey's DirectX
  21. // window preferences settings
  22. //..........................................................................................
  23. struct PS_INPUT
  24. {
  25. float2 texCoord : TEXCOORD0;
  26. // float3 vLightTS : TEXCOORD1_centroid; // light vector in tangent space, denormalized
  27. float3 vViewTS : TEXCOORD2_centroid; // view vector in tangent space, denormalized
  28. float2 vParallaxOffsetTS : TEXCOORD3_centroid; // Parallax offset vector in tangent space
  29. float3 vNormalWS : TEXCOORD4_centroid; // Normal vector in world space
  30. float3 vViewWS : TEXCOORD5_centroid; // View vector in world space
  31. float4 vDebug : TEXCOORD6;
  32. };
  33. //..........................................................................................
  34. // Function: ComputeIllumination
  35. //
  36. // Description: Computes phong illumination for the given pixel using its attribute textures
  37. // and a light vector.
  38. //..........................................................................................
  39. float4 ComputeIllumination( float2 texCoord, float3 vLightTS, float3 vViewTS, float fOcclusionShadow )
  40. {
  41. // Sample the normal from the normal map for the given texture sample:
  42. float3 vNormalTS = normalize( tex2D( tNormalMap, texCoord ) * 2 - 1 );
  43. // Sample base map:
  44. float4 cBaseColor = tex2D( tBaseMap, texCoord );
  45. // Compute diffuse color component:
  46. float4 cDiffuse = saturate( dot( vNormalTS, vLightTS )) * cDiffuseColor;
  47. // Compute specular component:
  48. float3 vReflectionTS = normalize( 2 * dot( vViewTS, vNormalTS ) * vNormalTS - vViewTS );
  49. float fRdotL = dot( vReflectionTS, vLightTS );
  50. float4 cSpecular = saturate( pow( fRdotL, fSpecularExponent )) * cSpecularColor;
  51. float4 cFinalColor = (( cAmbientColor + cDiffuse ) * cBaseColor + cSpecular ) * fOcclusionShadow;
  52. return cFinalColor;
  53. }
  54. //...........................................................................................
  55. // Function: ps_main
  56. //
  57. // Description: Computes pixel illumination result due to applying parallax occlusion mapping
  58. // to simulation of view-dependent surface displacement for a given height map
  59. //...........................................................................................
  60. float4 main( PS_INPUT i ) : COLOR0
  61. {
  62. int nMinSamples = g_ParallaxParms.x;
  63. int nMaxSamples = g_ParallaxParms.y;
  64. // Normalize the interpolated vectors:
  65. float3 vViewTS = normalize( i.vViewTS );
  66. float3 vViewWS = normalize( i.vViewWS );
  67. // float3 vLightTS = normalize( i.vLightTS );
  68. float3 vNormalWS = normalize( i.vNormalWS );
  69. float4 cResultColor = float4( 0, 0, 0, 1 );
  70. // Compute all the derivatives:
  71. float2 dx = ddx( i.texCoord );
  72. float2 dy = ddy( i.texCoord );
  73. //===============================================//
  74. // Parallax occlusion mapping offset computation //
  75. //===============================================//
  76. // Utilize dynamic flow control to change the number of samples per ray
  77. // depending on the viewing angle for the surface. Oblique angles require
  78. // smaller step sizes to achieve more accurate precision for computing displacement.
  79. // We express the sampling rate as a linear function of the angle between
  80. // the geometric normal and the view direction ray:
  81. int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewWS, vNormalWS ) );
  82. // Intersect the view ray with the height field profile along the direction of
  83. // the parallax offset ray (computed in the vertex shader. Note that the code is
  84. // designed specifically to take advantage of the dynamic flow control constructs
  85. // in HLSL and is very sensitive to specific syntax. When converting to other examples,
  86. // if still want to use dynamic flow control in the resulting assembly shader,
  87. // care must be applied.
  88. //
  89. // In the below steps we approximate the height field profile as piecewise linear
  90. // curve. We find the pair of endpoints between which the intersection between the
  91. // height field profile and the view ray is found and then compute line segment
  92. // intersection for the view ray and the line segment formed by the two endpoints.
  93. // This intersection is the displacement offset from the original texture coordinate.
  94. // See the above paper for more details about the process and derivation.
  95. //
  96. float fCurrHeight = 0.0;
  97. float fStepSize = 1.0 / (float) nNumSteps;
  98. float fPrevHeight = 1.0;
  99. float fNextHeight = 0.0;
  100. int nStepIndex = 0;
  101. bool bCondition = true;
  102. float2 vTexOffsetPerStep = fStepSize * i.vParallaxOffsetTS;
  103. float2 vTexCurrentOffset = i.texCoord;
  104. float fCurrentBound = 1.0;
  105. float fParallaxAmount = 0.0;
  106. float2 pt1 = 0;
  107. float2 pt2 = 0;
  108. float2 texOffset2 = 0;
  109. while ( nStepIndex < nNumSteps )
  110. {
  111. vTexCurrentOffset -= vTexOffsetPerStep;
  112. // Sample height map which in this case is stored in the alpha channel of the normal map:
  113. fCurrHeight = tex2Dgrad( tNormalMap, vTexCurrentOffset, dx, dy ).a;
  114. fCurrentBound -= fStepSize;
  115. if ( fCurrHeight > fCurrentBound )
  116. {
  117. pt1 = float2( fCurrentBound, fCurrHeight );
  118. pt2 = float2( fCurrentBound + fStepSize, fPrevHeight );
  119. texOffset2 = vTexCurrentOffset - vTexOffsetPerStep;
  120. nStepIndex = nNumSteps + 1;
  121. }
  122. else
  123. {
  124. nStepIndex++;
  125. fPrevHeight = fCurrHeight;
  126. }
  127. } // End of while ( nStepIndex < nNumSteps )
  128. float fDelta2 = pt2.x - pt2.y;
  129. float fDelta1 = pt1.x - pt1.y;
  130. fParallaxAmount = (pt1.x * fDelta2 - pt2.x * fDelta1 ) / ( fDelta2 - fDelta1 );
  131. float2 vParallaxOffset = i.vParallaxOffsetTS * (1 - fParallaxAmount );
  132. // The computed texture offset for the displaced point on the pseudo-extruded surface:
  133. float2 texSample = i.texCoord - vParallaxOffset;
  134. // float2 vLightRayTS = vLightTS.xy * fHeightMapRange;
  135. // Compute the soft blurry shadows taking into account self-occlusion for features of the height
  136. // field:
  137. // float sh0 = tex2Dgrad( tNormalMap, texSample, dx, dy ).a;
  138. // float shA = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.88, dx, dy ).a - sh0 - 0.88 ) * 1 * fShadowSoftening;
  139. // float sh9 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.77, dx, dy ).a - sh0 - 0.77 ) * 2 * fShadowSoftening;
  140. // float sh8 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.66, dx, dy ).a - sh0 - 0.66 ) * 4 * fShadowSoftening;
  141. // float sh7 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.55, dx, dy ).a - sh0 - 0.55 ) * 6 * fShadowSoftening;
  142. // float sh6 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.44, dx, dy ).a - sh0 - 0.44 ) * 8 * fShadowSoftening;
  143. // float sh5 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.33, dx, dy ).a - sh0 - 0.33 ) * 10 * fShadowSoftening;
  144. // float sh4 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.22, dx, dy ).a - sh0 - 0.22 ) * 12 * fShadowSoftening;
  145. // Compute the actual shadow strength:
  146. // float fOcclusionShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 );
  147. // The previous computation overbrightens the image, let's adjust for that:
  148. // fOcclusionShadow = fOcclusionShadow * 0.6 + 0.4;
  149. // Compute resulting color for the pixel:
  150. // cResultColor = ComputeIllumination( texSample, vLightTS, vViewTS, fOcclusionShadow );
  151. // cResultColor.xyz = ( float )nNumSteps / nMaxSamples;
  152. //cResultColor.xyz = float3( vTexOffsetPerStep, 0.0f );
  153. cResultColor.xyz = tex2Dgrad( tNormalMap, texSample, dx, dy ).rgb;
  154. cResultColor.a = 1.0f;
  155. // cResultColor.xyz = float3( vParallaxOffset * 10.0, 0.0f );
  156. // cResultColor.xyz = ( float3 )fParallaxAmount * .1f;
  157. // cResultColor.xyz = float3( i.texCoord - ( int2 )i.texCoord, 0.0f );
  158. // cResultColor.xyz = i.vViewTS;
  159. // cResultColor.xyz = i.vNormalWS.xyz;
  160. // cResultColor.xyz = float3( i.vParallaxOffsetTS * 10.0f, 0.0f );
  161. // cResultColor = i.vDebug;
  162. // cResultColor.xyz = ( float3 )tex2Dgrad( tNormalMap, texSample, dx, dy ).a;
  163. // cResultColor.xyz = float3( vTexOffsetPerStep * 10.0f, 0.0f );
  164. // cResultColor = float4( 1.0f, 0.0f, 0.0f, 1.0f );
  165. return cResultColor;
  166. } // End of float4 ps_main(..)
  167. #if 0
  168. struct PS_INPUT
  169. {
  170. float2 texCoord : TEXCOORD0;
  171. // float3 vLightTS : TEXCOORD1_centroid; // light vector in tangent space, denormalized
  172. float3 vViewTS : TEXCOORD2_centroid; // view vector in tangent space, denormalized
  173. float2 vParallaxOffsetTS : TEXCOORD3_centroid; // Parallax offset vector in tangent space
  174. float3 vNormalWS : TEXCOORD4_centroid; // Normal vector in world space
  175. float3 vViewWS : TEXCOORD5_centroid; // View vector in world space
  176. };
  177. #endif