PPTonemapping.bsl 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include "$ENGINE$\PPTonemapCommon.bslinc"
  2. technique 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. cbuffer Input
  52. {
  53. float gRawGamma;
  54. float gManualExposureScale;
  55. uint gNumSamples;
  56. }
  57. float3 ColorLookupTable(float3 linearColor)
  58. {
  59. float3 logColor = LinearToLogColor(linearColor);
  60. float3 UVW = logColor * ((LUT_SIZE - 1) / (float)LUT_SIZE) + (0.5f / LUT_SIZE);
  61. #if VOLUME_LUT
  62. float3 gradedColor = gColorLUT.Sample(gColorLUTSamp, UVW).rgb;
  63. #else
  64. float slice = floor(UVW.z * LUT_SIZE - 0.5f);
  65. float sliceFrac = UVW.z * LUT_SIZE - 0.5f - slice;
  66. float U = (UVW.x + slice) / LUT_SIZE;
  67. float V = UVW.y;
  68. // Blend between two slices (emulating a 3D texture sample)
  69. float3 v0 = gColorLUT.Sample(gColorLUTSamp, float2(U, V)).rgb;
  70. float3 v1 = gColorLUT.Sample(gColorLUTSamp, float2(U + 1.0f / LUT_SIZE, V)).rgb;
  71. float3 gradedColor = lerp(v0, v1, sliceFrac);
  72. #endif
  73. return gradedColor;
  74. }
  75. float3 tonemapSample(float3 samp, float exposureScale)
  76. {
  77. #if AUTO_EXPOSURE
  78. samp = samp * exposureScale;
  79. #else
  80. samp = samp * gManualExposureScale;
  81. #endif
  82. #if GAMMA_ONLY
  83. return pow(samp, gRawGamma);
  84. #else
  85. return ColorLookupTable(samp);
  86. #endif
  87. }
  88. float4 fsmain(VStoFS input) : SV_Target0
  89. {
  90. float4 sceneColor = 0;
  91. #if MSAA
  92. // Note: Ideally I'd want to use the MSAA coverage texture here, so I can only average samples for pixels
  93. // that really need it. But because forward rendering doesn't write to MSAA coverage I can't do it as I
  94. // don't have up-to-date coverage information. It might be good to find a way around this.
  95. for(uint i = 0; i < gNumSamples; ++i)
  96. sceneColor.rgb += tonemapSample(gInputTex.Load(trunc(input.uv0), i).rgb, input.exposureScale);
  97. sceneColor.rgb /= gNumSamples;
  98. #else
  99. sceneColor.rgb = tonemapSample(gInputTex.Sample(gInputSamp, input.uv0).rgb, input.exposureScale);
  100. #endif
  101. // Output luma in gamma-space, for FXAA
  102. // Note: This can be avoided if FXAA is not used
  103. sceneColor.a = dot(sceneColor.rgb, float3(0.299, 0.587, 0.114));
  104. return sceneColor;
  105. }
  106. };
  107. };