Skip to content

Commit

Permalink
bevy_gltf: Add support for loading lights (#3506)
Browse files Browse the repository at this point in the history
# 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.
  • Loading branch information
superdump committed Jan 3, 2022
1 parent d44c3cd commit b081b80
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 10 deletions.
7 changes: 6 additions & 1 deletion crates/bevy_gltf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
41 changes: 40 additions & 1 deletion crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_pbr/src/bundle.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down Expand Up @@ -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],
}

Expand Down
5 changes: 4 additions & 1 deletion crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>()
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions crates/bevy_render/src/color/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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();

Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_render/src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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],
}

Expand Down

0 comments on commit b081b80

Please sign in to comment.