#version 460 layout(set = 0, binding = 0) uniform sampler _EquirectangularSampler; layout(set = 1, binding = 0) uniform texture2D _EquirectangularTexture; layout(set = 2, binding = 1, rgba16f) uniform writeonly restrict imageCube _CubemapImage; const float INV_PI = 0.31830987; const float HALF_INV_PI = 0.15915494; layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; void main() { vec2 size = vec2(imageSize(_CubemapImage).xy); vec2 texCoord = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5)) / size; uint layerIndex = gl_GlobalInvocationID.z; texCoord = texCoord * vec2(2.0) - vec2(1.0); // Map to range [-1, 1] vec3 cubeCoord; if (layerIndex == 0) { // Positive X cubeCoord = vec3(1, -texCoord.y, -texCoord.x); } else if (layerIndex == 1) { // Negative X cubeCoord = vec3(-1, -texCoord.y, texCoord.x); } else if (layerIndex == 2) { // Positive Y cubeCoord = vec3(texCoord.x, 1, texCoord.y); } else if (layerIndex == 3) { // Negative Y cubeCoord = vec3(texCoord.x, -1, -texCoord.y); } else if (layerIndex == 4) { // Positive Z cubeCoord = vec3(texCoord.x, -texCoord.y, 1); } else if (layerIndex == 5) { // Negative Z cubeCoord = vec3(-texCoord.x, -texCoord.y, -1); } vec3 cubeDir = normalize(cubeCoord); float theta = atan(cubeDir.y, cubeDir.x); float phi = asin(cubeDir.z); vec2 equirectCoord = vec2(theta * HALF_INV_PI, phi * INV_PI) + vec2(0.5); vec4 irradiance = texture(sampler2D(_EquirectangularTexture, _EquirectangularSampler), equirectCoord); imageStore(_CubemapImage, ivec3(ivec2(gl_GlobalInvocationID.xy), layerIndex), irradiance); }