mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-18 07:35:19 +00:00
HDRI Skyboxes / Image-Based Lighting
This commit is contained in:
@@ -40,5 +40,5 @@ fn fragment(in: MeshVertexOutput) -> @location(0) vec4<f32> {
|
||||
let base = grid_lines(pos, depth, 1.0, 0.0001, 0.01);
|
||||
let sparse = grid_lines(pos, depth, 0.1, 0.00005, 0.005);
|
||||
|
||||
return vec4<f32>(0.5, 0.5, 0.5, 0.5) * min(0.5, saturate(dense + base + sparse));
|
||||
return vec4<f32>(1.0, 1.0, 1.0, 0.25) * saturate(dense + base + sparse);
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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