You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
3.4 KiB
Rust
120 lines
3.4 KiB
Rust
use bevy::{pbr::{ExtendedMaterial, MaterialExtension}, prelude::*, render::render_resource::{AsBindGroup, ShaderRef}};
|
|
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins(DefaultPlugins)
|
|
.add_plugins(MaterialPlugin::<MonkeyMaterial>::default())
|
|
.insert_resource(Speed(0.3))
|
|
.add_systems(Startup, init)
|
|
.add_systems(Update, add_shadows)
|
|
.add_systems(Update, process_material)
|
|
.add_systems(Update, rotate_monkey)
|
|
.run();
|
|
}
|
|
|
|
fn init(
|
|
server: Res<AssetServer>,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut monkey_materials: ResMut<Assets<MonkeyMaterial>>,
|
|
mut commands: Commands
|
|
) {
|
|
commands.spawn(SceneBundle {
|
|
scene: server.load("models/shadow-example.gltf#Scene0"),
|
|
..default()
|
|
});
|
|
|
|
commands.spawn(MaterialMeshBundle {
|
|
mesh: meshes.add(Sphere::new(1.0)),
|
|
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
|
material: monkey_materials.add(ExtendedMaterial {
|
|
base: StandardMaterial {
|
|
base_color: Color::RED.into(),
|
|
alpha_mode: AlphaMode::Mask(1.0),
|
|
..Default::default()
|
|
},
|
|
extension: MonkeyMaterialExtension { percentage: 0.5 },
|
|
}),
|
|
..default()
|
|
});
|
|
}
|
|
|
|
fn add_shadows(
|
|
mut lights: Query<(Entity, &mut PointLight), Added<PointLight>>,
|
|
mut commands: Commands,
|
|
) {
|
|
lights.iter_mut().for_each(|(e, mut l)| {
|
|
info!("Fixing up shadows");
|
|
l.shadows_enabled = true;
|
|
|
|
let config: bevy::pbr::CascadeShadowConfig =
|
|
bevy::pbr::CascadeShadowConfigBuilder { ..default() }.into();
|
|
commands.entity(e).insert(config);
|
|
});
|
|
}
|
|
|
|
type MonkeyMaterial = ExtendedMaterial<StandardMaterial, MonkeyMaterialExtension>;
|
|
|
|
#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
|
|
struct MonkeyMaterialExtension {
|
|
#[uniform(100)]
|
|
percentage: f32,
|
|
}
|
|
|
|
impl MaterialExtension for MonkeyMaterialExtension {
|
|
fn fragment_shader() -> ShaderRef {
|
|
"shaders/dissolve.wgsl".into()
|
|
}
|
|
|
|
fn deferred_fragment_shader() -> ShaderRef {
|
|
"shaders/dissolve.wgsl".into()
|
|
}
|
|
}
|
|
|
|
fn process_material(
|
|
query: Query<(Entity, &Handle<StandardMaterial>, &Name), Added<Handle<StandardMaterial>>>,
|
|
base_materials: Res<Assets<StandardMaterial>>,
|
|
mut monkey_materials: ResMut<Assets<MonkeyMaterial>>,
|
|
mut commands: Commands,
|
|
) {
|
|
query.iter().for_each(|(e, h, n)| {
|
|
info!("Extended Materials");
|
|
let mut base = base_materials.get(h).unwrap().clone();
|
|
|
|
base.alpha_mode = AlphaMode::Mask(1.0);
|
|
// base.base_color = base.base_color.clone().with_a(0.0);
|
|
|
|
let extension = MonkeyMaterialExtension { percentage: 0.5 };
|
|
|
|
let monkey_material = monkey_materials.add(
|
|
ExtendedMaterial {
|
|
base, extension
|
|
}
|
|
);
|
|
commands
|
|
.entity(e)
|
|
.remove::<Handle<StandardMaterial>>()
|
|
.insert(monkey_material);
|
|
})
|
|
}
|
|
|
|
#[derive(Resource)]
|
|
struct Speed(f32);
|
|
|
|
fn rotate_monkey(
|
|
mut query: Query<(&mut Transform, &Name)>,
|
|
time: Res<Time>,
|
|
mut speed: ResMut<Speed>,
|
|
keys: Res<ButtonInput<KeyCode>>,
|
|
) {
|
|
if keys.just_pressed(KeyCode::ArrowUp) {
|
|
speed.0 *= 1.1;
|
|
} else if keys.just_pressed(KeyCode::ArrowDown) {
|
|
speed.0 *= 0.9;
|
|
}
|
|
query.iter_mut().for_each(|(mut t, n)| {
|
|
if *n == Name::new("Suzanne") {
|
|
t.rotate_local_y(time.delta_seconds() * speed.0)
|
|
}
|
|
});
|
|
} |