Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atmosphere LUT parameterization improvements #17555

Merged
merged 10 commits into from
Feb 3, 2025
11 changes: 4 additions & 7 deletions crates/bevy_pbr/src/atmosphere/aerial_view_lut.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ fn main(@builtin(global_invocation_id) idx: vec3<u32>) {

for (var slice_i: u32 = 0; slice_i < settings.aerial_view_lut_size.z; slice_i++) {
for (var step_i: u32 = 0; step_i < settings.aerial_view_lut_samples; step_i++) {
// Offset by -0.5 to align sampling position with slice boundaries,
// since each texel stores the integral over its entire slice
var t_i = t_max * (f32(slice_i) - 0.5 + ((f32(step_i) + MIDPOINT_RATIO) / f32(settings.aerial_view_lut_samples))) / f32(settings.aerial_view_lut_size.z);
t_i = max(t_i, 0.0);
let t_i = t_max * (f32(slice_i) + ((f32(step_i) + MIDPOINT_RATIO) / f32(settings.aerial_view_lut_samples))) / f32(settings.aerial_view_lut_size.z);
let dt = (t_i - prev_t);
prev_t = t_i;

Expand All @@ -61,9 +58,9 @@ fn main(@builtin(global_invocation_id) idx: vec3<u32>) {
// We only have one channel to store transmittance, so we store the mean
let mean_transmittance = (throughput.r + throughput.g + throughput.b) / 3.0;

// Store the optical depth so that it can be linearly sampled between slices
let optical_depth = -log(max(mean_transmittance, 1e-6)); // Avoid log(0)
// Store in log space to allow linear interpolation of exponential values between slices
let log_transmittance = -log(max(mean_transmittance, 1e-6)); // Avoid log(0)
let log_inscattering = log(max(total_inscattering, vec3(1e-6)));
textureStore(aerial_view_lut_out, vec3(vec2<u32>(idx.xy), slice_i), vec4(log_inscattering, optical_depth));
textureStore(aerial_view_lut_out, vec3(vec2<u32>(idx.xy), slice_i), vec4(log_inscattering, log_transmittance));
}
}
12 changes: 10 additions & 2 deletions crates/bevy_pbr/src/atmosphere/functions.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,18 @@ fn sample_sky_view_lut(r: f32, ray_dir_as: vec3<f32>) -> vec3<f32> {
fn sample_aerial_view_lut(uv: vec2<f32>, depth: f32) -> vec4<f32> {
let view_pos = view.view_from_clip * vec4(uv_to_ndc(uv), depth, 1.0);
let dist = length(view_pos.xyz / view_pos.w) * settings.scene_units_to_m;
let uvw = vec3(uv, dist / settings.aerial_view_lut_max_distance);
let t_max = settings.aerial_view_lut_max_distance;
let num_slices = f32(settings.aerial_view_lut_size.z);
// Offset the W coordinate by -0.5 over the max distance in order to
// align sampling position with slice boundaries, since each texel
// stores the integral over its entire slice
let uvw = vec3(uv, saturate(dist / t_max - 0.5 / num_slices));
let sample = textureSampleLevel(aerial_view_lut, aerial_view_lut_sampler, uvw, 0.0);
// Treat the first slice specially since there is 0 scattering at the camera
let delta_slice = t_max / num_slices;
let fade = saturate(dist / delta_slice);
// Recover the values from log space
return vec4(exp(sample.rgb), exp(-sample.a));
return vec4(exp(sample.rgb) * fade, exp(sample.a) * fade);
}

// PHASE FUNCTIONS
Expand Down
Loading