From 394390a4d6ffa1d8878d863b3c559416c56df4e5 Mon Sep 17 00:00:00 2001 From: hut Date: Mon, 1 Apr 2024 03:12:59 +0200 Subject: [PATCH] more realistic ring density function --- assets/shaders/jupiters_rings.wgsl | 148 ++++++++++++++++++++++++++++- src/defs.txt | 2 +- src/world.rs | 2 +- 3 files changed, 146 insertions(+), 6 deletions(-) diff --git a/assets/shaders/jupiters_rings.wgsl b/assets/shaders/jupiters_rings.wgsl index 6f4b573..be61819 100644 --- a/assets/shaders/jupiters_rings.wgsl +++ b/assets/shaders/jupiters_rings.wgsl @@ -6,15 +6,155 @@ @group(2) @binding(0) var ring_radius: f32; @group(2) @binding(1) var jupiter_radius: f32; +const jupiter_radius_Mm: f32 = 71.492; + +//fn ring_density(r: f32) -> f32 { +// // r is in terms of megameters. +//// if r < 92 { +//// return 0.0; +//// } +//// if r > 226 { +//// return 0.0; +//// } +// +// let B0: f32 = 1.0; +// let d0: f32 = 71492.0; +// let lambda: f32 = 5000.0; +// let alpha: f32 = 0.1; +// let beta: f32 = 0.001; +// let dist = r * 400; +// +// let brightness: f32 = B0 * exp(-(dist - d0) / lambda) * (1.0 + alpha * sin(beta * (dist - d0))); +// return brightness * 1; +//} + +//fn ring_density(r: f32) -> f32 { +// if r < jupiter_radius_Mm { +// return 0.0; +// } +// if r > jupiter_radius_Mm * 3 { +// return 0.0; +// } +// let radius = (r - jupiter_radius_Mm) / (jupiter_radius_Mm * 2) + 1; +// // Constants representing the approximate normalized start, peak, and end radii of the rings +// let halo_start: f32 = 1.1; +// let halo_peak: f32 = 1.2; +// let halo_end: f32 = 1.3; +// +// let main_start: f32 = 1.4; +// let main_peak: f32 = 1.5; +// let main_end: f32 = 1.6; +// +// let gossamer_start: f32 = 1.7; +// let gossamer_peak: f32 = 1.8; +// let gossamer_end: f32 = 1.9; +// +// // Piecewise linear function for density approximation +// if (radius >= halo_start && radius < halo_peak) { +// return 1.0; +// //return (radius - halo_start) / (halo_peak - halo_start); +// } else if (radius >= halo_peak && radius <= halo_end) { +// return 1.0 - (radius - halo_peak) / (halo_end - halo_peak); +// } else if (radius >= main_start && radius < main_peak) { +// return (radius - main_start) / (main_peak - main_start); +// } else if (radius >= main_peak && radius <= main_end) { +// return 1.0 - (radius - main_peak) / (main_end - main_peak); +// } else if (radius >= gossamer_start && radius < gossamer_peak) { +// return (radius - gossamer_start) / (gossamer_peak - gossamer_start); +// } else if (radius >= gossamer_peak && radius <= gossamer_end) { +// return 1.0 - (radius - gossamer_peak) / (gossamer_end - gossamer_peak); +// } +// +// return 0.0; // Outside of rings, density is 0 +//} + +//fn ring_density(radius: f32) -> f32 { +// // Define key radii for Jupiter's rings and gaps +// let inner_radius: f32 = 1.806e5; // Inner boundary of the Halo ring +// let halo_main_gap: f32 = 1.22e5; // Gap between Halo and Main rings +// let main_amalthea_gap: f32 = 1.8e5; // Gap between Main and Amalthea Gossamer ring +// let amalthea_thebe_gap: f32 = 2.24e5; // Gap between Amalthea and Thebe Gossamer rings +// let outer_radius: f32 = 2.2e5; // Outer boundary of Thebe Gossamer ring +// let metis_notch_inner: f32 = 1.28e5; // Inner boundary of Metis notch +// let metis_notch_outer: f32 = 1.29e5; // Outer boundary of Metis notch +// +// // Density function +// if radius > outer_radius { +// return 0.0; // Beyond rings, density is zero +// } else if radius > metis_notch_inner && radius < metis_notch_outer { +// return 0.2; // Notch at the orbit of Metis +// } else if radius > halo_main_gap && radius < main_amalthea_gap { +// return 1.0; // Highest density in Main ring +// } else if radius > amalthea_thebe_gap { +// return 0.5; // Lower density in Thebe Gossamer ring +// } else { +// return 0.75; // Moderate density in other areas +// } +//} + +// Smooth step function for edge smoothing +fn smooth_edge(start: f32, end: f32, value: f32, smooth_factor: f32) -> f32 { + var x = ((value - start) / (end - start)); + if x < 0 { + return 0.0; + } + if x > 1 { + return 1.0; + } + return pow(x, smooth_factor) * (3.0 - 2.0 * x); +} +fn ring_density(radius: f32) -> f32 { + let halo_inner: f32 = 92.0; + let halo_outer: f32 = 122.5; + let main_inner: f32 = 122.5; + let main_outer: f32 = 129.0; + let amalthea_inner: f32 = 129.0; + let amalthea_outer: f32 = 182.0; + let thebe_inner: f32 = 129.0; + let thebe_outer: f32 = 229.0; + let metis_notch_center: f32 = 128.0; + let metis_notch_width: f32 = 0.6; + + let halo_brightness: f32 = 0.4; + let main_brightness: f32 = 1.0; + let almathea_brightness: f32 = 0.3; + let thebe_brightness: f32 = 0.2; + + let smooth_factor: f32 = 2.0; // Smooth edges + + if radius < halo_inner || radius > thebe_outer { + return 0.0; + } else if radius >= halo_inner && radius <= halo_outer { + return halo_brightness * smooth_edge(halo_inner, halo_outer, radius, smooth_factor); + } else if radius >= main_inner && radius <= main_outer { + var metis_notch_effect = 1.0; + if radius > metis_notch_center - metis_notch_width * 0.5 && radius < metis_notch_center + metis_notch_width * 0.5 { + metis_notch_effect = 0.5 * (1.0 - smooth_edge(metis_notch_center - metis_notch_width * 0.5, metis_notch_center + metis_notch_width * 0.5, radius, smooth_factor)); + } + return main_brightness * metis_notch_effect * smooth_edge(main_inner, main_outer, radius, smooth_factor); + } else if radius >= amalthea_inner && radius <= amalthea_outer { + return almathea_brightness * smooth_edge(amalthea_inner, amalthea_outer, radius, smooth_factor); + } else if radius >= thebe_inner && radius <= thebe_outer { + return thebe_brightness * smooth_edge(thebe_inner, thebe_outer, radius, smooth_factor); + } + return 0.0; +} + @fragment fn fragment(in: VertexOutput) -> @location(0) vec4 { let jupiter_percent = jupiter_radius / ring_radius; let color = vec3(0.3, 0.3, 0.3); - var alpha = 0.01; - let r = distance(in.uv, vec2(0.5)); + var alpha = 0.04; + let r_uv = 2 * distance(in.uv, vec2(0.5)); + let r = r_uv * ring_radius / jupiter_radius * jupiter_radius_Mm; - alpha *= (sin(11*r / 0.71 * 3.1415) + 1) / 2; - alpha *= (cos(r / 0.72 * 3.1415) + 1) / 2; + alpha *= ring_density(r); + if alpha <= 0.0 { + return vec4(color, alpha); + } + + //alpha *= (sin(11*r / 0.71 * 3.1415) + 1) / 2; + //alpha *= (cos(r / 0.72 * 3.1415) + 1) / 2; if in.uv[0] < 0.5 { let dist = (0.5 - in.uv[0]) * 2.0; // 0.0=jupiter's center, 1.0=edge of the ring diff --git a/src/defs.txt b/src/defs.txt index b61f6f8..a437be0 100644 --- a/src/defs.txt +++ b/src/defs.txt @@ -1,4 +1,4 @@ -actor 0 0 0 suit +actor -800000 800000 0 suit player yes mass 200.0 scale 1 diff --git a/src/world.rs b/src/world.rs index 900c26d..b2e70a8 100644 --- a/src/world.rs +++ b/src/world.rs @@ -184,7 +184,7 @@ pub fn setup( info!("Generated {starcount} stars"); // Add shaded ring - let ring_radius = 900000.0; + let ring_radius = 640000.0; let jupiter_radius = 200000.0; commands.spawn(MaterialMeshBundle { mesh: meshes.add(Mesh::from(Cylinder::new(ring_radius, 1.0))),