Bloom.ankiprog 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma anki technique Downscale vert pixel comp
  6. #pragma anki technique Exposure vert pixel comp
  7. #pragma anki technique Upscale vert pixel comp
  8. #include <AnKi/Shaders/QuadVert.hlsl>
  9. // ===========================================================================
  10. // Downscale =
  11. // ===========================================================================
  12. #if(ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER) && ANKI_TECHNIQUE_Downscale
  13. # include <AnKi/Shaders/Functions.hlsl>
  14. SamplerState g_linearAnyClampSampler : register(s0);
  15. Texture2D<Vec3> g_tex : register(t0);
  16. struct Constants
  17. {
  18. Vec2 m_fbSize;
  19. UVec2 m_padding;
  20. };
  21. ANKI_FAST_CONSTANTS(Constants, g_consts)
  22. # if ANKI_COMPUTE_SHADER
  23. RWTexture2D<Vec4> g_storageTex : register(u1);
  24. # endif
  25. # if ANKI_COMPUTE_SHADER
  26. [numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
  27. {
  28. const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5) / g_consts.m_fbSize;
  29. # else
  30. Vec3 main(VertOut input) : SV_TARGET0
  31. {
  32. const Vec2 uv = input.m_uv;
  33. # endif
  34. Vec3 output;
  35. const F32 weight = 1.0 / 5.0;
  36. output = g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0) * weight;
  37. output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)) * weight;
  38. output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)) * weight;
  39. output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)) * weight;
  40. output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)) * weight;
  41. # if ANKI_COMPUTE_SHADER
  42. g_storageTex[svDispatchThreadId] = Vec4(output, 1.0);
  43. # else
  44. return output;
  45. # endif
  46. }
  47. #endif // (ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER) && ANKI_TECHNIQUE_Downscale
  48. // ===========================================================================
  49. // Exposure =
  50. // ===========================================================================
  51. #if(ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER) && ANKI_TECHNIQUE_Exposure
  52. # include <AnKi/Shaders/TonemappingFunctions.hlsl>
  53. # include <AnKi/Shaders/Functions.hlsl>
  54. SamplerState g_linearAnyClampSampler : register(s0);
  55. Texture2D<Vec4> g_inTex : register(t0);
  56. # define TONEMAPPING_REGISTER u0
  57. # include <AnKi/Shaders/TonemappingResources.hlsl>
  58. struct Consts
  59. {
  60. F32 m_threshold;
  61. F32 m_scale;
  62. F32 m_padding0;
  63. F32 m_padding1;
  64. };
  65. ANKI_FAST_CONSTANTS(Consts, g_consts)
  66. # if ANKI_COMPUTE_SHADER
  67. RWTexture2D<Vec4> g_storageTex : register(u1);
  68. # endif
  69. # if ANKI_COMPUTE_SHADER
  70. [numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
  71. # else
  72. Vec3 main(VertOut input) : SV_TARGET0
  73. # endif
  74. {
  75. # if ANKI_COMPUTE_SHADER
  76. Vec2 imgSize;
  77. g_storageTex.GetDimensions(imgSize.x, imgSize.y);
  78. const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5) / imgSize;
  79. # else
  80. const Vec2 uv = input.m_uv;
  81. # endif
  82. const F32 weight = 1.0 / 5.0;
  83. Vec3 color = g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb * weight;
  84. color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)).rgb * weight;
  85. color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)).rgb * weight;
  86. color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)).rgb * weight;
  87. color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)).rgb * weight;
  88. color = tonemap<F32>(color, readExposureAndAverageLuminance<F32>().y, g_consts.m_threshold) * g_consts.m_scale;
  89. # if ANKI_COMPUTE_SHADER
  90. g_storageTex[svDispatchThreadId] = Vec4(color, 0.0);
  91. # else
  92. return color;
  93. # endif
  94. }
  95. #endif // (ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER) && ANKI_TECHNIQUE_Exposure
  96. // ===========================================================================
  97. // Upscale =
  98. // ===========================================================================
  99. #if(ANKI_PIXEL_SHADER || ANKI_COMPUTE_SHADER) && ANKI_TECHNIQUE_Upscale
  100. # include <AnKi/Shaders/Functions.hlsl>
  101. // Constants
  102. # define ENABLE_CHROMATIC_DISTORTION 1
  103. # define ENABLE_HALO 1
  104. constexpr U32 kMaxGhosts = 4u;
  105. constexpr F32 kGhostDispersal = 0.7;
  106. constexpr F32 kHaloWidth = 0.4;
  107. constexpr F32 kChromaticDistortion = 3.0;
  108. constexpr F32 kHaloOpacity = 0.5;
  109. SamplerState g_linearAnyClampSampler : register(s0);
  110. Texture2D<Vec4> g_inputTex : register(t0);
  111. Texture2D<Vec3> g_lensDirtTex : register(t1);
  112. # if ANKI_COMPUTE_SHADER
  113. RWTexture2D<Vec4> g_storageTex : register(u0);
  114. # endif
  115. Vec3 textureDistorted(Texture2D<Vec4> tex, SamplerState sampl, Vec2 uv,
  116. Vec2 direction, // direction of distortion
  117. Vec3 distortion) // per-channel distortion factor
  118. {
  119. # if ENABLE_CHROMATIC_DISTORTION
  120. return Vec3(tex.SampleLevel(sampl, uv + direction * distortion.r, 0.0).r, tex.SampleLevel(sampl, uv + direction * distortion.g, 0.0).g,
  121. tex.SampleLevel(sampl, uv + direction * distortion.b, 0.0).b);
  122. # else
  123. return tex.SampleLevel(uv, 0.0).rgb;
  124. # endif
  125. }
  126. Vec3 ssLensFlare(Vec2 uv)
  127. {
  128. Vec2 textureSize;
  129. g_inputTex.GetDimensions(textureSize.x, textureSize.y);
  130. const Vec2 texelSize = 1.0 / textureSize;
  131. const Vec3 distortion = Vec3(-texelSize.x * kChromaticDistortion, 0.0, texelSize.x * kChromaticDistortion);
  132. const F32 lensOfHalf = length(Vec2(0.5, 0.5));
  133. const Vec2 flipUv = Vec2(1.0, 1.0) - uv;
  134. const Vec2 ghostVec = (Vec2(0.5, 0.5) - flipUv) * kGhostDispersal;
  135. const Vec2 direction = normalize(ghostVec);
  136. Vec3 result = Vec3(0.0, 0.0, 0.0);
  137. // Sample ghosts
  138. [unroll] for(U32 i = 0u; i < kMaxGhosts; ++i)
  139. {
  140. const Vec2 offset = frac(flipUv + ghostVec * F32(i));
  141. F32 weight = length(Vec2(0.5, 0.5) - offset) / lensOfHalf;
  142. weight = pow(1.0 - weight, 10.0);
  143. result += textureDistorted(g_inputTex, g_linearAnyClampSampler, offset, direction, distortion) * weight;
  144. }
  145. // Sample halo
  146. # if ENABLE_HALO
  147. const Vec2 haloVec = normalize(ghostVec) * kHaloWidth;
  148. F32 weight = length(Vec2(0.5, 0.5) - frac(flipUv + haloVec)) / lensOfHalf;
  149. weight = pow(1.0 - weight, 20.0);
  150. result += textureDistorted(g_inputTex, g_linearAnyClampSampler, flipUv + haloVec, direction, distortion) * (weight * kHaloOpacity);
  151. # endif
  152. // Lens dirt
  153. result *= g_lensDirtTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb;
  154. return result;
  155. }
  156. Vec3 upscale(Vec2 uv)
  157. {
  158. const F32 weight = 1.0 / 5.0;
  159. Vec3 result = g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb * weight;
  160. result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)).rgb * weight;
  161. result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)).rgb * weight;
  162. result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)).rgb * weight;
  163. result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)).rgb * weight;
  164. return result;
  165. }
  166. # if ANKI_COMPUTE_SHADER
  167. [numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
  168. # else
  169. Vec3 main(VertOut input) : SV_TARGET0
  170. # endif
  171. {
  172. # if ANKI_COMPUTE_SHADER
  173. Vec2 storageTexSize;
  174. g_storageTex.GetDimensions(storageTexSize.x, storageTexSize.y);
  175. const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5) / storageTexSize;
  176. # else
  177. const Vec2 uv = input.m_uv;
  178. # endif
  179. const Vec3 outColor = ssLensFlare(uv) + upscale(uv);
  180. # if ANKI_COMPUTE_SHADER
  181. g_storageTex[svDispatchThreadId] = Vec4(outColor, 0.0);
  182. # else
  183. return outColor;
  184. # endif
  185. }
  186. #endif // (ANKI_PIXEL_SHADER || ANKI_COMPUTE_SHADER) && ANKI_TECHNIQUE_Upscale