83 lines
No EOL
2.7 KiB
Text
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));
|
|
}
|
|
]] |