PPTonemapping.bsl 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "$ENGINE$\PPTonemapCommon.bslinc"
  2. shader PPTonemapping
  3. {
  4. mixin PPTonemapCommon;
  5. variations
  6. {
  7. VOLUME_LUT = { true, false };
  8. GAMMA_ONLY = { true, false };
  9. AUTO_EXPOSURE = { true, false };
  10. MSAA = { true, false };
  11. };
  12. depth
  13. {
  14. read = false;
  15. write = false;
  16. };
  17. code
  18. {
  19. struct VStoFS
  20. {
  21. float4 position : SV_POSITION;
  22. float2 uv0 : TEXCOORD0;
  23. float exposureScale : TEXCOORD1;
  24. };
  25. struct VertexInput
  26. {
  27. float2 screenPos : POSITION;
  28. float2 uv0 : TEXCOORD0;
  29. };
  30. Texture2D gEyeAdaptationTex;
  31. VStoFS vsmain(VertexInput input)
  32. {
  33. VStoFS output;
  34. output.position = float4(input.screenPos, 0, 1);
  35. output.uv0 = input.uv0;
  36. output.exposureScale = gEyeAdaptationTex.Load(int3(0, 0, 0)).r;
  37. return output;
  38. }
  39. #if MSAA
  40. Texture2DMS<float4> gInputTex;
  41. #else
  42. SamplerState gInputSamp;
  43. Texture2D gInputTex;
  44. #endif
  45. SamplerState gColorLUTSamp;
  46. #if VOLUME_LUT
  47. Texture3D gColorLUT;
  48. #else
  49. Texture2D gColorLUT;
  50. #endif
  51. Texture2D gBloomTex;
  52. SamplerState gBloomSamp;
  53. cbuffer Input
  54. {
  55. float gRawGamma;
  56. float gManualExposureScale;
  57. float2 gTexSize;
  58. float4 gBloomTint;
  59. uint gNumSamples;
  60. }
  61. float3 ColorLookupTable(float3 linearColor)
  62. {
  63. float3 logColor = LinearToLogColor(linearColor);
  64. float3 UVW = logColor * ((LUT_SIZE - 1) / (float)LUT_SIZE) + (0.5f / LUT_SIZE);
  65. #if VOLUME_LUT
  66. float3 gradedColor = gColorLUT.Sample(gColorLUTSamp, UVW).rgb;
  67. #else
  68. float slice = floor(UVW.z * LUT_SIZE - 0.5f);
  69. float sliceFrac = UVW.z * LUT_SIZE - 0.5f - slice;
  70. float U = (UVW.x + slice) / LUT_SIZE;
  71. float V = UVW.y;
  72. // Blend between two slices (emulating a 3D texture sample)
  73. float3 v0 = gColorLUT.Sample(gColorLUTSamp, float2(U, V)).rgb;
  74. float3 v1 = gColorLUT.Sample(gColorLUTSamp, float2(U + 1.0f / LUT_SIZE, V)).rgb;
  75. float3 gradedColor = lerp(v0, v1, sliceFrac);
  76. #endif
  77. return gradedColor;
  78. }
  79. float3 tonemapSample(float3 samp, float exposureScale)
  80. {
  81. #if AUTO_EXPOSURE
  82. samp = samp * exposureScale;
  83. #else
  84. samp = samp * gManualExposureScale;
  85. #endif
  86. #if GAMMA_ONLY
  87. return pow(samp, gRawGamma);
  88. #else
  89. return ColorLookupTable(samp);
  90. #endif
  91. }
  92. float4 fsmain(VStoFS input) : SV_Target0
  93. {
  94. float4 sceneColor = 0;
  95. float3 bloomColor = gBloomTex.Sample(gBloomSamp, input.uv0) * gBloomTint;
  96. #if MSAA
  97. // Note: Ideally I'd want to use the MSAA coverage texture here, so I can only average samples for pixels
  98. // that really need it. But because forward rendering doesn't write to MSAA coverage I can't do it as I
  99. // don't have up-to-date coverage information. It might be good to find a way around this.
  100. int2 pixelXY = trunc(input.uv0 * gTexSize);
  101. for(uint i = 0; i < gNumSamples; ++i)
  102. sceneColor.rgb += tonemapSample(gInputTex.Load(pixelXY, i).rgb + bloomColor, input.exposureScale);
  103. sceneColor.rgb /= gNumSamples;
  104. #else
  105. sceneColor.rgb = tonemapSample(gInputTex.Sample(gInputSamp, input.uv0).rgb + bloomColor, input.exposureScale);
  106. #endif
  107. // Output luma in gamma-space, for FXAA
  108. // Note: This can be avoided if FXAA is not used
  109. sceneColor.a = dot(sceneColor.rgb, float3(0.299, 0.587, 0.114));
  110. return sceneColor;
  111. }
  112. };
  113. };