Skip to content

Commit 7c087b1

Browse files
committed
Fix atmosphere lighting issue for below ground geo
1 parent b59a71a commit 7c087b1

File tree

2 files changed

+16
-15
lines changed

2 files changed

+16
-15
lines changed

crates/bevy_pbr/src/atmosphere/functions.wgsl

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,17 @@ fn calculate_visible_sun_ratio(atmosphere: Atmosphere, r: f32, mu: f32, sun_angu
281281

282282
// TRANSFORM UTILITIES
283283

284+
/// Clamp a position to the planet surface (with a small epsilon) to avoid underground artifacts.
285+
fn clamp_to_surface(atmosphere: Atmosphere, position: vec3<f32>) -> vec3<f32> {
286+
let min_radius = atmosphere.bottom_radius + EPSILON;
287+
let r = length(position);
288+
if r < min_radius {
289+
let up = normalize(position);
290+
return up * min_radius;
291+
}
292+
return position;
293+
}
294+
284295
fn max_atmosphere_distance(r: f32, mu: f32) -> f32 {
285296
let t_top = distance_to_top_atmosphere_boundary(atmosphere, r, mu);
286297
let t_bottom = distance_to_bottom_atmosphere_boundary(r, mu);
@@ -291,18 +302,7 @@ fn max_atmosphere_distance(r: f32, mu: f32) -> f32 {
291302
/// Returns the observer's position in the atmosphere
292303
fn get_view_position() -> vec3<f32> {
293304
var world_pos = view.world_position * settings.scene_units_to_m + vec3(0.0, atmosphere.bottom_radius, 0.0);
294-
295-
// If the camera is underground, clamp it to the ground surface along the local up.
296-
let r = length(world_pos);
297-
// Nudge r above ground to avoid sqrt cancellation, zero-length segments where
298-
// r is equal to bottom_radius, which show up as black pixels
299-
let min_radius = atmosphere.bottom_radius + EPSILON;
300-
if r < min_radius {
301-
let up = normalize(world_pos);
302-
world_pos = up * min_radius;
303-
}
304-
305-
return world_pos;
305+
return clamp_to_surface(atmosphere, world_pos);
306306
}
307307

308308
// We assume the `up` vector at the view position is the y axis, since the world is locally flat/level.

crates/bevy_pbr/src/render/pbr_lighting.wgsl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#import bevy_pbr::{
44
mesh_view_types::POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE,
55
mesh_view_bindings as view_bindings,
6-
atmosphere::functions::calculate_visible_sun_ratio,
6+
atmosphere::functions::{calculate_visible_sun_ratio, clamp_to_surface},
77
atmosphere::bruneton_functions::transmittance_lut_r_mu_to_uv,
88
}
99
#import bevy_render::maths::PI
@@ -862,8 +862,9 @@ color *= (*light).color.rgb * texture_sample;
862862
let O = vec3(0.0, atmosphere.bottom_radius, 0.0);
863863
let P_scaled = P * vec3(view_bindings::atmosphere_data.settings.scene_units_to_m);
864864
let P_as = P_scaled + O;
865-
let r = length(P_as);
866-
let local_up = normalize(P_as);
865+
let P_clamped = clamp_to_surface(atmosphere, P_as);
866+
let r = length(P_clamped);
867+
let local_up = normalize(P_clamped);
867868
let mu_light = dot(L, local_up);
868869

869870
// Sample atmosphere

0 commit comments

Comments
 (0)