Skip to content

Commit

Permalink
Spotlights (#4715)
Browse files Browse the repository at this point in the history
# Objective

add spotlight support

## Solution / Changelog

- add spotlight angles (inner, outer) to ``PointLight`` struct. emitted light is linearly attenuated from 100% to 0% as angle tends from inner to outer. Direction is taken from the existing transform rotation.
- add spotlight direction (vec3) and angles (f32,f32) to ``GpuPointLight`` struct (60 bytes -> 80 bytes) in ``pbr/render/lights.rs`` and ``mesh_view_bind_group.wgsl``
- reduce no-buffer-support max point light count to 204 due to above
- use spotlight data to attenuate light in ``pbr.wgsl``
- do additional cluster culling on spotlights to minimise cost in ``assign_lights_to_clusters``
- changed one of the lights in the lighting demo to a spotlight
- also added a ``spotlight`` demo - probably not justified but so reviewers can see it more easily

## notes

increasing the size of the GpuPointLight struct on my machine reduces the FPS of ``many_lights -- sphere`` from ~150fps to 140fps. 

i thought this was a reasonable tradeoff, and felt better than handling spotlights separately which is possible but would mean introducing a new bind group, refactoring light-assignment code and adding new spotlight-specific code in pbr.wgsl. the FPS impact for smaller numbers of lights should be very small.

the cluster culling strategy reintroduces the cluster aabb code which was recently removed... sorry. the aabb is used to get a cluster bounding sphere, which can then be tested fairly efficiently using the strategy described at the end of https://bartwronski.com/2017/04/13/cull-that-cone/. this works well with roughly cubic clusters (where the cluster z size is close to the same as x/y size), less well for other cases like single Z slice / tiled forward rendering. In the worst case we will end up just keeping the culling of the equivalent point light.

Co-authored-by: François <[email protected]>
  • Loading branch information
robtfm and mockersf committed Jul 8, 2022
1 parent e8a1c71 commit a7bb662
Showing 1 changed file with 28 additions and 4 deletions.
32 changes: 28 additions & 4 deletions src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use bevy_log::warn;
use bevy_math::{Mat4, Vec3};
use bevy_pbr::{
AlphaMode, DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle,
StandardMaterial,
SpotLight, SpotLightBundle, StandardMaterial,
};
use bevy_render::{
camera::{
Expand Down Expand Up @@ -862,9 +862,33 @@ fn load_node(
}
}
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."),
inner_cone_angle,
outer_cone_angle,
} => {
let mut entity = parent.spawn_bundle(SpotLightBundle {
spot_light: SpotLight {
color: Color::from(light.color()),
// NOTE: KHR_punctual_lights defines the intensity units for spot lights in
// candela (lm/sr) which is luminous intensity and we need luminous power.
// For a spot light, we map 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),
inner_angle: inner_cone_angle,
outer_angle: outer_cone_angle,
..Default::default()
},
..Default::default()
});
if let Some(name) = light.name() {
entity.insert(Name::new(name.to_string()));
}
if let Some(extras) = light.extras() {
entity.insert(super::GltfExtras {
value: extras.get().to_string(),
});
}
}
}
}

Expand Down

0 comments on commit a7bb662

Please sign in to comment.