PPTonemapping.bsl 2.9 KB

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