Hdr.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /******************************************************************************/
  2. #include "!Header.h"
  3. #include "Hdr.h"
  4. #define SIMPLE 1 // mode 0 is not fully developed
  5. #define BRIGHT 1 // if apply adjustment for scenes where half pixels are bright, and other half are dark, in that case prefer focus on brighter, to avoid making already bright pixels too bright
  6. #define GEOMETRIC 0 // don't use geometric mean, because of cases when bright sky is mostly occluded by dark objects, then entire scene will get brighter, making the sky look too bright and un-realistic
  7. /******************************************************************************/
  8. // HDR
  9. /******************************************************************************/
  10. Vec4 HdrDS_PS(NOPERSP Vec2 inTex:TEXCOORD,
  11. uniform Int step ):COLOR
  12. {
  13. Vec2 tex_min=inTex-ColSize.xy,
  14. tex_max=inTex+ColSize.xy;
  15. if(step==0)
  16. {
  17. // use linear filtering because we're downsampling
  18. Vec sum=TexLod(Col, Vec2(tex_min.x, tex_min.y)).rgb
  19. +TexLod(Col, Vec2(tex_max.x, tex_min.y)).rgb
  20. +TexLod(Col, Vec2(tex_min.x, tex_max.y)).rgb
  21. +TexLod(Col, Vec2(tex_max.x, tex_max.y)).rgb;
  22. Flt lum;
  23. #if SIMPLE
  24. lum=Max(sum*HdrWeight);
  25. #else
  26. // fast approximation, more precise but slower would be to call 'SRGBToLinear' for every pixel, or mark that 'Col' is a SRGB texture for step==0
  27. Vec lin=SRGBToLinear(sum*0.25f);
  28. lum=Dot(lin, ColorLumWeight2); // this gives us 'LinearLumOfSRGBColor'
  29. #endif
  30. #if BRIGHT
  31. lum=Sqr(lum);
  32. #endif
  33. #if GEOMETRIC
  34. lum=log2(Max(lum, EPS)); // NaN
  35. #endif
  36. return lum;
  37. }else
  38. {
  39. // use linear filtering because we're downsampling
  40. return Avg(TexLod(Col, Vec2(tex_min.x, tex_min.y)).x,
  41. TexLod(Col, Vec2(tex_max.x, tex_min.y)).x,
  42. TexLod(Col, Vec2(tex_min.x, tex_max.y)).x,
  43. TexLod(Col, Vec2(tex_max.x, tex_max.y)).x);
  44. }
  45. }
  46. /******************************************************************************/
  47. Vec4 HdrUpdate_PS(NOPERSP Vec2 inTex:TEXCOORD):COLOR
  48. {
  49. Flt lum=TexPoint(Col, Vec2(0, 0)).x;
  50. #if GEOMETRIC
  51. lum=exp2(lum); // we've applied 'log2' above, so revert it back
  52. #endif
  53. #if BRIGHT
  54. lum=Sqrt(lum); // we've applied 'Sqr' above, so revert it back
  55. #endif
  56. lum=HdrBrightness/Max(lum, EPS_COL); // desired scale
  57. lum=Mid(lum, HdrMaxDark, HdrMaxBright);
  58. return Lerp(lum, TexPoint(Lum, Vec2(0, 0)).x, Step);
  59. }
  60. /******************************************************************************/
  61. Vec4 Hdr_PS(NOPERSP Vec2 inTex:TEXCOORD):COLOR
  62. {
  63. Vec4 col=TexLod (Col, inTex); // can't use 'TexPoint' because 'Col' can be supersampled
  64. Flt lum=TexPoint(Lum, Vec2(0, 0)).x;
  65. #if SIMPLE
  66. col.rgb*=lum;
  67. #else
  68. col.rgb=LinearToSRGB(SRGBToLinear(col.rgb)*lum);
  69. #endif
  70. return col;
  71. }
  72. /******************************************************************************/
  73. // TECHNIQUES
  74. /******************************************************************************/
  75. TECHNIQUE(HdrDS0, Draw_VS(), HdrDS_PS(0));
  76. TECHNIQUE(HdrDS1, Draw_VS(), HdrDS_PS(1));
  77. TECHNIQUE(HdrUpdate, Draw_VS(), HdrUpdate_PS());
  78. TECHNIQUE(Hdr , Draw_VS(), Hdr_PS());
  79. /******************************************************************************/