PackFunctions.glsl 5.2 KB

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