LumixEngine/data/pipelines/atmo_optical_depth.shd

63 lines
No EOL
1.7 KiB
Text

include "pipelines/common.glsl"
compute_shader [[
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
layout (rg32f, binding = 0) uniform writeonly image2D u_output;
layout(std140, binding = 4) uniform Data {
float u_bot;
float u_top;
float u_distribution_rayleigh;
float u_distribution_mie;
vec4 u_scatter_rayleigh;
vec4 u_scatter_mie;
vec4 u_absorb_mie;
vec4 u_sunlight;
vec4 u_resolution;
};
vec2 ray_sphere_intersect(vec3 r0, vec3 rd, vec3 s0, float sr) {
vec3 s0_r0 = s0 - r0;
float tc = dot(s0_r0, rd);
float d2 = dot(s0_r0, s0_r0) - tc * tc;
float sr2 = sr * sr;
if (d2 > sr2) return vec2(-1);
float td2 = sr2 - d2;
float td = sqrt(td2);
return vec2(tc - td, tc + td);
}
vec3 getTopAtmo(vec3 p, vec3 dir) {
vec2 t = ray_sphere_intersect(p, dir, vec3(0), u_top);
return p + t.y * dir.xyz;
}
float opticalDepth(vec3 a, vec3 b, float distribution) {
float l = length(a - b);
int step_count = 50;
float dens = 0;
vec3 step = (b - a) / step_count;
float step_len = l / step_count;
vec3 p = a;
for (int i = 0; i < step_count; ++i) {
float h = length(p + step * 0.5);
float tmp = exp(min(0, (u_bot - h) / distribution));
dens += step_len * tmp;
p += step;
}
return dens;
}
void main() {
const vec2 xy = gl_GlobalInvocationID.xy / u_resolution.xy;
float angle = xy.x * M_PI * 0.5;
const vec3 p = vec3(0, u_bot + (u_top - u_bot) * xy.y, 0);
const vec3 dir = vec3(sqrt(saturate(1 - xy.x * xy.x)), xy.x, 0);
float rayleigh = opticalDepth(p, getTopAtmo(p, dir), u_distribution_rayleigh);
float mie = opticalDepth(p, getTopAtmo(p, dir), u_distribution_mie);
imageStore(u_output, ivec2(gl_GlobalInvocationID.xy), vec4(rayleigh, mie, 0, 0));
}
]]