bevy_gltf: Add support for loading lights (#3506)
# Objective - Add support for loading lights from glTF 2.0 files ## Solution - This adds support for the KHR_punctual_lights extension which supports point, directional, and spot lights, though we don't yet support spot lights. - Inserting light bundles when creating scenes required registering some more light bundle component types.
This commit is contained in:
parent
d44c3cd150
commit
85b7589388
@ -24,7 +24,12 @@ bevy_scene = { path = "../bevy_scene", version = "0.5.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.5.0" }
|
||||
|
||||
# other
|
||||
gltf = { version = "0.16.0", default-features = false, features = ["utils", "names", "KHR_materials_unlit"] }
|
||||
gltf = { version = "0.16.0", default-features = false, features = [
|
||||
"KHR_lights_punctual",
|
||||
"KHR_materials_unlit",
|
||||
"names",
|
||||
"utils",
|
||||
] }
|
||||
thiserror = "1.0"
|
||||
anyhow = "1.0.4"
|
||||
base64 = "0.13.0"
|
||||
|
||||
@ -6,7 +6,10 @@ use bevy_core::Name;
|
||||
use bevy_ecs::world::World;
|
||||
use bevy_log::warn;
|
||||
use bevy_math::{Mat4, Vec3};
|
||||
use bevy_pbr::{AlphaMode, PbrBundle, StandardMaterial};
|
||||
use bevy_pbr::{
|
||||
AlphaMode, DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle,
|
||||
StandardMaterial,
|
||||
};
|
||||
use bevy_render::{
|
||||
camera::{
|
||||
Camera, CameraPlugin, CameraProjection, OrthographicProjection, PerspectiveProjection,
|
||||
@ -550,6 +553,42 @@ fn load_node(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(light) = gltf_node.light() {
|
||||
match light.kind() {
|
||||
gltf::khr_lights_punctual::Kind::Directional => {
|
||||
parent.spawn_bundle(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
color: Color::from(light.color()),
|
||||
// NOTE: KHR_punctual_lights defines the intensity units for directional
|
||||
// lights in lux (lm/m^2) which is what we need.
|
||||
illuminance: light.intensity(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
gltf::khr_lights_punctual::Kind::Point => {
|
||||
parent.spawn_bundle(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
color: Color::from(light.color()),
|
||||
// NOTE: KHR_punctual_lights defines the intensity units for point lights in
|
||||
// candela (lm/sr) which is luminous intensity and we need luminous power.
|
||||
// For a point light, luminous power = 4 * pi * luminous intensity
|
||||
intensity: light.intensity() * std::f32::consts::PI * 4.0,
|
||||
range: light.range().unwrap_or(20.0),
|
||||
radius: light.range().unwrap_or(0.0),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
gltf::khr_lights_punctual::Kind::Spot {
|
||||
inner_cone_angle: _inner_cone_angle,
|
||||
outer_cone_angle: _outer_cone_angle,
|
||||
} => warn!("Spot lights are not yet supported."),
|
||||
}
|
||||
}
|
||||
|
||||
// append other nodes
|
||||
for child in gltf_node.children() {
|
||||
if let Err(err) = load_node(&child, parent, load_context, buffer_data) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::{DirectionalLight, PointLight, SpecializedMaterial, StandardMaterial};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_ecs::{bundle::Bundle, component::Component};
|
||||
use bevy_ecs::{bundle::Bundle, component::Component, reflect::ReflectComponent};
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_render::{
|
||||
mesh::Mesh,
|
||||
primitives::{CubemapFrusta, Frustum},
|
||||
@ -37,8 +38,10 @@ impl<M: SpecializedMaterial> Default for MaterialMeshBundle<M> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Clone, Debug, Default)]
|
||||
#[derive(Component, Clone, Debug, Default, Reflect)]
|
||||
#[reflect(Component)]
|
||||
pub struct CubemapVisibleEntities {
|
||||
#[reflect(ignore)]
|
||||
data: [VisibleEntities; 6],
|
||||
}
|
||||
|
||||
|
||||
@ -67,7 +67,10 @@ impl Plugin for PbrPlugin {
|
||||
Shader::from_wgsl(include_str!("render/depth.wgsl")),
|
||||
);
|
||||
|
||||
app.add_plugin(MeshRenderPlugin)
|
||||
app.register_type::<CubemapVisibleEntities>()
|
||||
.register_type::<DirectionalLight>()
|
||||
.register_type::<PointLight>()
|
||||
.add_plugin(MeshRenderPlugin)
|
||||
.add_plugin(MaterialPlugin::<StandardMaterial>::default())
|
||||
.init_resource::<AmbientLight>()
|
||||
.init_resource::<DirectionalLightShadowMap>()
|
||||
|
||||
@ -2,6 +2,7 @@ use std::collections::HashSet;
|
||||
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_math::{Mat4, UVec2, UVec3, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles};
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_render::{
|
||||
camera::{Camera, CameraProjection, OrthographicProjection},
|
||||
color::Color,
|
||||
@ -33,7 +34,8 @@ use crate::{
|
||||
/// | 4000 | 300 | | 75-100 | 40.5 |
|
||||
///
|
||||
/// Source: [Wikipedia](https://en.wikipedia.org/wiki/Lumen_(unit)#Lighting)
|
||||
#[derive(Component, Debug, Clone, Copy)]
|
||||
#[derive(Component, Debug, Clone, Copy, Reflect)]
|
||||
#[reflect(Component)]
|
||||
pub struct PointLight {
|
||||
pub color: Color,
|
||||
pub intensity: f32,
|
||||
@ -104,7 +106,8 @@ impl Default for PointLightShadowMap {
|
||||
/// | 32,000–100,000 | Direct sunlight |
|
||||
///
|
||||
/// Source: [Wikipedia](https://en.wikipedia.org/wiki/Lux)
|
||||
#[derive(Component, Debug, Clone)]
|
||||
#[derive(Component, Debug, Clone, Reflect)]
|
||||
#[reflect(Component)]
|
||||
pub struct DirectionalLight {
|
||||
pub color: Color,
|
||||
/// Illuminance in lux
|
||||
|
||||
@ -617,6 +617,12 @@ impl From<[f32; 4]> for Color {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 3]> for Color {
|
||||
fn from([r, g, b]: [f32; 3]) -> Self {
|
||||
Color::rgb(r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for Vec4 {
|
||||
fn from(color: Color) -> Self {
|
||||
let color: [f32; 4] = color.into();
|
||||
|
||||
@ -33,7 +33,7 @@ use crate::{
|
||||
camera::CameraPlugin,
|
||||
color::Color,
|
||||
mesh::MeshPlugin,
|
||||
primitives::Frustum,
|
||||
primitives::{CubemapFrusta, Frustum},
|
||||
render_graph::RenderGraph,
|
||||
render_resource::{RenderPipelineCache, Shader, ShaderLoader},
|
||||
renderer::render_system,
|
||||
@ -141,7 +141,8 @@ impl Plugin for RenderPlugin {
|
||||
.init_asset_loader::<ShaderLoader>()
|
||||
.init_resource::<ScratchRenderWorld>()
|
||||
.register_type::<Color>()
|
||||
.register_type::<Frustum>();
|
||||
.register_type::<Frustum>()
|
||||
.register_type::<CubemapFrusta>();
|
||||
let render_pipeline_cache = RenderPipelineCache::new(device.clone());
|
||||
let asset_server = app.world.get_resource::<AssetServer>().unwrap().clone();
|
||||
|
||||
|
||||
@ -144,8 +144,10 @@ impl Frustum {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Default)]
|
||||
#[derive(Component, Debug, Default, Reflect)]
|
||||
#[reflect(Component)]
|
||||
pub struct CubemapFrusta {
|
||||
#[reflect(ignore)]
|
||||
pub frusta: [Frustum; 6],
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user