cubemap_roughness.glsl 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #[compute]
  2. #version 450
  3. VERSION_DEFINES
  4. #define GROUP_SIZE 8
  5. layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in;
  6. layout(set = 0, binding = 0) uniform samplerCube source_cube;
  7. layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
  8. layout(push_constant, binding = 1, std430) uniform Params {
  9. uint face_id;
  10. uint sample_count;
  11. float roughness;
  12. bool use_direct_write;
  13. float face_size;
  14. }
  15. params;
  16. #define M_PI 3.14159265359
  17. vec3 texelCoordToVec(vec2 uv, uint faceID) {
  18. mat3 faceUvVectors[6];
  19. // -x
  20. faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
  21. faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
  22. faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
  23. // +x
  24. faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
  25. faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
  26. faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
  27. // -y
  28. faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
  29. faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
  30. faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
  31. // +y
  32. faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
  33. faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
  34. faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
  35. // -z
  36. faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
  37. faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
  38. faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
  39. // +z
  40. faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
  41. faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
  42. faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
  43. // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
  44. vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
  45. return normalize(result);
  46. }
  47. vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
  48. float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
  49. // Compute distribution direction
  50. float Phi = 2.0 * M_PI * Xi.x;
  51. float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
  52. float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
  53. // Convert to spherical direction
  54. vec3 H;
  55. H.x = SinTheta * cos(Phi);
  56. H.y = SinTheta * sin(Phi);
  57. H.z = CosTheta;
  58. vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
  59. vec3 TangentX = normalize(cross(UpVector, N));
  60. vec3 TangentY = cross(N, TangentX);
  61. // Tangent to world space
  62. return TangentX * H.x + TangentY * H.y + N * H.z;
  63. }
  64. // http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
  65. float GGX(float NdotV, float a) {
  66. float k = a / 2.0;
  67. return NdotV / (NdotV * (1.0 - k) + k);
  68. }
  69. // http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
  70. float G_Smith(float a, float nDotV, float nDotL) {
  71. return GGX(nDotL, a * a) * GGX(nDotV, a * a);
  72. }
  73. float radicalInverse_VdC(uint bits) {
  74. bits = (bits << 16u) | (bits >> 16u);
  75. bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
  76. bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
  77. bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
  78. bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
  79. return float(bits) * 2.3283064365386963e-10; // / 0x100000000
  80. }
  81. vec2 Hammersley(uint i, uint N) {
  82. return vec2(float(i) / float(N), radicalInverse_VdC(i));
  83. }
  84. void main() {
  85. uvec3 id = gl_GlobalInvocationID;
  86. id.z += params.face_id;
  87. vec2 uv = ((vec2(id.xy) * 2.0 + 1.0) / (params.face_size) - 1.0);
  88. vec3 N = texelCoordToVec(uv, id.z);
  89. //vec4 color = color_interp;
  90. if (params.use_direct_write) {
  91. imageStore(dest_cubemap, ivec3(id), vec4(texture(source_cube, N).rgb, 1.0));
  92. } else {
  93. vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
  94. for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) {
  95. vec2 xi = Hammersley(sampleNum, params.sample_count);
  96. vec3 H = ImportanceSampleGGX(xi, params.roughness, N);
  97. vec3 V = N;
  98. vec3 L = (2.0 * dot(V, H) * H - V);
  99. float ndotl = clamp(dot(N, L), 0.0, 1.0);
  100. if (ndotl > 0.0) {
  101. sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
  102. sum.a += ndotl;
  103. }
  104. }
  105. sum /= sum.a;
  106. imageStore(dest_cubemap, ivec3(id), vec4(sum.rgb, 1.0));
  107. }
  108. }