PackFunctions.glsl 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright (C) 2009-2022, 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.glsl>
  7. #include <AnKi/Shaders/TonemappingFunctions.glsl>
  8. /// Pack 3D normal to 2D vector
  9. /// See the clean code in comments in revision < r467
  10. Vec2 packNormal(const Vec3 normal)
  11. {
  12. const F32 SCALE = 1.7777;
  13. const F32 scalar1 = (normal.z + 1.0) * (SCALE * 2.0);
  14. return normal.xy / scalar1 + 0.5;
  15. }
  16. /// Reverse the packNormal
  17. Vec3 unpackNormal(const Vec2 enc)
  18. {
  19. const F32 SCALE = 1.7777;
  20. const Vec2 nn = enc * (2.0 * SCALE) - SCALE;
  21. const F32 g = 2.0 / (dot(nn.xy, nn.xy) + 1.0);
  22. Vec3 normal;
  23. normal.xy = g * nn.xy;
  24. normal.z = g - 1.0;
  25. return normalize(normal);
  26. }
  27. // See http://johnwhite3d.blogspot.no/2017/10/signed-octahedron-normal-encoding.html
  28. // Result in [0.0, 1.0]
  29. Vec3 signedOctEncode(Vec3 n)
  30. {
  31. Vec3 outn;
  32. const Vec3 nabs = abs(n);
  33. n /= nabs.x + nabs.y + nabs.z;
  34. outn.y = n.y * 0.5 + 0.5;
  35. outn.x = n.x * 0.5 + outn.y;
  36. outn.y = n.x * -0.5 + outn.y;
  37. outn.z = saturate(n.z * MAX_F32);
  38. return outn;
  39. }
  40. // See http://johnwhite3d.blogspot.no/2017/10/signed-octahedron-normal-encoding.html
  41. Vec3 signedOctDecode(const Vec3 n)
  42. {
  43. Vec3 outn;
  44. outn.x = n.x - n.y;
  45. outn.y = n.x + n.y - 1.0;
  46. outn.z = n.z * 2.0 - 1.0;
  47. outn.z = outn.z * (1.0 - abs(outn.x) - abs(outn.y));
  48. outn = normalize(outn);
  49. return outn;
  50. }
  51. // Vectorized version. Assumes that v is in [0.0, 1.0]
  52. U32 newPackUnorm4x8(const Vec4 v)
  53. {
  54. Vec4 a = v * 255.0;
  55. UVec4 b = UVec4(a) << UVec4(0u, 8u, 16u, 24u);
  56. UVec2 c = b.xy | b.zw;
  57. return c.x | c.y;
  58. }
  59. // Vectorized version
  60. Vec4 newUnpackUnorm4x8(const U32 u)
  61. {
  62. const UVec4 a = UVec4(u) >> UVec4(0u, 8u, 16u, 24u);
  63. const UVec4 b = a & UVec4(0xFFu);
  64. const Vec4 c = Vec4(b);
  65. return c * (1.0 / 255.0);
  66. }
  67. // Convert from RGB to YCbCr.
  68. // The RGB should be in [0, 1] and the output YCbCr will be in [0, 1] as well.
  69. Vec3 rgbToYCbCr(const Vec3 rgb)
  70. {
  71. const F32 y = dot(rgb, Vec3(0.299, 0.587, 0.114));
  72. const F32 cb = 0.5 + dot(rgb, Vec3(-0.168736, -0.331264, 0.5));
  73. const F32 cr = 0.5 + dot(rgb, Vec3(0.5, -0.418688, -0.081312));
  74. return Vec3(y, cb, cr);
  75. }
  76. // Convert the output of rgbToYCbCr back to RGB.
  77. Vec3 yCbCrToRgb(const Vec3 ycbcr)
  78. {
  79. const F32 cb = ycbcr.y - 0.5;
  80. const F32 cr = ycbcr.z - 0.5;
  81. const F32 y = ycbcr.x;
  82. const F32 r = 1.402 * cr;
  83. const F32 g = -0.344 * cb - 0.714 * cr;
  84. const F32 b = 1.772 * cb;
  85. return Vec3(r, g, b) + y;
  86. }
  87. // Pack a Vec2 to a single F32.
  88. // comp should be in [0, 1] and the output will be in [0, 1].
  89. F32 packUnorm2ToUnorm1(const Vec2 comp)
  90. {
  91. return dot(round(comp * 15.0), Vec2(1.0 / (255.0 / 16.0), 1.0 / 255.0));
  92. }
  93. // Unpack a single F32 to Vec2. Does the oposite of packUnorm2ToUnorm1.
  94. Vec2 unpackUnorm1ToUnorm2(F32 c)
  95. {
  96. #if 1
  97. const F32 temp = c * (255.0 / 16.0);
  98. const F32 a = floor(temp);
  99. const F32 b = temp - a; // b = fract(temp)
  100. return Vec2(a, b) * Vec2(1.0 / 15.0, 16.0 / 15.0);
  101. #else
  102. const U32 temp = U32(c * 255.0);
  103. const U32 a = temp >> 4;
  104. const U32 b = temp & 0xF;
  105. return Vec2(a, b) / 15.0;
  106. #endif
  107. }
  108. const ANKI_RP F32 ABSOLUTE_MAX_EMISSION = 1024.0;
  109. #if !defined(MAX_EMISSION)
  110. const ANKI_RP F32 MAX_EMISSION = 30.0; // Max emission. Keep as low as possible and less than ABSOLUTE_MAX_EMISSION
  111. #endif
  112. // Round the MAX_EMISSION to fit a U8_UNORM
  113. const ANKI_RP F32 FIXED_MAX_EMISSION =
  114. F32(U32(MAX_EMISSION / ABSOLUTE_MAX_EMISSION * 255.0)) / 255.0 * ABSOLUTE_MAX_EMISSION;
  115. const ANKI_RP F32 MIN_ROUGHNESS = 0.05;
  116. // G-Buffer structure
  117. struct GbufferInfo
  118. {
  119. ANKI_RP Vec3 m_diffuse;
  120. ANKI_RP Vec3 m_f0; ///< Freshnel at zero angles.
  121. ANKI_RP Vec3 m_normal;
  122. ANKI_RP F32 m_roughness;
  123. ANKI_RP F32 m_metallic;
  124. ANKI_RP F32 m_subsurface;
  125. ANKI_RP Vec3 m_emission;
  126. Vec2 m_velocity;
  127. };
  128. // Populate the G buffer
  129. void packGBuffer(GbufferInfo g, out Vec4 rt0, out Vec4 rt1, out Vec4 rt2, out Vec2 rt3)
  130. {
  131. const F32 packedSubsurfaceMetallic = packUnorm2ToUnorm1(Vec2(g.m_subsurface, g.m_metallic));
  132. const Vec3 tonemappedEmission = invertReinhardTonemap(g.m_emission);
  133. rt0 = Vec4(g.m_diffuse, packedSubsurfaceMetallic);
  134. rt1 = Vec4(g.m_roughness, g.m_f0.x, tonemappedEmission.rb);
  135. const Vec3 encNorm = signedOctEncode(g.m_normal);
  136. rt2 = Vec4(tonemappedEmission.g, encNorm);
  137. rt3 = g.m_velocity;
  138. }
  139. ANKI_RP Vec3 unpackDiffuseFromGBuffer(ANKI_RP Vec4 rt0, ANKI_RP F32 metallic)
  140. {
  141. return rt0.xyz *= 1.0 - metallic;
  142. }
  143. ANKI_RP Vec3 unpackNormalFromGBuffer(ANKI_RP Vec4 rt2)
  144. {
  145. return signedOctDecode(rt2.yzw);
  146. }
  147. ANKI_RP F32 unpackRoughnessFromGBuffer(ANKI_RP Vec4 rt1)
  148. {
  149. ANKI_RP F32 r = rt1.x;
  150. r = r * (1.0 - MIN_ROUGHNESS) + MIN_ROUGHNESS;
  151. return r;
  152. }
  153. // Read part of the G-buffer
  154. void unpackGBufferNoVelocity(ANKI_RP Vec4 rt0, ANKI_RP Vec4 rt1, ANKI_RP Vec4 rt2, out GbufferInfo g)
  155. {
  156. g.m_diffuse = rt0.xyz;
  157. const Vec2 unpackedSubsurfaceMetallic = unpackUnorm1ToUnorm2(rt0.w);
  158. g.m_subsurface = unpackedSubsurfaceMetallic.x;
  159. g.m_metallic = unpackedSubsurfaceMetallic.y;
  160. g.m_roughness = unpackRoughnessFromGBuffer(rt1);
  161. g.m_f0 = Vec3(rt1.y);
  162. g.m_emission = invertReinhardTonemap(Vec3(rt1.z, rt2.x, rt1.w));
  163. g.m_normal = signedOctDecode(rt2.yzw);
  164. g.m_velocity = Vec2(MAX_F32); // Put something random
  165. // Compute reflectance
  166. g.m_f0 = mix(g.m_f0, g.m_diffuse, g.m_metallic);
  167. // Compute diffuse
  168. g.m_diffuse *= 1.0 - g.m_metallic;
  169. }