omni light -> point light

This commit is contained in:
Carter Anderson 2021-07-01 16:54:58 -07:00
parent 4099ef6aa2
commit bc769d9641
7 changed files with 43 additions and 45 deletions

View file

@ -4,7 +4,7 @@ use bevy::{
ecs::prelude::*, ecs::prelude::*,
input::Input, input::Input,
math::{Quat, Vec3}, math::{Quat, Vec3},
pbr2::{OmniLight, OmniLightBundle, PbrBundle, StandardMaterial}, pbr2::{PbrBundle, PointLight, PointLightBundle, StandardMaterial},
prelude::{App, Assets, BuildChildren, KeyCode, Transform}, prelude::{App, Assets, BuildChildren, KeyCode, Transform},
render2::{ render2::{
camera::PerspectiveCameraBundle, camera::PerspectiveCameraBundle,
@ -98,10 +98,10 @@ fn setup(
// light // light
commands commands
.spawn_bundle(OmniLightBundle { .spawn_bundle(PointLightBundle {
// transform: Transform::from_xyz(5.0, 8.0, 2.0), // transform: Transform::from_xyz(5.0, 8.0, 2.0),
transform: Transform::from_xyz(1.0, 2.0, 0.0), transform: Transform::from_xyz(1.0, 2.0, 0.0),
omni_light: OmniLight { point_light: PointLight {
color: Color::RED, color: Color::RED,
..Default::default() ..Default::default()
}, },
@ -124,10 +124,10 @@ fn setup(
// light // light
commands commands
.spawn_bundle(OmniLightBundle { .spawn_bundle(PointLightBundle {
// transform: Transform::from_xyz(5.0, 8.0, 2.0), // transform: Transform::from_xyz(5.0, 8.0, 2.0),
transform: Transform::from_xyz(-1.0, 2.0, 0.0), transform: Transform::from_xyz(-1.0, 2.0, 0.0),
omni_light: OmniLight { point_light: PointLight {
color: Color::GREEN, color: Color::GREEN,
..Default::default() ..Default::default()
}, },
@ -150,10 +150,10 @@ fn setup(
// light // light
commands commands
.spawn_bundle(OmniLightBundle { .spawn_bundle(PointLightBundle {
// transform: Transform::from_xyz(5.0, 8.0, 2.0), // transform: Transform::from_xyz(5.0, 8.0, 2.0),
transform: Transform::from_xyz(0.0, 4.0, 0.0), transform: Transform::from_xyz(0.0, 4.0, 0.0),
omni_light: OmniLight { point_light: PointLight {
color: Color::BLUE, color: Color::BLUE,
..Default::default() ..Default::default()
}, },

View file

@ -1,7 +1,7 @@
use bevy::{ use bevy::{
ecs::prelude::*, ecs::prelude::*,
math::Vec3, math::Vec3,
pbr2::{OmniLight, OmniLightBundle, PbrBundle, StandardMaterial}, pbr2::{PbrBundle, PointLight, PointLightBundle, StandardMaterial},
prelude::{App, Assets, Transform}, prelude::{App, Assets, Transform},
render2::{ render2::{
camera::{OrthographicCameraBundle, OrthographicProjection}, camera::{OrthographicCameraBundle, OrthographicProjection},
@ -64,9 +64,9 @@ fn setup(
..Default::default() ..Default::default()
}); });
// light // light
commands.spawn_bundle(OmniLightBundle { commands.spawn_bundle(PointLightBundle {
transform: Transform::from_translation(Vec3::new(50.0, 50.0, 50.0)), transform: Transform::from_translation(Vec3::new(50.0, 50.0, 50.0)),
omni_light: OmniLight { point_light: PointLight {
intensity: 50000., intensity: 50000.,
range: 100., range: 100.,
..Default::default() ..Default::default()

View file

@ -1,4 +1,4 @@
use crate::{OmniLight, StandardMaterial}; use crate::{PointLight, StandardMaterial};
use bevy_asset::Handle; use bevy_asset::Handle;
use bevy_ecs::bundle::Bundle; use bevy_ecs::bundle::Bundle;
use bevy_render2::mesh::Mesh; use bevy_render2::mesh::Mesh;
@ -25,8 +25,8 @@ impl Default for PbrBundle {
/// A component bundle for "light" entities /// A component bundle for "light" entities
#[derive(Debug, Bundle, Default)] #[derive(Debug, Bundle, Default)]
pub struct OmniLightBundle { pub struct PointLightBundle {
pub omni_light: OmniLight, pub point_light: PointLight,
pub transform: Transform, pub transform: Transform,
pub global_transform: GlobalTransform, pub global_transform: GlobalTransform,
} }

View file

@ -2,19 +2,19 @@ use bevy_ecs::reflect::ReflectComponent;
use bevy_reflect::Reflect; use bevy_reflect::Reflect;
use bevy_render2::color::Color; use bevy_render2::color::Color;
/// An omnidirectional light /// A light that emits light in all directions from a central point.
#[derive(Debug, Clone, Copy, Reflect)] #[derive(Debug, Clone, Copy, Reflect)]
#[reflect(Component)] #[reflect(Component)]
pub struct OmniLight { pub struct PointLight {
pub color: Color, pub color: Color,
pub intensity: f32, pub intensity: f32,
pub range: f32, pub range: f32,
pub radius: f32, pub radius: f32,
} }
impl Default for OmniLight { impl Default for PointLight {
fn default() -> Self { fn default() -> Self {
OmniLight { PointLight {
color: Color::rgb(1.0, 1.0, 1.0), color: Color::rgb(1.0, 1.0, 1.0),
intensity: 200.0, intensity: 200.0,
range: 20.0, range: 20.0,

View file

@ -1,4 +1,4 @@
use crate::{AmbientLight, ExtractedMeshes, MeshMeta, OmniLight, PbrShaders}; use crate::{AmbientLight, ExtractedMeshes, MeshMeta, PbrShaders, PointLight};
use bevy_ecs::{prelude::*, system::SystemState}; use bevy_ecs::{prelude::*, system::SystemState};
use bevy_math::{const_vec3, Mat4, Vec3, Vec4}; use bevy_math::{const_vec3, Mat4, Vec3, Vec4};
use bevy_render2::{ use bevy_render2::{
@ -11,7 +11,7 @@ use bevy_render2::{
render_resource::*, render_resource::*,
renderer::{RenderContext, RenderDevice}, renderer::{RenderContext, RenderDevice},
texture::*, texture::*,
view::{ExtractedView, ViewUniform, ViewUniformOffset}, view::{ExtractedView, ViewUniformOffset},
}; };
use bevy_transform::components::GlobalTransform; use bevy_transform::components::GlobalTransform;
use crevice::std140::AsStd140; use crevice::std140::AsStd140;
@ -46,17 +46,17 @@ pub struct GpuLight {
#[derive(Copy, Clone, Debug, AsStd140)] #[derive(Copy, Clone, Debug, AsStd140)]
pub struct GpuLights { pub struct GpuLights {
// TODO: this comes first to work around a WGSL alignment issue. We need to solve this issue before releasing the renderer rework // TODO: this comes first to work around a WGSL alignment issue. We need to solve this issue before releasing the renderer rework
lights: [GpuLight; MAX_OMNI_LIGHTS], lights: [GpuLight; MAX_POINT_LIGHTS],
ambient_color: Vec4, ambient_color: Vec4,
len: u32, len: u32,
} }
// NOTE: this must be kept in sync MAX_OMNI_LIGHTS in pbr.frag // NOTE: this must be kept in sync MAX_POINT_LIGHTS in pbr.frag
pub const MAX_OMNI_LIGHTS: usize = 10; pub const MAX_POINT_LIGHTS: usize = 10;
pub const SHADOW_SIZE: Extent3d = Extent3d { pub const SHADOW_SIZE: Extent3d = Extent3d {
width: 1024, width: 1024,
height: 1024, height: 1024,
depth_or_array_layers: 6 * MAX_OMNI_LIGHTS as u32, depth_or_array_layers: 6 * MAX_POINT_LIGHTS as u32,
}; };
pub const SHADOW_FORMAT: TextureFormat = TextureFormat::Depth32Float; pub const SHADOW_FORMAT: TextureFormat = TextureFormat::Depth32Float;
@ -178,7 +178,7 @@ impl FromWorld for ShadowShaders {
pub fn extract_lights( pub fn extract_lights(
mut commands: Commands, mut commands: Commands,
ambient_light: Res<AmbientLight>, ambient_light: Res<AmbientLight>,
lights: Query<(Entity, &OmniLight, &GlobalTransform)>, lights: Query<(Entity, &PointLight, &GlobalTransform)>,
) { ) {
commands.insert_resource(ExtractedAmbientLight { commands.insert_resource(ExtractedAmbientLight {
color: ambient_light.color, color: ambient_light.color,
@ -290,11 +290,11 @@ pub fn prepare_lights(
let mut gpu_lights = GpuLights { let mut gpu_lights = GpuLights {
ambient_color: ambient_color.into(), ambient_color: ambient_color.into(),
len: lights.iter().len() as u32, len: lights.iter().len() as u32,
lights: [GpuLight::default(); MAX_OMNI_LIGHTS], lights: [GpuLight::default(); MAX_POINT_LIGHTS],
}; };
// TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query // TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query
for (light_index, light) in lights.iter().enumerate().take(MAX_OMNI_LIGHTS) { for (light_index, light) in lights.iter().enumerate().take(MAX_POINT_LIGHTS) {
let projection = let projection =
Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, light.range); Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, light.range);

View file

@ -87,7 +87,7 @@ struct StandardMaterial {
flags: u32; flags: u32;
}; };
struct OmniLight { struct PointLight {
color: vec4<f32>; color: vec4<f32>;
// projection: mat4x4<f32>; // projection: mat4x4<f32>;
position: vec3<f32>; position: vec3<f32>;
@ -101,7 +101,7 @@ struct OmniLight {
struct Lights { struct Lights {
// NOTE: this array size must be kept in sync with the constants defined bevy_pbr2/src/render/light.rs // NOTE: this array size must be kept in sync with the constants defined bevy_pbr2/src/render/light.rs
// TODO: this can be removed if we move to storage buffers for light arrays // TODO: this can be removed if we move to storage buffers for light arrays
omni_lights: array<OmniLight, 10>; point_lights: array<PointLight, 10>;
ambient_color: vec4<f32>; ambient_color: vec4<f32>;
num_lights: u32; num_lights: u32;
}; };
@ -296,8 +296,8 @@ fn reinhard_extended_luminance(color: vec3<f32>, max_white_l: f32) -> vec3<f32>
return change_luminance(color, l_new); return change_luminance(color, l_new);
} }
fn omni_light( fn point_light(
world_position: vec3<f32>, light: OmniLight, roughness: f32, NdotV: f32, N: vec3<f32>, V: vec3<f32>, world_position: vec3<f32>, light: PointLight, roughness: f32, NdotV: f32, N: vec3<f32>, V: vec3<f32>,
R: vec3<f32>, F0: vec3<f32>, diffuseColor: vec3<f32> R: vec3<f32>, F0: vec3<f32>, diffuseColor: vec3<f32>
) -> vec3<f32> { ) -> vec3<f32> {
let light_to_frag = light.position.xyz - world_position.xyz; let light_to_frag = light.position.xyz - world_position.xyz;
@ -349,7 +349,7 @@ fn omni_light(
} }
fn fetch_shadow(light_id: i32, frag_position: vec4<f32>) -> f32 { fn fetch_shadow(light_id: i32, frag_position: vec4<f32>) -> f32 {
let light = lights.omni_lights[light_id]; let light = lights.point_lights[light_id];
// because the shadow maps align with the axes and the frustum planes are at 45 degrees // because the shadow maps align with the axes and the frustum planes are at 45 degrees
// we can get the worldspace depth by taking the largest absolute axis // we can get the worldspace depth by taking the largest absolute axis
@ -472,8 +472,8 @@ fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
// accumulate color // accumulate color
var light_accum: vec3<f32> = vec3<f32>(0.0); var light_accum: vec3<f32> = vec3<f32>(0.0);
for (var i: i32 = 0; i < i32(lights.num_lights); i = i + 1) { for (var i: i32 = 0; i < i32(lights.num_lights); i = i + 1) {
let light = lights.omni_lights[i]; let light = lights.point_lights[i];
let light_contrib = omni_light(in.world_position.xyz, light, roughness, NdotV, N, V, R, F0, diffuse_color); let light_contrib = point_light(in.world_position.xyz, light, roughness, NdotV, N, V, R, F0, diffuse_color);
let shadow = fetch_shadow(i, in.world_position); let shadow = fetch_shadow(i, in.world_position);
light_accum = light_accum + light_contrib * shadow; light_accum = light_accum + light_contrib * shadow;
} }

View file

@ -118,21 +118,19 @@ pub fn prepare_windows(
.or_insert_with(|| render_device.create_swap_chain(surface, &swap_chain_descriptor)); .or_insert_with(|| render_device.create_swap_chain(surface, &swap_chain_descriptor));
let frame = match swap_chain.get_current_frame() { let frame = match swap_chain.get_current_frame() {
Ok(swap_chain_frame) => { Ok(swap_chain_frame) => swap_chain_frame,
swap_chain_frame
},
Err(wgpu::SwapChainError::Outdated) => { Err(wgpu::SwapChainError::Outdated) => {
let new_swap_chain = render_device.create_swap_chain(surface, &swap_chain_descriptor); let new_swap_chain =
let frame = new_swap_chain.get_current_frame().expect("Error recreating swap chain"); render_device.create_swap_chain(surface, &swap_chain_descriptor);
window_surfaces.swap_chains.insert( let frame = new_swap_chain
window.id, .get_current_frame()
new_swap_chain .expect("Error recreating swap chain");
); window_surfaces
.swap_chains
.insert(window.id, new_swap_chain);
frame frame
},
err => {
err.expect("Failed to acquire next swap chain texture!")
} }
err => err.expect("Failed to acquire next swap chain texture!"),
}; };
window.swap_chain_frame = Some(TextureView::from(frame)); window.swap_chain_frame = Some(TextureView::from(frame));