# Objective - Fix the atmosphere LUT parameterization in the aerial -view and sky-view LUTs - Correct the light accumulation according to a ray-marched reference - Avoid negative values of the sun disk illuminance when the sun disk is below the horizon ## Solution - Adding a Newton's method iteration to `fast_sqrt` function - Switched to using `fast_acos_4` for better precision of the sun angle towards the horizon (view mu angle = 0) - Simplified the function for mapping to and from the Sky View UV coordinates by removing an if statement and correctly apply the method proposed by the [Hillarie paper](https://sebh.github.io/publications/egsr2020.pdf) detailed in section 5.3 and 5.4. - Replaced the `ray_dir_ws.y` term with a shadow factor in the `sample_sun_illuminance` function that correctly approximates the sun disk occluded by the earth from any view point ## Testing - Ran the atmosphere and SSAO examples to make sure the shaders still compile and run as expected. --- ## Showcase <img width="1151" alt="showcase-img" src="https://github.com/user-attachments/assets/de875533-42bd-41f9-9fd0-d7cc57d6e51c" /> --------- Co-authored-by: Emerson Coskey <emerson@coskey.dev>
49 lines
1.9 KiB
WebGPU Shading Language
49 lines
1.9 KiB
WebGPU Shading Language
#import bevy_pbr::atmosphere::{
|
|
types::{Atmosphere, AtmosphereSettings},
|
|
bindings::{settings, atmosphere},
|
|
functions::{AtmosphereSample, sample_atmosphere, get_local_r, max_atmosphere_distance, MIDPOINT_RATIO},
|
|
bruneton_functions::{transmittance_lut_uv_to_r_mu, distance_to_bottom_atmosphere_boundary, distance_to_top_atmosphere_boundary},
|
|
}
|
|
|
|
|
|
#import bevy_core_pipeline::fullscreen_vertex_shader::FullscreenVertexOutput
|
|
|
|
@group(0) @binding(13) var transmittance_lut_out: texture_storage_2d<rgba16float, write>;
|
|
|
|
@compute
|
|
@workgroup_size(16, 16, 1)
|
|
fn main(@builtin(global_invocation_id) idx: vec3<u32>) {
|
|
let uv: vec2<f32> = (vec2<f32>(idx.xy) + 0.5) / vec2<f32>(settings.transmittance_lut_size);
|
|
// map UV coordinates to view height (r) and zenith cos angle (mu)
|
|
let r_mu = transmittance_lut_uv_to_r_mu(uv);
|
|
|
|
// compute the optical depth from view height r to the top atmosphere boundary
|
|
let optical_depth = ray_optical_depth(r_mu.x, r_mu.y, settings.transmittance_lut_samples);
|
|
let transmittance = exp(-optical_depth);
|
|
|
|
textureStore(transmittance_lut_out, idx.xy, vec4(transmittance, 1.0));
|
|
}
|
|
|
|
/// Compute the optical depth of the atmosphere from the ground to the top atmosphere boundary
|
|
/// at a given view height (r) and zenith cos angle (mu)
|
|
fn ray_optical_depth(r: f32, mu: f32, sample_count: u32) -> vec3<f32> {
|
|
let t_max = max_atmosphere_distance(r, mu);
|
|
var optical_depth = vec3<f32>(0.0f);
|
|
var prev_t = 0.0f;
|
|
|
|
for (var i = 0u; i < sample_count; i++) {
|
|
let t_i = t_max * (f32(i) + MIDPOINT_RATIO) / f32(sample_count);
|
|
let dt = t_i - prev_t;
|
|
prev_t = t_i;
|
|
|
|
let r_i = get_local_r(r, mu, t_i);
|
|
|
|
let atmosphere_sample = sample_atmosphere(r_i);
|
|
let sample_optical_depth = atmosphere_sample.extinction * dt;
|
|
|
|
optical_depth += sample_optical_depth;
|
|
}
|
|
|
|
return optical_depth;
|
|
}
|