diff --git a/assets/shaders/aurora.wgsl b/assets/shaders/aurora.wgsl new file mode 100644 index 0000000..e3f4bb7 --- /dev/null +++ b/assets/shaders/aurora.wgsl @@ -0,0 +1,25 @@ +#import bevy_pbr::{ + mesh_view_bindings::globals, + forward_io::VertexOutput, +} + +const latitude_cutoff = 50.0; +const tau = 6.283185307179586; + +@fragment +fn fragment(in: VertexOutput) -> @location(0) vec4 { + let color = vec3(2.0, 6.0, 20.0); + var alpha = 0.0; + + let lat = 180.0 * abs(in.uv[1] - 0.5); + let phase = in.uv[0] * 2.0 * 3.14159; + if (lat > latitude_cutoff) { + let y = (lat - latitude_cutoff) / (90.0 - latitude_cutoff); + //alpha = sin(phase * 5.0) + sin(5.0 * y); + alpha = 0.1 * clamp(-4.0 * cos(tau * sqrt(y + 0.01 * sin(phase * 20.0) + 0.1 * sin(phase))) - 3.0, 0.0, 1.0); + alpha += 0.3 * clamp(-1000.0 * cos(tau * sqrt(y + 0.01 * sin(phase * 30.0) + 0.1 * sin(phase + 0.3))) - 992.0, 0.0, 1.0); + alpha += 0.2 * clamp(-1000.0 * cos(tau * sqrt(-0.13 + y + 0.01 * sin(phase * 20.0) + 0.2 * sin(phase + 0.4))) - 992.0, 0.0, 1.0); + } + + return vec4(color, clamp(alpha, 0.0, 1.0)); +} diff --git a/src/cmd.rs b/src/cmd.rs index e741508..06d30c1 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -106,6 +106,7 @@ struct ParserState { orbit_phase: Option, has_physics: bool, has_ring: bool, + has_aurora: bool, wants_maxrotation: Option, wants_maxvelocity: Option, wants_tolookat_id: Option, @@ -169,6 +170,7 @@ impl Default for ParserState { orbit_phase: None, has_physics: true, has_ring: false, + has_aurora: false, wants_maxrotation: None, wants_maxvelocity: None, wants_tolookat_id: None, @@ -473,6 +475,9 @@ pub fn load_defs(mut ew_spawn: EventWriter) { ["ring", "yes"] => { state.has_ring = true; } + ["aurora", "yes"] => { + state.has_aurora = true; + } ["tidally", "locked"] => { state.is_tidally_locked = true; } @@ -907,6 +912,7 @@ fn spawn_entities( mut meshes: ResMut>, mut materials: ResMut>, mut materials_jupiter: ResMut>, + mut materials_aurora: ResMut>, mut id2pos: ResMut, mut achievement_tracker: ResMut, mut ew_updateavatar: EventWriter, @@ -1301,6 +1307,26 @@ fn spawn_entities( NotShadowReceiver, )); } + + if state.has_aurora { + let radius = state.model_scale * 1.01; + commands.spawn(( + world::DespawnOnPlayerDeath, + MaterialMeshBundle { + mesh: meshes.add(Sphere::new(radius).mesh().uv(128, 128)), + material: materials_aurora.add(load::JupitersAurora { + alpha_mode: AlphaMode::Blend, + }), + transform: Transform::from_translation(absolute_pos.as_vec3()), + ..default() + }, + Position::new(absolute_pos), + //Rotation::default(), + Rotation::from(Quat::from_rotation_x(-90f32.to_radians())), + NotShadowCaster, + NotShadowReceiver, + )); + } } } diff --git a/src/data/defs.txt b/src/data/defs.txt index c14a897..6f7ff47 100644 --- a/src/data/defs.txt +++ b/src/data/defs.txt @@ -89,6 +89,7 @@ actor 0 0 0 planet yes sphere yes ring yes + aurora yes physics off rotationy 3.13 rotationz 135 diff --git a/src/load.rs b/src/load.rs index c4e665d..089ebfd 100644 --- a/src/load.rs +++ b/src/load.rs @@ -19,6 +19,7 @@ pub struct LoadPlugin; impl Plugin for LoadPlugin { fn build(&self, app: &mut App) { app.add_plugins(MaterialPlugin::::default()); + app.add_plugins(MaterialPlugin::::default()); app.add_plugins(MaterialPlugin::::default()); app.add_plugins(MaterialPlugin::< ExtendedMaterial, @@ -103,6 +104,21 @@ impl Material for JupitersRing { } } +// Jupiter's Aurora +#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)] +pub struct JupitersAurora { + pub alpha_mode: AlphaMode, +} + +impl Material for JupitersAurora { + fn fragment_shader() -> ShaderRef { + "shaders/aurora.wgsl".into() + } + fn alpha_mode(&self) -> AlphaMode { + self.alpha_mode + } +} + // Sky Box #[derive(Asset, TypePath, AsBindGroup, Debug, Clone)] pub struct SkyBox {}