LumixEngine/data/pipelines/atmo_scattering.shd
2020-10-28 21:33:02 +01:00

83 lines
No EOL
2.7 KiB
Text

include "pipelines/common.glsl"
compute_shader [[
// https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/s2016-pbs-frostbite-sky-clouds-new.pdf
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
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;
};
layout (rgba32f, binding = 0) uniform writeonly image2D u_inscatter;
layout (binding = 1) uniform sampler2D u_optical_depth;
float getOptDepthY(vec3 position) {
return saturate((length(position) - u_bot) / (u_top - u_bot));
}
vec4 sampleOpticalDepth(vec3 dir, vec3 up, float height) {
return texture(u_optical_depth, vec2(saturate(dot(dir, up)), height));
}
void main()
{
const vec3 extinction_rayleigh = u_scatter_rayleigh.rgb;
const vec3 extinction_mie = u_scatter_mie.rgb + vec3(4.4e-6);
float zenith_angle = gl_GlobalInvocationID.y / u_resolution.y * M_PI * 0.5;
vec3 eyedir = vec3(cos(zenith_angle), sin(zenith_angle), 0);
vec3 campos = vec3(0, u_bot, 0) + Global.camera_world_pos.xyz;
vec2 atmo_isect = raySphereIntersect(campos, eyedir, vec3(0), u_top);
if (atmo_isect.y < 0) {
imageStore(u_inscatter, ivec2(gl_GlobalInvocationID.xy), vec4(0));
return;
}
atmo_isect.x = max(0, atmo_isect.x);
vec3 rayleigh = vec3(0);
vec3 mie = vec3(0);
vec3 p = campos;//+ atmo_isect.x * eyedir;
const int STEP_COUNT = 50;
float dist = atmo_isect.y - atmo_isect.x;
dist = gl_GlobalInvocationID.x == uint(u_resolution.x) - 1
? dist
: min(gl_GlobalInvocationID.x / u_resolution.x * 50e3, dist);
const float step_len = dist / STEP_COUNT;
const vec3 step = step_len * eyedir;
float height_b = getOptDepthY(campos);
vec4 depth_b = sampleOpticalDepth(eyedir, vec3(0, 1, 0), height_b);
const float cos_light_up = saturate(Global.light_dir.y);
const float cos_eye_up = saturate(eyedir.y);
for (int i = 0; i < STEP_COUNT; ++i) {
float height_a = getOptDepthY(p);
vec3 up = normalize(p);
vec4 depth_a = sampleOpticalDepth(Global.light_dir.xyz, up, height_a);
vec4 depth_c = sampleOpticalDepth(eyedir, up, height_a);
vec3 total_transmittance =
exp((-depth_a.x - depth_b.x + depth_c.x) * extinction_rayleigh)
* exp((-depth_a.y - depth_b.y + depth_c.y) * extinction_mie);
float h = min(0, u_bot - length(p));
rayleigh += step_len * exp(h / u_distribution_rayleigh) * total_transmittance;
mie += step_len * exp(h / u_distribution_mie) * total_transmittance;
p += step;
}
imageStore(u_inscatter, ivec2(gl_GlobalInvocationID.xy), vec4(rayleigh, mie.b));
}
]]