mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-24 08:26:01 +00:00
HDRI Skyboxes / Image-Based Lighting
This commit is contained in:
@@ -2,12 +2,14 @@
|
||||
|
||||
use bevy::prelude::*;
|
||||
use orbit_cam::{OrbitCam, OrbitCamPlugin};
|
||||
use skybox::SkyboxPlugin;
|
||||
use test_scene::TestScenePlugin;
|
||||
use ui::UiLayerPlugin;
|
||||
use viewport::ViewportSize;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
mod orbit_cam;
|
||||
mod skybox;
|
||||
mod test_scene;
|
||||
mod ui;
|
||||
mod viewport;
|
||||
@@ -32,6 +34,7 @@ pub fn init(viewport_size: ViewportSize) {
|
||||
}),
|
||||
OrbitCamPlugin,
|
||||
TestScenePlugin,
|
||||
SkyboxPlugin,
|
||||
UiLayerPlugin,
|
||||
))
|
||||
.add_systems(Update, draw_world_axes.after(orbit_cam::pan_orbit_camera))
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
use core::fmt;
|
||||
|
||||
use bevy::{
|
||||
asset::LoadState,
|
||||
core_pipeline::Skybox,
|
||||
prelude::*,
|
||||
render::render_resource::{TextureViewDescriptor, TextureViewDimension},
|
||||
};
|
||||
|
||||
pub struct SkyboxPlugin;
|
||||
|
||||
impl Plugin for SkyboxPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(Startup, setup)
|
||||
.add_systems(Update, asset_loaded);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct Cubemap {
|
||||
is_loaded: bool,
|
||||
image_handle: Handle<Image>,
|
||||
env_diffuse: Handle<Image>,
|
||||
env_specular: Handle<Image>,
|
||||
}
|
||||
|
||||
impl Cubemap {
|
||||
fn new(name: impl fmt::Display, assets: &Res<AssetServer>) -> Self {
|
||||
let paths = SkyboxPaths::new(name);
|
||||
|
||||
Self {
|
||||
is_loaded: false,
|
||||
image_handle: assets.load(paths.main),
|
||||
env_diffuse: assets.load(paths.env_diffuse),
|
||||
env_specular: assets.load(paths.env_specular),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SkyboxPaths {
|
||||
pub main: String,
|
||||
pub env_diffuse: String,
|
||||
pub env_specular: String,
|
||||
}
|
||||
|
||||
impl SkyboxPaths {
|
||||
fn new(name: impl fmt::Display) -> Self {
|
||||
Self {
|
||||
main: format!("skyboxes/{name}.hdr"),
|
||||
env_diffuse: format!("skyboxes/{name}_diffuse.zstd.ktx2"),
|
||||
env_specular: format!("skyboxes/{name}_specular.zstd.ktx2"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup(mut cmd: Commands, assets: Res<AssetServer>) {
|
||||
cmd.insert_resource(Cubemap::new("promenade_de_vidy_4k", &assets));
|
||||
}
|
||||
|
||||
fn asset_loaded(
|
||||
assets: Res<AssetServer>,
|
||||
camera: Query<Entity, With<Camera3d>>,
|
||||
mut cmd: Commands,
|
||||
mut images: ResMut<Assets<Image>>,
|
||||
mut cubemap: ResMut<Cubemap>,
|
||||
) {
|
||||
if !cubemap.is_loaded
|
||||
&& assets.get_load_state(cubemap.image_handle.clone_weak()) == LoadState::Loaded
|
||||
{
|
||||
let image = images.get_mut(&cubemap.image_handle).unwrap();
|
||||
if image.texture_descriptor.array_layer_count() == 1 {
|
||||
image.reinterpret_stacked_2d_as_array(6);
|
||||
image.texture_view_descriptor = Some(TextureViewDescriptor {
|
||||
dimension: Some(TextureViewDimension::Cube),
|
||||
..default()
|
||||
});
|
||||
}
|
||||
|
||||
cmd.entity(camera.single()).insert((
|
||||
Skybox(cubemap.image_handle.clone()),
|
||||
EnvironmentMapLight {
|
||||
diffuse_map: cubemap.env_diffuse.clone(),
|
||||
specular_map: cubemap.env_specular.clone(),
|
||||
},
|
||||
));
|
||||
|
||||
cubemap.is_loaded = true;
|
||||
}
|
||||
}
|
||||
@@ -34,25 +34,11 @@ fn spawn_scene(
|
||||
mut std_mats: ResMut<Assets<StandardMaterial>>,
|
||||
mut mat_proc_grid: ResMut<Assets<ProceduralGridMaterial>>,
|
||||
) {
|
||||
let mut light_xform = Transform::IDENTITY;
|
||||
light_xform.rotation = Quat::from_rotation_y(f32::to_radians(-70.0)) * light_xform.rotation;
|
||||
light_xform.rotation *= Quat::from_rotation_x(f32::to_radians(-60.0));
|
||||
|
||||
cmd.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 25_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
transform: light_xform,
|
||||
..default()
|
||||
});
|
||||
|
||||
// Cube
|
||||
// Sphere
|
||||
cmd.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||
mesh: meshes.add(Mesh::try_from(shape::Icosphere::default()).unwrap()),
|
||||
material: std_mats.add(StandardMaterial {
|
||||
base_color: Color::SILVER,
|
||||
base_color: Color::WHITE,
|
||||
..default()
|
||||
}),
|
||||
transform: Transform::IDENTITY,
|
||||
|
||||
Reference in New Issue
Block a user