Advertisement
Guest User

The Witcher 3 - feedingGBuffer pixel shader (w/o spec tex)

a guest
Dec 28th, 2018
552
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.89 KB | None | 0 0
  1. cbuffer cbPerFrame : register (b0)
  2. {
  3. float4 cb0_v0;
  4. float4 cb0_v1;
  5. float4 cb0_v2;
  6. float4 cb0_v3;
  7. }
  8.  
  9. cbuffer cbData : register (b12)
  10. {
  11. float elapsedTime;
  12. uint numFrames;
  13. float2 pad;
  14.  
  15. float2 viewportSize;
  16. float2 viewportInvSize;
  17. }
  18.  
  19. cbuffer cbMaterial : register (b4)
  20. {
  21. float4 cb4_v0;
  22. float4 cb4_v1;
  23. float4 cb4_v2;
  24. float4 cb4_v3;
  25. float4 cb4_v4;
  26. float4 cb4_v5;
  27. float4 cb4_v6;
  28. float4 cb4_v7;
  29. }
  30.  
  31. Texture2D texture0 : register (t0);
  32. Texture2D texture1 : register (t1);
  33. //Texture2D texture2 : register (t2);
  34. Texture2D texture13 : register (t13);
  35.  
  36. SamplerState samplerAnisoWrap : register (s0);
  37. SamplerState samplerPointClamp : register (s13);
  38.  
  39.  
  40. struct VS_OUTPUT
  41. {
  42. float4 out0 : PARAMS;
  43. float4 out1 : PARAMS1;
  44. float3 NormalW : NORMAL;
  45. float3 TangentW : TANGENT;
  46. };
  47.  
  48. struct PS_OUTPUT
  49. {
  50. float4 RT0 : SV_Target0;
  51. float4 RT1 : SV_Target1;
  52. float4 RT2 : SV_Target2;
  53. };
  54.  
  55. // Crytek's BFN
  56. // see:
  57. // https://github.com/CRYTEK/CRYENGINE/blob/release/Engine/Shaders/HWScripts/CryFX/Common.cfi#L383
  58. void CompressUnsignedNormalToNormalsBuffer( in Texture2D texNormalsFit, inout float3 vNormal )
  59. {
  60. // expand from unsigned
  61. //vNormal.rgb = vNormal.rgb * 2.h - 1.h;
  62.  
  63. // renormalize (needed if any blending or interpolation happened before)
  64. vNormal.rgb = normalize(vNormal.rgb);
  65.  
  66. // get unsigned normal for cubemap lookup (note the full float presision is required)
  67. float3 vNormalUns = abs( vNormal.rgb );
  68.  
  69. // get the main axis for cubemap lookup
  70. float maxNAbs = max(vNormalUns.z, max(vNormalUns.x, vNormalUns.y));
  71.  
  72. // get texture coordinates in a collapsed cubemap
  73. float2 vTexCoord = vNormalUns.z < maxNAbs ? (vNormalUns.y < maxNAbs?vNormalUns.yz : vNormalUns.xz) : vNormalUns.xy;
  74. vTexCoord = vTexCoord.x < vTexCoord.y ? (vTexCoord.yx) : (vTexCoord.xy);
  75. vTexCoord.y /= vTexCoord.x;
  76.  
  77. // fit normal into the edge of unit cube
  78. vNormal /= maxNAbs;
  79.  
  80. // look-up fitting length and scale the normal to get the best fit
  81. float fFittingScale = texNormalsFit.SampleLevel( samplerPointClamp, vTexCoord, 0 ).r;
  82.  
  83. // scale the normal to get the best fit
  84. vNormal *= fFittingScale;
  85. }
  86.  
  87. float getMaxComponent(in float3 color)
  88. {
  89. float result = max( color.x, max( color.y, color.z ) );
  90.  
  91. return result;
  92. }
  93.  
  94. float3 albedoColorFilter( in float3 color, in float desaturationFactor, in float3 desaturationValue )
  95. {
  96. float sumColorComponents = color.r + color.g + color.b;
  97.  
  98. float averageColorComponentValue = 0.3333 * sumColorComponents;
  99. float oneMinusAverageColorComponentValue = 1.0 - averageColorComponentValue;
  100.  
  101. float factor = 0.5 * (desaturationFactor - 1.0);
  102.  
  103. float avgColorComponent = lerp(averageColorComponentValue, oneMinusAverageColorComponentValue, saturate(factor));
  104. float3 tempColor0 = saturate(color * desaturationValue * 1.5);
  105.  
  106. float mask = saturate( avgColorComponent * abs(factor) );
  107.  
  108. float3 finalColor = lerp(color, tempColor0, mask);
  109. return finalColor;
  110. }
  111.  
  112. PS_OUTPUT GBufferPS( in VS_OUTPUT Input, in uint bIsFrontFace : SV_IsFrontFace ) : SV_Target0
  113. {
  114. float paramZ2 = Input.out0.z * cb4_v0.x;
  115.  
  116. // We have three render target outputs
  117. PS_OUTPUT pout = (PS_OUTPUT) 0;
  118.  
  119. // Texcoords
  120. float2 Texcoords = Input.out1.xy;
  121.  
  122. // Data from textures
  123. float4 normalTex = texture1.Sample( samplerAnisoWrap, Texcoords );
  124. float3 colorTex = texture0.Sample( samplerAnisoWrap, Texcoords ).rgb;
  125.  
  126.  
  127. /* ALBEDO */
  128. // optional desaturation (?) filter
  129. float3 albedoColor = albedoColorFilter( colorTex, cb4_v2.x, cb4_v1.rgb );
  130. float albedoMaxComponent = getMaxComponent( albedoColor );
  131.  
  132. // I really have no idea what this is
  133. // In most of cases Vertex Shader outputs "paramZ" as 0
  134. float paramZ = Input.out0.z; // note, mostly 0
  135.  
  136. // Note that 0.70 are 0.85 are not present in the output assembly
  137. // Because I wanted to use lerp here I had to adjust them manually.
  138. float param = (albedoMaxComponent > 0.22) ? 0.70 : 0.85;
  139. float mulParam = lerp(1, param, paramZ2);
  140.  
  141. // Output
  142. pout.RT0.rgb = albedoColor * mulParam;
  143. pout.RT0.a = cb4_v6.x;
  144.  
  145. /* NORMALS */
  146. float3 sampledNormal = ((normalTex.xyz - 0.5) * 2);
  147.  
  148. // Data to construct TBN matrix
  149. float3 Tangent = Input.TangentW.xyz;
  150. float3 Normal = Input.NormalW.xyz;
  151. float3 Bitangent;
  152. Bitangent.x = Input.out0.w;
  153. Bitangent.yz = Input.out1.zw;
  154.  
  155. // remove this saturate in real scenario, this is a hack to make sure normal-tbn multiplication
  156. // will have 'mad' instructions
  157. Bitangent = saturate(Bitangent);
  158.  
  159. float3x3 TBN = float3x3(Tangent, Bitangent, Normal);
  160. float3 normal = mul( sampledNormal, TBN );
  161.  
  162.  
  163. // Trick to set normal vector properly in wireframe mode (I guess)
  164. //
  165. // See: https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-semantics
  166. //
  167. // * SV_IsFrontFace
  168. // Specifies whether a triangle is front facing.
  169. // For lines and points, IsFrontFace has the value true.
  170. // The exception is lines drawn out of triangles (wireframe mode),
  171. // which sets IsFrontFace the same way as rasterizing the triangle in solid mode.
  172. // Can be written to by the geometry shader, and read by the pixel shader.
  173. [branch] if (bIsFrontFace <= 0)
  174. {
  175. float cosTheta = dot(Input.NormalW, normal);
  176. float3 invNormal = cosTheta * Input.NormalW;
  177. normal = normal - 2*invNormal;
  178. }
  179.  
  180.  
  181.  
  182. /* SPECULAR */
  183. //float3 specularTex = texture2.Sample( samplerAnisoWrap, Texcoords ).rgb;
  184. float oneMinusReflectivity = 1.0 - normalTex.a;
  185. float3 specularTex = pow(cb4_v3.rgb, 2.2);
  186. oneMinusReflectivity = oneMinusReflectivity * cb4_v4.x + cb4_v5.x;
  187. specularTex = saturate(specularTex * oneMinusReflectivity);
  188. specularTex = pow(specularTex, 1.0/2.2);
  189.  
  190. // Similar algorithm as in Albedo. Calculate max component, compare this with
  191. // some threshold and calculate "minimum" value if needed.
  192. // Because in the scene I analyzed paramZ was set to zero, value from texture will be
  193. // the final result.
  194. float specularMaxComponent = getMaxComponent( specularTex );
  195. float3 specB = (specularMaxComponent > 0.2) ? specularTex : float3(0.12, 0.12, 0.12);
  196. float3 finalSpec = lerp(specularTex, specB, paramZ);
  197. pout.RT2.xyz = finalSpec;
  198.  
  199.  
  200. /* REFLECTIVITY */
  201. float reflectivity = normalTex.a;
  202. float reflectivity2 = (reflectivity < 0.33) ? (reflectivity * 0.95) : 0.33;
  203.  
  204. float finalReflectivity = lerp(reflectivity, reflectivity2, paramZ);
  205. pout.RT1.a = finalReflectivity;
  206. pout.RT2.w = (cb4_v7.x > 0.0) ? (16.5/255.0) : 0.0;
  207.  
  208. /* BEST FIT NORMALS */
  209. CompressUnsignedNormalToNormalsBuffer(texture13, normal.xyz);
  210. pout.RT1.xyz = normal * 0.5 + 0.5;
  211.  
  212. return pout;
  213. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement