Created
July 6, 2020 20:45
-
-
Save NotAPenguin0/9e80433acf6b15ab6c1acaa6f252713d to your computer and use it in GitHub Desktop.
irradiance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #version 450 | |
| layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; | |
| layout (binding = 0) uniform samplerCube cube_map; | |
| layout (binding = 1, rgba32f) uniform imageCube irradiance_map; | |
| vec3 view_pos = vec3(0, 0, 0); | |
| vec3 view_target[6] = { | |
| vec3(1, 0, 0), | |
| vec3(-1, 0, 0), | |
| vec3(0, -1, 0), | |
| vec3(0, 1, 0), | |
| vec3(0, 0, 1), | |
| vec3(0, 0, -1) | |
| }; | |
| vec3 view_up[6] = { | |
| vec3(0, 1, 0), | |
| vec3(0, 1, 0), | |
| vec3(0, 0, 1), // +Y | |
| vec3(0, 0, -1), // -Y | |
| vec3(0, 1, 0), | |
| vec3(0, 1, 0) | |
| }; | |
| mat4 look_at(vec3 pos, vec3 target, vec3 world_up) { | |
| vec3 fwd = normalize(target - pos); | |
| vec3 right = cross(world_up, fwd); | |
| vec3 up = cross(fwd, right); | |
| return mat4(vec4(right, 0), vec4(up, 0), vec4(fwd, 0), vec4(pos, 1)); | |
| } | |
| // Remaps uv coordinates to a position in range [-1, 1] | |
| vec2 uv_to_quad_pos(vec2 uv) { | |
| return uv * 2.0f - 1.0f; | |
| } | |
| vec3 to_local_direction(vec2 uv, int face) { | |
| mat4 view = look_at(view_pos, view_target[face], view_up[face]); | |
| return (view * vec4(uv_to_quad_pos(uv), 1, 1)).xyz; | |
| } | |
| #define PI 3.14159265359 | |
| vec3 calculate_irradiance(vec3 local_direction) { | |
| vec3 normal = normalize(vec3(local_direction.x, -local_direction.y, local_direction.z)); | |
| vec3 irradiance = vec3(0.0); | |
| vec3 up = vec3(0.0, 1.0, 0.0); | |
| vec3 right = cross(up, normal); | |
| up = cross(normal, right); | |
| float sample_delta = 0.025; | |
| float n_samples = 0.0; | |
| for(float phi = 0.0; phi < 2.0 * PI; phi += sample_delta) { | |
| for(float theta = 0.0; theta < 0.5 * PI; theta += sample_delta) { | |
| // spherical to cartesian (in tangent space) | |
| vec3 tangent_sample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); | |
| // tangent space to world | |
| vec3 sample_vec = tangent_sample.x * right + tangent_sample.y * up + tangent_sample.z * normal; | |
| irradiance += texture(cube_map, sample_vec).rgb * cos(theta) * sin(theta); | |
| n_samples++; | |
| } | |
| } | |
| irradiance = PI * irradiance * (1.0 / float(n_samples)); | |
| return irradiance; | |
| } | |
| void main() { | |
| int face_size = imageSize(irradiance_map).x; | |
| vec2 uv = vec2(gl_GlobalInvocationID.xy) / float(face_size); | |
| vec3 local_direction = normalize(to_local_direction(uv, int(gl_GlobalInvocationID.z))); | |
| vec4 color = vec4(calculate_irradiance(local_direction), 1); | |
| ivec3 cube_texels = ivec3(gl_GlobalInvocationID.xyz); | |
| imageStore(irradiance_map, cube_texels, color); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment