Pack.glsl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #ifndef ANKI_SHADERS_PACK_GLSL
  6. #define ANKI_SHADERS_PACK_GLSL
  7. #include "shaders/Common.glsl"
  8. /// Pack 3D normal to 2D vector
  9. /// See the clean code in comments in revision < r467
  10. vec2 packNormal(in vec3 normal)
  11. {
  12. const float SCALE = 1.7777;
  13. float scalar1 = (normal.z + 1.0) * (SCALE * 2.0);
  14. return normal.xy / scalar1 + 0.5;
  15. }
  16. /// Reverse the packNormal
  17. vec3 unpackNormal(in vec2 enc)
  18. {
  19. const float SCALE = 1.7777;
  20. vec2 nn = enc * (2.0 * SCALE) - SCALE;
  21. float 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. #if GL_ES || __VERSION__ < 400
  28. // Vectorized version. See clean one at <= r1048
  29. uint packUnorm4x8(in vec4 v)
  30. {
  31. vec4 a = clamp(v, 0.0, 1.0) * 255.0;
  32. uvec4 b = uvec4(a) << uvec4(0U, 8U, 16U, 24U);
  33. uvec2 c = b.xy | b.zw;
  34. return c.x | c.y;
  35. }
  36. // Vectorized version. See clean one at <= r1048
  37. vec4 unpackUnorm4x8(in highp uint u)
  38. {
  39. uvec4 a = uvec4(u) >> uvec4(0U, 8U, 16U, 24U);
  40. uvec4 b = a & uvec4(0xFFU);
  41. vec4 c = vec4(b);
  42. return c * (1.0 / 255.0);
  43. }
  44. #endif
  45. // Convert from RGB to YCbCr.
  46. // The RGB should be in [0, 1] and the output YCbCr will be in [0, 1] as well.
  47. vec3 rgbToYCbCr(in vec3 rgb)
  48. {
  49. float y = dot(rgb, vec3(0.299, 0.587, 0.114));
  50. float cb = 0.5 + dot(rgb, vec3(-0.168736, -0.331264, 0.5));
  51. float cr = 0.5 + dot(rgb, vec3(0.5, -0.418688, -0.081312));
  52. return vec3(y, cb, cr);
  53. }
  54. // Convert the output of rgbToYCbCr back to RGB.
  55. vec3 yCbCrToRgb(in vec3 ycbcr)
  56. {
  57. float cb = ycbcr.y - 0.5;
  58. float cr = ycbcr.z - 0.5;
  59. float y = ycbcr.x;
  60. float r = 1.402 * cr;
  61. float g = -0.344 * cb - 0.714 * cr;
  62. float b = 1.772 * cb;
  63. return vec3(r, g, b) + y;
  64. }
  65. // Pack a vec2 to a single float.
  66. // comp should be in [0, 1] and the output will be in [0, 1].
  67. float packUnorm2ToUnorm1(in vec2 comp)
  68. {
  69. return dot(round(comp * 15.0), vec2(1.0 / (255.0 / 16.0), 1.0 / 255.0));
  70. }
  71. // Unpack a single float to vec2. Does the oposite of packUnorm2ToUnorm1.
  72. vec2 unpackUnorm1ToUnorm2(in float c)
  73. {
  74. #if 1
  75. float temp = c * (255.0 / 16.0);
  76. float a = floor(temp);
  77. float b = temp - a; // b = fract(temp)
  78. return vec2(a, b) * vec2(1.0 / 15.0, 16.0 / 15.0);
  79. #else
  80. uint temp = uint(c * 255.0);
  81. uint a = temp >> 4;
  82. uint b = temp & 0xF;
  83. return vec2(a, b) / 15.0;
  84. #endif
  85. }
  86. // Max emission. Keep as low as possible
  87. const float MAX_EMISSION = 10.0;
  88. // G-Buffer structure
  89. struct GbufferInfo
  90. {
  91. vec3 diffuse;
  92. vec3 specular;
  93. vec3 normal;
  94. float roughness;
  95. float metallic;
  96. float subsurface;
  97. float emission;
  98. };
  99. // Populate the G buffer
  100. void writeGBuffer(in GbufferInfo g, out vec4 rt0, out vec4 rt1, out vec4 rt2)
  101. {
  102. float comp = packUnorm2ToUnorm1(vec2(g.subsurface, g.metallic));
  103. rt0 = vec4(g.diffuse, comp);
  104. rt1 = vec4(g.specular, g.roughness);
  105. rt2 = vec4(g.normal * 0.5 + 0.5, g.emission / MAX_EMISSION);
  106. }
  107. // Read from G-buffer
  108. void readNormalFromGBuffer(in sampler2D rt2, in vec2 uv, out vec3 normal)
  109. {
  110. normal = texture(rt2, uv).rgb * 2.0 - 1.0;
  111. }
  112. // Read from the G buffer
  113. void readGBuffer(in sampler2D rt0, in sampler2D rt1, in sampler2D rt2, in vec2 uv, in float lod, out GbufferInfo g)
  114. {
  115. vec4 comp = textureLod(rt0, uv, lod);
  116. g.diffuse = comp.xyz;
  117. vec2 comp2 = unpackUnorm1ToUnorm2(comp.w);
  118. g.subsurface = comp2.x;
  119. g.metallic = comp2.y;
  120. comp = textureLod(rt1, uv, lod);
  121. g.specular = comp.xyz;
  122. g.roughness = comp.w;
  123. comp = textureLod(rt2, uv, lod);
  124. g.normal = comp.xyz * 2.0 - 1.0;
  125. g.emission = comp.w * MAX_EMISSION;
  126. // Fix values
  127. g.specular = mix(g.specular, g.diffuse, g.metallic);
  128. g.diffuse *= (1.0 - g.metallic);
  129. }
  130. #endif