Refactoring, reorganization and cleanup (#7)

### New `math` module
 * Traits for error-tolerant floating-point comparisons
 * Traits for interpolation and easing
 * Bevy plugin to manage 3D interpolations with ECS components

### `skybox` module refactor
 * ECS resource to enable external skybox selection/updates
 * System run conditions for more idiomatic/ECS-friendly control flow

### Camera controller refactor
 * Renamed from `orbit_cam` to `camera_controller`
 * Now delegates to the new interpolation plugin for WASD motion smoothing
 * Simple API for attaching the `CameraController` component to the camera from
   another module -- this resolves an awkward separation-of-concerns situation
	where we had to configure a bunch of render-quality settings in the camera
	controller module

### Scene module refactor
 * Renamed from `test_scene` to `scene`
 * This module is now responsible for configuring the skybox
 * This module is now responsible for spawning the camera and configuring the
   render settings
This commit is contained in:
Danny McGee
2023-10-31 16:39:10 -04:00
committed by GitHub
parent 4b9ea61495
commit ce6db7fc3c
11 changed files with 811 additions and 399 deletions
+158
View File
@@ -0,0 +1,158 @@
use bevy::{
core_pipeline::{
bloom::{BloomCompositeMode, BloomPrefilterSettings, BloomSettings},
fxaa::Fxaa,
tonemapping::Tonemapping,
},
math::vec3,
pbr::NotShadowCaster,
prelude::*,
reflect::{TypePath, TypeUuid},
render::render_resource::{AsBindGroup, ShaderRef},
};
use crate::{
camera_controller::{CameraController, CameraControllerBundle, CameraMotionSystem},
skybox::SkyboxId,
};
pub struct ScenePlugin;
impl Plugin for ScenePlugin {
fn build(&self, app: &mut App) {
app.insert_resource(ClearColor(Color::hsl(0.0, 0.0, 0.25)))
.add_plugins(MaterialPlugin::<ProceduralGridMaterial>::default())
.add_systems(Startup, spawn_scene)
.add_systems(PostUpdate, move_plane_with_camera.after(CameraMotionSystem));
}
}
#[derive(Component)]
struct WorldGridPlane;
fn spawn_scene(
mut cmd: Commands,
assets: Res<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut mat_proc_grid: ResMut<Assets<ProceduralGridMaterial>>,
) {
// Skybox
cmd.insert_resource(SkyboxId("test_scene".into()));
// glTF scene
cmd.spawn(SceneBundle {
scene: assets.load("gltf/sample-room.gltf#Scene0"),
..default()
});
// Camera, graphics settings
let focus = vec3(0.35011, 0.5, -0.99576);
let camera_xform = Transform::from_xyz(-2.5, 4.5, 5.0).looking_at(focus, Vec3::Y);
cmd.spawn((
Camera3dBundle {
transform: camera_xform,
tonemapping: Tonemapping::BlenderFilmic,
camera: Camera {
hdr: true,
..default()
},
..default()
},
CameraControllerBundle::new(focus, camera_xform.translation),
BloomSettings {
composite_mode: BloomCompositeMode::EnergyConserving,
intensity: 0.25,
prefilter_settings: BloomPrefilterSettings {
threshold: 0.8,
threshold_softness: 0.5,
},
..default()
},
Fxaa::default(),
));
// Main light
// TODO: get Blender to export enough metadata to automate light placements
cmd.spawn(PointLightBundle {
point_light: PointLight {
color: Color::hex("FFE5B4").unwrap(),
intensity: 200.,
radius: 0.1,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(0.35263, 2.4348, 0.19601),
..default()
});
// Monitor glow
cmd.spawn(PointLightBundle {
point_light: PointLight {
color: Color::WHITE,
intensity: 6.,
radius: 0.25,
shadows_enabled: false,
..default()
},
transform: Transform::from_xyz(0.42615, 1.0706, -2.0705),
..default()
});
// Plane
let plane = meshes.add(Mesh::from(shape::Plane {
size: 200.0,
subdivisions: 0,
}));
let proc_grid = mat_proc_grid.add(ProceduralGridMaterial {});
cmd.spawn((
SpatialBundle::from_transform(Transform::IDENTITY),
WorldGridPlane,
))
.with_children(|parent| {
parent.spawn((
MaterialMeshBundle {
mesh: plane.clone(),
material: proc_grid.clone(),
transform: Transform::IDENTITY,
..default()
},
NotShadowCaster,
));
parent.spawn((
MaterialMeshBundle {
mesh: plane,
material: proc_grid,
transform: Transform::IDENTITY.looking_to(Vec3::Z, Vec3::NEG_Y),
..default()
},
NotShadowCaster,
));
});
}
fn move_plane_with_camera(
mut plane: Query<(&WorldGridPlane, &mut Transform)>,
camera: Query<&CameraController, Changed<CameraController>>,
) {
if let Ok(&CameraController { focus, .. }) = camera.get_single() {
let (_, mut xform) = plane.single_mut();
xform.translation.x = focus.x;
xform.translation.z = focus.z;
}
}
#[derive(AsBindGroup, Clone, TypePath, TypeUuid)]
#[uuid = "CE331A13-F247-4F5B-A75E-670B2BD5776A"]
struct ProceduralGridMaterial {}
impl Material for ProceduralGridMaterial {
fn fragment_shader() -> ShaderRef {
"shaders/procedural_grid.wgsl".into()
}
fn alpha_mode(&self) -> AlphaMode {
AlphaMode::Blend
}
}