52 lines
1.8 KiB
GLSL
52 lines
1.8 KiB
GLSL
#version 450
|
|
#pragma shader_stage(compute)
|
|
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
|
|
|
layout(binding = 0) uniform samplerCube environmentMap;
|
|
layout(binding = 1, rgba16f) uniform writeonly image2DArray irradianceMap;
|
|
|
|
const float PI = 3.14159265359;
|
|
|
|
vec3 getDirection(uint face, vec2 uv) {
|
|
vec3 dir;
|
|
uv = uv * 2.0 - 1.0;
|
|
switch(face) {
|
|
case 0: dir = vec3( 1.0, -uv.y, -uv.x); break; // POSITIVE_X
|
|
case 1: dir = vec3(-1.0, -uv.y, uv.x); break; // NEGATIVE_X
|
|
case 2: dir = vec3( uv.x, 1.0, uv.y); break; // POSITIVE_Y
|
|
case 3: dir = vec3( uv.x, -1.0, -uv.y); break; // NEGATIVE_Y
|
|
case 4: dir = vec3( uv.x, -uv.y, 1.0); break; // POSITIVE_Z
|
|
case 5: dir = vec3(-uv.x, -uv.y, -1.0); break; // NEGATIVE_Z
|
|
}
|
|
return normalize(dir);
|
|
}
|
|
|
|
void main() {
|
|
ivec3 storePos = ivec3(gl_GlobalInvocationID);
|
|
ivec2 size = imageSize(irradianceMap).xy;
|
|
if (storePos.x >= size.x || storePos.y >= size.y) return;
|
|
|
|
vec2 uv = (vec2(storePos.xy) + 0.5) / vec2(size);
|
|
vec3 normal = getDirection(storePos.z, uv);
|
|
|
|
vec3 irradiance = vec3(0.0);
|
|
vec3 up = vec3(0.0, 1.0, 0.0);
|
|
vec3 right = normalize(cross(up, normal));
|
|
up = normalize(cross(normal, right));
|
|
|
|
float sampleDelta = 0.025;
|
|
float nrSamples = 0.0;
|
|
|
|
for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) {
|
|
for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) {
|
|
vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
|
|
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal;
|
|
|
|
irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
|
|
nrSamples++;
|
|
}
|
|
}
|
|
irradiance = PI * irradiance * (1.0 / float(nrSamples));
|
|
|
|
imageStore(irradianceMap, storePos, vec4(irradiance, 1.0));
|
|
} |