PackFunctions.hlsl 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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 once
  6. #include <AnKi/Shaders/Common.hlsl>
  7. #include <AnKi/Shaders/TonemappingFunctions.hlsl>
  8. constexpr F32 kMinRoughness = 0.05;
  9. /// Pack 3D normal to 2D vector
  10. /// See the clean code in comments in revision < r467
  11. template<typename T>
  12. vector<T, 2> packNormal(vector<T, 3> normal)
  13. {
  14. const T scale = 1.7777;
  15. const T scalar1 = (normal.z + T(1)) * (scale * T(2));
  16. return normal.xy / scalar1 + T(0.5);
  17. }
  18. /// Reverse the packNormal
  19. template<typename T>
  20. vector<T, 3> unpackNormal(const vector<T, 2> enc)
  21. {
  22. const T scale = 1.7777;
  23. const vector<T, 2> nn = enc * (T(2) * scale) - scale;
  24. const T g = T(2) / (dot(nn.xy, nn.xy) + T(1));
  25. vector<T, 3> normal;
  26. normal.xy = g * nn.xy;
  27. normal.z = g - T(1);
  28. return normalize(normal);
  29. }
  30. // See http://johnwhite3d.blogspot.no/2017/10/signed-octahedron-normal-encoding.html
  31. // Result in [0.0, 1.0]
  32. template<typename T>
  33. vector<T, 3> signedOctEncode(vector<T, 3> n)
  34. {
  35. vector<T, 3> outn;
  36. const vector<T, 3> nabs = abs(n);
  37. n /= nabs.x + nabs.y + nabs.z;
  38. outn.y = n.y * T(0.5) + T(0.5);
  39. outn.x = n.x * T(0.5) + outn.y;
  40. outn.y = n.x * -T(0.5) + outn.y;
  41. outn.z = saturate(n.z * getMaxNumericLimit<T>());
  42. return outn;
  43. }
  44. // See http://johnwhite3d.blogspot.no/2017/10/signed-octahedron-normal-encoding.html
  45. template<typename T>
  46. vector<T, 3> signedOctDecode(vector<T, 3> n)
  47. {
  48. vector<T, 3> outn;
  49. outn.x = n.x - n.y;
  50. outn.y = n.x + n.y - T(1);
  51. outn.z = n.z * T(2) - T(1);
  52. outn.z = outn.z * (1.0 - abs(outn.x) - abs(outn.y));
  53. outn = normalize(outn);
  54. return outn;
  55. }
  56. // Vectorized version. Assumes that v is in [0.0, 1.0]
  57. template<typename T>
  58. U32 packUnorm4x8(const vector<T, 4> value)
  59. {
  60. const UVec4 packed = UVec4(value * T(255));
  61. return packed.x | (packed.y << 8u) | (packed.z << 16u) | (packed.w << 24u);
  62. }
  63. // Reverse of packUnorm4x8
  64. template<typename T>
  65. vector<T, 4> unpackUnorm4x8(const U32 value)
  66. {
  67. const UVec4 packed = UVec4(value & 0xFF, (value >> 8u) & 0xFF, (value >> 16u) & 0xff, value >> 24u);
  68. return vector<T, 4>(packed) / T(255);
  69. }
  70. template<typename T>
  71. U32 packSnorm4x8(vector<T, 4> value)
  72. {
  73. const IVec4 packed = IVec4(round(clamp(value, T(-1), T(1)) * T(127))) & 0xFFu;
  74. return U32(packed.x | (packed.y << 8) | (packed.z << 16) | (packed.w << 24));
  75. }
  76. template<typename T>
  77. vector<T, 4> unpackSnorm4x8(U32 value)
  78. {
  79. const I32 signedValue = (I32)value;
  80. const IVec4 packed = IVec4(signedValue << 24, signedValue << 16, signedValue << 8, signedValue) >> 24;
  81. return clamp(vector<T, 4>(packed) / T(127), T(-1), T(1));
  82. }
  83. // Convert from RGB to YCbCr.
  84. // The RGB should be in [0, 1] and the output YCbCr will be in [0, 1] as well.
  85. template<typename T>
  86. vector<T, 3> rgbToYCbCr(const vector<T, 3> rgb)
  87. {
  88. const T y = dot(rgb, vector<T, 3>(0.299, 0.587, 0.114));
  89. const T cb = T(0.5) + dot(rgb, vector<T, 3>(-0.168736, -0.331264, 0.5));
  90. const T cr = T(0.5) + dot(rgb, vector<T, 3>(0.5, -0.418688, -0.081312));
  91. return vector<T, 3>(y, cb, cr);
  92. }
  93. // Convert the output of rgbToYCbCr back to RGB.
  94. template<typename T>
  95. vector<T, 3> yCbCrToRgb(const vector<T, 3> ycbcr)
  96. {
  97. const T cb = ycbcr.y - T(0.5);
  98. const T cr = ycbcr.z - T(0.5);
  99. const T y = ycbcr.x;
  100. const T r = T(1.402) * cr;
  101. const T g = T(-0.344) * cb - T(0.714) * cr;
  102. const T b = T(1.772) * cb;
  103. return vector<T, 3>(r, g, b) + y;
  104. }
  105. // Pack a Vec2 to a single F32.
  106. // comp should be in [0, 1] and the output will be in [0, 1].
  107. template<typename T>
  108. T packUnorm2ToUnorm1(const vector<T, 2> comp)
  109. {
  110. return dot(round(comp * T(15)), Vec2(T(1) / T(255.0 / 16.0), T(1.0 / 255.0)));
  111. }
  112. // Unpack a single F32 to Vec2. Does the oposite of packUnorm2ToUnorm1.
  113. template<typename T>
  114. vector<T, 2> unpackUnorm1ToUnorm2(T c)
  115. {
  116. #if 1
  117. const T temp = c * T(255.0 / 16.0);
  118. const T a = floor(temp);
  119. const T b = temp - a; // b = fract(temp)
  120. return vector<T, 2>(a, b) * vector<T, 2>(1.0 / 15.0, 16.0 / 15.0);
  121. #else
  122. const U32 temp = U32(c * 255.0);
  123. const U32 a = temp >> 4;
  124. const U32 b = temp & 0xF;
  125. return vector<T, 2>(a, b) / T(15);
  126. #endif
  127. }
  128. // G-Buffer structure
  129. template<typename T>
  130. struct GbufferInfo
  131. {
  132. vector<T, 3> m_diffuse;
  133. vector<T, 3> m_f0; ///< Freshnel at zero angles.
  134. vector<T, 3> m_normal;
  135. vector<T, 3> m_emission;
  136. T m_roughness;
  137. T m_metallic;
  138. T m_subsurface;
  139. Vec2 m_velocity;
  140. };
  141. struct GBufferPixelOut
  142. {
  143. ANKI_RELAXED_PRECISION Vec4 m_rt0 : SV_TARGET0;
  144. ANKI_RELAXED_PRECISION Vec4 m_rt1 : SV_TARGET1;
  145. ANKI_RELAXED_PRECISION Vec4 m_rt2 : SV_TARGET2;
  146. Vec2 m_rt3 : SV_TARGET3;
  147. };
  148. // Populate the G buffer
  149. template<typename T>
  150. GBufferPixelOut packGBuffer(GbufferInfo<T> g)
  151. {
  152. GBufferPixelOut output;
  153. const T packedSubsurfaceMetallic = packUnorm2ToUnorm1(vector<T, 2>(g.m_subsurface, g.m_metallic));
  154. const vector<T, 3> tonemappedEmission = reinhardTonemap(g.m_emission);
  155. output.m_rt0 = vector<T, 4>(g.m_diffuse, packedSubsurfaceMetallic);
  156. output.m_rt1 = vector<T, 4>(g.m_roughness, g.m_f0.x, tonemappedEmission.rb);
  157. const vector<T, 3> encNorm = signedOctEncode(g.m_normal);
  158. output.m_rt2 = vector<T, 4>(tonemappedEmission.g, encNorm);
  159. output.m_rt3 = g.m_velocity;
  160. return output;
  161. }
  162. template<typename T>
  163. vector<T, 3> unpackDiffuseFromGBuffer(vector<T, 4> rt0, T metallic)
  164. {
  165. return rt0.xyz *= T(1) - metallic;
  166. }
  167. template<typename T>
  168. vector<T, 3> unpackNormalFromGBuffer(vector<T, 4> rt2)
  169. {
  170. return signedOctDecode(rt2.yzw);
  171. }
  172. template<typename T>
  173. T unpackRoughnessFromGBuffer(vector<T, 4> rt1, T minRoughness)
  174. {
  175. T r = rt1.x;
  176. if(minRoughness > 0.0)
  177. {
  178. r = r * (T(1) - T(minRoughness)) + T(minRoughness);
  179. }
  180. return r;
  181. }
  182. template<typename T>
  183. T unpackRoughnessFromGBuffer(vector<T, 4> rt1)
  184. {
  185. return unpackRoughnessFromGBuffer<T>(rt1, kMinRoughness);
  186. }
  187. template<typename T>
  188. vector<T, 2> unpackSubsurfaceAndMetallicFromGBuffer(vector<T, 4> rt0)
  189. {
  190. const vector<T, 2> unpackedSubsurfaceMetallic = unpackUnorm1ToUnorm2(rt0.w);
  191. return unpackedSubsurfaceMetallic;
  192. }
  193. // Read part of the G-buffer
  194. template<typename T>
  195. void unpackGBufferNoVelocity(vector<T, 4> rt0, vector<T, 4> rt1, vector<T, 4> rt2, out GbufferInfo<T> g)
  196. {
  197. g.m_diffuse = rt0.xyz;
  198. const vector<T, 2> unpackedSubsurfaceMetallic = unpackUnorm1ToUnorm2(rt0.w);
  199. g.m_subsurface = unpackedSubsurfaceMetallic.x;
  200. g.m_metallic = unpackedSubsurfaceMetallic.y;
  201. g.m_roughness = unpackRoughnessFromGBuffer(rt1);
  202. g.m_f0 = vector<T, 3>(rt1.y, rt1.y, rt1.y);
  203. g.m_emission = invertReinhardTonemap(vector<T, 3>(rt1.z, rt2.x, rt1.w));
  204. g.m_normal = signedOctDecode(rt2.yzw);
  205. g.m_velocity = getMaxNumericLimit<T>(); // Put something random
  206. // Compute reflectance
  207. g.m_f0 = lerp(g.m_f0, g.m_diffuse, g.m_metallic);
  208. // Compute diffuse
  209. g.m_diffuse *= T(1) - g.m_metallic;
  210. }