@@ -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+
284295fn 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
292303fn 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.
0 commit comments