From 2121642b92d24a94dc3de65a6c72d952a362bd5e Mon Sep 17 00:00:00 2001 From: hut Date: Mon, 1 Apr 2024 02:05:38 +0200 Subject: [PATCH] first attempt at jovian ring with shader --- assets/shaders/jupiters_rings.wgsl | 33 +++++++++++++ assets/shaders/testshader.wgsl | 22 --------- src/world.rs | 76 ++++++++++++++++++++---------- 3 files changed, 84 insertions(+), 47 deletions(-) create mode 100644 assets/shaders/jupiters_rings.wgsl delete mode 100644 assets/shaders/testshader.wgsl diff --git a/assets/shaders/jupiters_rings.wgsl b/assets/shaders/jupiters_rings.wgsl new file mode 100644 index 0000000..6f4b573 --- /dev/null +++ b/assets/shaders/jupiters_rings.wgsl @@ -0,0 +1,33 @@ +#import bevy_pbr::{ + mesh_view_bindings::globals, + forward_io::VertexOutput, +} + +@group(2) @binding(0) var ring_radius: f32; +@group(2) @binding(1) var jupiter_radius: f32; + +@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)); + + 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 + let side_dist = abs(in.uv[1] - 0.5); + + let cutoff = 0.5 * jupiter_percent * cos(dist); + if side_dist < cutoff { + return vec4(color, 0.0); + } + let fuzzy_boundary = 0.01; + if side_dist < cutoff + fuzzy_boundary { + return vec4(color, alpha * (side_dist - cutoff) / fuzzy_boundary); + } + } + return vec4(color, alpha); +} diff --git a/assets/shaders/testshader.wgsl b/assets/shaders/testshader.wgsl deleted file mode 100644 index 6ded205..0000000 --- a/assets/shaders/testshader.wgsl +++ /dev/null @@ -1,22 +0,0 @@ -#import bevy_pbr::{ - mesh_view_bindings::globals, - forward_io::VertexOutput, -} - -@fragment -fn fragment(in: VertexOutput) -> @location(0) vec4 { - let speed = 3.0; - let t_1 = sin(globals.time * speed) * 0.5 + 0.5; - let t_2 = cos(globals.time * speed); - - let distance_to_center = distance(in.uv, vec2(0.5)) * 1.4; - - let red = vec3(0.627955, 0.224863, 0.125846); - let green = vec3(0.86644, -0.233887, 0.179498); - let blue = vec3(0.701674, 0.274566, -0.169156); - let white = vec3(1.0, 0.0, 0.0); - let pos = vec3(in.position[0], in.position[1], in.position[2]); - let mixed = mix(pos, mix(green, white, t_2), distance_to_center); - - return vec4(mixed, 1.0); -} diff --git a/src/world.rs b/src/world.rs index fdcdc03..900c26d 100644 --- a/src/world.rs +++ b/src/world.rs @@ -40,18 +40,27 @@ impl Plugin for WorldPlugin { //app.add_systems(Update, asset_loaded.after(load_cubemap_asset)); //app.add_systems(Update, swap_world_on_ar_toggle); app.add_plugins(PhysicsPlugins::default()); - app.add_plugins(MaterialPlugin::::default()); + app.add_plugins(MaterialPlugin::::default()); //app.add_plugins(PhysicsDebugPlugin::default()); app.insert_resource(Gravity(Vec3::splat(0.0))); } } #[derive(Asset, TypePath, AsBindGroup, Debug, Clone)] -pub struct CustomMaterial {} +pub struct RingMaterial { + alpha_mode: AlphaMode, + #[uniform(0)] + ring_radius: f32, + #[uniform(1)] + jupiter_radius: f32, +} -impl Material for CustomMaterial { +impl Material for RingMaterial { fn fragment_shader() -> ShaderRef { - "shaders/testshader.wgsl".into() + "shaders/jupiters_rings.wgsl".into() + } + fn alpha_mode(&self) -> AlphaMode { + self.alpha_mode } } @@ -79,7 +88,7 @@ pub fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, - mut materials_custom: ResMut>, + mut materials_custom: ResMut>, asset_server: Res, ) { // let cubemap_handle = asset_server.load(ASSET_CUBEMAP); @@ -175,26 +184,43 @@ pub fn setup( info!("Generated {starcount} stars"); // Add shaded ring - let max = 20; - for i in 0..max { - let f = i as f32; - let maxf = max as f32; - let ringmesh = Mesh::from(Cylinder::new(400000.0 + f * 10000.0, 5000.0 - 150.0 * f)); - let clr = 0.4 + (f/maxf).clamp(0.0,0.6); - commands.spawn(MaterialMeshBundle { - mesh: meshes.add(ringmesh), - transform: Transform::from_xyz(300000.0, 0.0, 500000.0), - //material: materials_custom.add(CustomMaterial {}), - material: materials.add(StandardMaterial { - base_color: Color::rgba(clr, clr, clr, 0.0001), - unlit: true, - cull_mode: None, - alpha_mode: AlphaMode::Blend, - ..default() - }), - ..default() - }); - } + let ring_radius = 900000.0; + let jupiter_radius = 200000.0; + commands.spawn(MaterialMeshBundle { + mesh: meshes.add(Mesh::from(Cylinder::new(ring_radius, 1.0))), + transform: Transform::from_xyz(300000.0, -4000.0, 500000.0) + .with_rotation(Quat::from_rotation_z(PI*0.05)) + , + //transform: Transform::from_xyz(300000.0, 0.0, 500000.0)), + material: materials_custom.add(RingMaterial { + alpha_mode: AlphaMode::Blend, + ring_radius: ring_radius, + jupiter_radius: jupiter_radius, + }), + ..default() + }); + //let max = 20; + //for i in 0..max { + // let f = i as f32; + // let maxf = max as f32; + // let ringmesh = Mesh::from(Cylinder::new(400000.0 + f * 10000.0, 5000.0 - 150.0 * f)); + // let clr = 0.4 + (f/maxf).clamp(0.0,0.6); + // commands.spawn(MaterialMeshBundle { + // mesh: meshes.add(ringmesh), + // transform: Transform::from_xyz(300000.0, 0.0, 500000.0), + // material: materials_custom.add(RingMaterial { + // alpha_mode: AlphaMode::Blend, + // }), + // material: materials.add(StandardMaterial { + // base_color: Color::rgba(clr, clr, clr, 0.0001), + // unlit: true, + // cull_mode: None, + // alpha_mode: AlphaMode::Blend, + // ..default() + // }), + // ..default() + // }); + //} // Add Light from the Sun commands.spawn(DirectionalLightBundle {