Implement spot lights and directional lights
This commit is contained in:
parent
e412e589d1
commit
104649d574
|
@ -12,6 +12,7 @@ use lyra_engine::{
|
||||||
#[derive(Clone, Component)]
|
#[derive(Clone, Component)]
|
||||||
pub struct FreeFlyCamera {
|
pub struct FreeFlyCamera {
|
||||||
pub speed: f32,
|
pub speed: f32,
|
||||||
|
pub slow_speed_factor: f32,
|
||||||
pub look_speed: f32,
|
pub look_speed: f32,
|
||||||
pub mouse_sensitivity: f32,
|
pub mouse_sensitivity: f32,
|
||||||
pub look_with_keys: bool,
|
pub look_with_keys: bool,
|
||||||
|
@ -21,6 +22,7 @@ impl Default for FreeFlyCamera {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
speed: 4.0,
|
speed: 4.0,
|
||||||
|
slow_speed_factor: 0.25,
|
||||||
look_speed: 0.09,
|
look_speed: 0.09,
|
||||||
mouse_sensitivity: 0.4,
|
mouse_sensitivity: 0.4,
|
||||||
look_with_keys: false,
|
look_with_keys: false,
|
||||||
|
@ -29,9 +31,10 @@ impl Default for FreeFlyCamera {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FreeFlyCamera {
|
impl FreeFlyCamera {
|
||||||
pub fn new(speed: f32, look_speed: f32, mouse_sensitivity: f32, look_with_keys: bool) -> Self {
|
pub fn new(speed: f32, slow_speed_factor: f32, look_speed: f32, mouse_sensitivity: f32, look_with_keys: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
speed,
|
speed,
|
||||||
|
slow_speed_factor,
|
||||||
look_speed,
|
look_speed,
|
||||||
mouse_sensitivity,
|
mouse_sensitivity,
|
||||||
look_with_keys,
|
look_with_keys,
|
||||||
|
@ -117,7 +120,13 @@ impl SimpleSystem for FreeFlyCameraPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
if velocity != Vec3::ZERO {
|
if velocity != Vec3::ZERO {
|
||||||
cam.transform.translation += velocity.normalize() * fly.speed * delta_time;
|
let temp = if keys.is_pressed(KeyCode::E) {
|
||||||
|
fly.speed * delta_time * fly.slow_speed_factor
|
||||||
|
} else {
|
||||||
|
fly.speed * delta_time
|
||||||
|
};
|
||||||
|
|
||||||
|
cam.transform.translation += velocity.normalize() * temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use lyra_engine::{math::{self, Vec3}, ecs::{World, components::{transform::TransformComponent, camera::CameraComponent, model::ModelComponent, DeltaTime}, EventQueue, SimpleSystem, Component, Criteria, CriteriaSchedule, BatchedSystem}, math::Transform, input::{KeyCode, InputButtons, MouseMotion, ActionHandler, Layout, Action, ActionKind, LayoutId, ActionMapping, Binding, ActionSource, ActionMappingId, InputActionPlugin, ActionState}, game::Game, plugin::Plugin, render::{window::{CursorGrabMode, WindowOptions}, light::PointLight}, change_tracker::Ct};
|
use lyra_engine::{math::{self, Vec3}, ecs::{World, components::{transform::TransformComponent, camera::CameraComponent, model::ModelComponent, DeltaTime}, EventQueue, SimpleSystem, Component, Criteria, CriteriaSchedule, BatchedSystem}, math::Transform, input::{KeyCode, InputButtons, MouseMotion, ActionHandler, Layout, Action, ActionKind, LayoutId, ActionMapping, Binding, ActionSource, ActionMappingId, InputActionPlugin, ActionState}, game::Game, plugin::Plugin, render::{window::{CursorGrabMode, WindowOptions}, light::{PointLight, directional::DirectionalLight, SpotLight}}, change_tracker::Ct};
|
||||||
use lyra_engine::assets::{ResourceManager, Model};
|
use lyra_engine::assets::{ResourceManager, Model};
|
||||||
|
|
||||||
mod free_fly_camera;
|
mod free_fly_camera;
|
||||||
|
@ -77,65 +77,106 @@ async fn main() {
|
||||||
let crate_model = resman.request::<Model>("assets/crate/crate.gltf").unwrap();
|
let crate_model = resman.request::<Model>("assets/crate/crate.gltf").unwrap();
|
||||||
drop(resman);
|
drop(resman);
|
||||||
|
|
||||||
/* world.spawn((
|
|
||||||
ModelComponent(cube_model.clone()),
|
|
||||||
TransformComponent::from(Transform::from_xyz(3.0, 0.5, -2.2)),
|
|
||||||
)); */
|
|
||||||
|
|
||||||
world.spawn((
|
world.spawn((
|
||||||
ModelComponent(antique_camera_model),
|
ModelComponent(antique_camera_model),
|
||||||
TransformComponent::from(Transform::from_xyz(0.0, -5.0, -10.0)),
|
TransformComponent::from(Transform::from_xyz(0.0, -5.0, -10.0)),
|
||||||
));
|
));
|
||||||
|
|
||||||
/* let light = PointLight {
|
{
|
||||||
color: Vec3::new(1.0, 1.0, 1.0),
|
let mut cube_tran = Transform::from_xyz(-3.5, 0.0, -8.0);
|
||||||
position: Vec3::new(0.0, -5.0, -8.0),
|
//cube_tran.rotate_y(math::Angle::Degrees(180.0));
|
||||||
constant: 1.0,
|
world.spawn((
|
||||||
linear: 0.09,
|
TransformComponent::from(cube_tran),
|
||||||
quadratic: 0.032,
|
ModelComponent(crate_model.clone()),
|
||||||
};
|
CubeFlag,
|
||||||
world.spawn((light,)); */
|
));
|
||||||
let mut cube_tran = Transform::from_xyz(-3.5, 0.0, -7.0);
|
}
|
||||||
cube_tran.rotate_y(math::Angle::Degrees(180.0));
|
|
||||||
world.spawn((
|
|
||||||
/* PointLight {
|
|
||||||
color: Vec3::new(1.0, 1.0, 1.0),
|
|
||||||
intensity: 1.0,
|
|
||||||
constant: 1.0,
|
|
||||||
linear: 0.045,
|
|
||||||
quadratic: 0.0075,
|
|
||||||
}, */
|
|
||||||
TransformComponent::from(cube_tran),
|
|
||||||
ModelComponent(crate_model.clone()),
|
|
||||||
CubeFlag,
|
|
||||||
));
|
|
||||||
|
|
||||||
let mut light_tran = Transform::from_xyz(1.5, 2.5, -8.5);
|
{
|
||||||
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
let mut light_tran = Transform::from_xyz(1.5, 2.5, 0.0);
|
||||||
world.spawn((
|
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
||||||
PointLight {
|
light_tran.rotate_x(math::Angle::Degrees(-45.0));
|
||||||
color: Vec3::new(1.0, 1.0, 1.0), //Vec3::new(0.361, 0.984, 0.0),
|
light_tran.rotate_y(math::Angle::Degrees(25.0));
|
||||||
intensity: 1.2,
|
world.spawn((
|
||||||
/* constant: 1.0,
|
DirectionalLight {
|
||||||
linear: 0.045,
|
color: Vec3::new(1.0, 1.0, 1.0),
|
||||||
quadratic: 0.0075, */
|
ambient: 0.3,
|
||||||
|
diffuse: 1.0,
|
||||||
|
specular: 1.3,
|
||||||
|
},
|
||||||
|
TransformComponent::from(light_tran),
|
||||||
|
ModelComponent(cube_model.clone()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
constant: 1.0,
|
{
|
||||||
linear: 0.09,
|
let mut light_tran = Transform::from_xyz(-3.5, 0.2, -4.5);
|
||||||
quadratic: 0.032,
|
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
||||||
|
world.spawn((
|
||||||
|
SpotLight {
|
||||||
|
color: Vec3::new(1.0, 0.2, 0.2),
|
||||||
|
cutoff: math::Angle::Degrees(12.5),
|
||||||
|
outer_cutoff: math::Angle::Degrees(17.5),
|
||||||
|
|
||||||
ambient: 0.3,
|
constant: 1.0,
|
||||||
diffuse: 1.0,
|
linear: 0.007,
|
||||||
specular: 1.3,
|
quadratic: 0.0002,
|
||||||
},
|
|
||||||
TransformComponent::from(light_tran),
|
ambient: 0.0,
|
||||||
ModelComponent(cube_model),
|
diffuse: 7.0,
|
||||||
));
|
specular: 1.0,
|
||||||
|
},
|
||||||
|
TransformComponent::from(light_tran),
|
||||||
|
ModelComponent(cube_model.clone()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* {
|
||||||
|
let mut light_tran = Transform::from_xyz(-5.0, 2.5, -9.5);
|
||||||
|
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
||||||
|
world.spawn((
|
||||||
|
PointLight {
|
||||||
|
color: Vec3::new(1.0, 1.0, 1.0),
|
||||||
|
|
||||||
|
intensity: 1.0,
|
||||||
|
|
||||||
|
constant: 1.0,
|
||||||
|
linear: 0.045,
|
||||||
|
quadratic: 0.0075,
|
||||||
|
|
||||||
|
ambient: 0.1,
|
||||||
|
diffuse: 1.0,
|
||||||
|
specular: 1.3,
|
||||||
|
},
|
||||||
|
TransformComponent::from(light_tran),
|
||||||
|
ModelComponent(cube_model.clone()),
|
||||||
|
));
|
||||||
|
} */
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut light_tran = Transform::from_xyz(2.0, 2.5, -9.5);
|
||||||
|
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
||||||
|
world.spawn((
|
||||||
|
PointLight {
|
||||||
|
color: Vec3::new(0.0, 0.0, 1.0),
|
||||||
|
|
||||||
|
intensity: 3.3,
|
||||||
|
|
||||||
|
constant: 1.0,
|
||||||
|
linear: 0.09,
|
||||||
|
quadratic: 0.032,
|
||||||
|
|
||||||
|
ambient: 0.2,
|
||||||
|
diffuse: 1.0,
|
||||||
|
specular: 1.3,
|
||||||
|
},
|
||||||
|
TransformComponent::from(light_tran),
|
||||||
|
ModelComponent(cube_model),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let mut camera = CameraComponent::new_3d();
|
let mut camera = CameraComponent::new_3d();
|
||||||
camera.transform.translation += math::Vec3::new(0.0, 0.0, 7.5);
|
camera.transform.translation += math::Vec3::new(0.0, 0.0, 5.5);
|
||||||
//camera.transform.rotate_y(Angle::Degrees(-25.0));
|
|
||||||
//camera.transform.rotate_z(math::Angle::Degrees(-90.0));
|
|
||||||
world.spawn(( camera, FreeFlyCamera::default() ));
|
world.spawn(( camera, FreeFlyCamera::default() ));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -156,7 +197,7 @@ async fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let spin_system = |world: &mut World| -> anyhow::Result<()> {
|
let spin_system = |world: &mut World| -> anyhow::Result<()> {
|
||||||
const SPEED: f32 = 7.0;
|
const SPEED: f32 = 4.0;
|
||||||
let delta_time = **world.get_resource::<DeltaTime>().unwrap();
|
let delta_time = **world.get_resource::<DeltaTime>().unwrap();
|
||||||
|
|
||||||
for (transform, _) in world.query_mut::<(&mut TransformComponent, &CubeFlag)>().iter_mut() {
|
for (transform, _) in world.query_mut::<(&mut TransformComponent, &CubeFlag)>().iter_mut() {
|
||||||
|
@ -164,6 +205,11 @@ async fn main() {
|
||||||
t.rotate_y(math::Angle::Degrees(SPEED * delta_time));
|
t.rotate_y(math::Angle::Degrees(SPEED * delta_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for (transform, s) in world.query_mut::<(&mut TransformComponent, &mut SpotLight)>().iter_mut() {
|
||||||
|
let t = &mut transform.transform;
|
||||||
|
t.rotate_x(math::Angle::Degrees(SPEED * delta_time));
|
||||||
|
} */
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub fn radians_to_degrees(radians: f32) -> f32 {
|
||||||
radians * 180.0 / PI
|
radians * 180.0 / PI
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Angle {
|
pub enum Angle {
|
||||||
Degrees(f32),
|
Degrees(f32),
|
||||||
Radians(f32),
|
Radians(f32),
|
||||||
|
@ -35,3 +35,37 @@ impl Angle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Add for Angle {
|
||||||
|
type Output = Angle;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Angle::Radians(self.to_radians() + rhs.to_radians())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::AddAssign for Angle {
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
match self {
|
||||||
|
Angle::Degrees(d) => *d += rhs.to_degrees(),
|
||||||
|
Angle::Radians(r) => *r += rhs.to_radians(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Sub for Angle {
|
||||||
|
type Output = Angle;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
Angle::Radians(self.to_radians() - rhs.to_radians())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::SubAssign for Angle {
|
||||||
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
|
match self {
|
||||||
|
Angle::Degrees(d) => *d -= rhs.to_degrees(),
|
||||||
|
Angle::Radians(r) => *r -= rhs.to_radians(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,9 @@
|
||||||
#[repr(C)]
|
#[derive(Default, Debug, Clone, edict::Component)]
|
||||||
#[derive(Default, Debug, Copy, Clone, edict::Component)]
|
|
||||||
pub struct DirectionalLight {
|
pub struct DirectionalLight {
|
||||||
pub direction: glam::Quat,
|
//pub direction: glam::Quat,
|
||||||
pub color: glam::Vec3,
|
pub color: glam::Vec3,
|
||||||
|
|
||||||
pub ambient: glam::Vec3,
|
pub ambient: f32,
|
||||||
pub diffuse: glam::Vec3,
|
pub diffuse: f32,
|
||||||
pub specular: glam::Vec3,
|
pub specular: f32,
|
||||||
}
|
}
|
|
@ -1,19 +1,27 @@
|
||||||
pub mod point;
|
pub mod point;
|
||||||
pub mod directional;
|
pub mod directional;
|
||||||
|
pub mod spotlight;
|
||||||
|
|
||||||
|
pub use point::*;
|
||||||
|
pub use directional::*;
|
||||||
|
pub use spotlight::*;
|
||||||
|
|
||||||
use std::{collections::{VecDeque, HashMap}, num::{NonZeroU64, NonZeroU32}, marker::PhantomData};
|
use std::{collections::{VecDeque, HashMap}, num::{NonZeroU64, NonZeroU32}, marker::PhantomData};
|
||||||
|
|
||||||
use edict::query::EpochOf;
|
use edict::query::EpochOf;
|
||||||
pub use point::*;
|
pub use point::*;
|
||||||
use tracing::debug;
|
use tracing::{debug, Instrument};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use crate::{math::Transform, ecs::components::TransformComponent};
|
use crate::{math::Transform, ecs::components::TransformComponent};
|
||||||
|
|
||||||
|
use self::directional::DirectionalLight;
|
||||||
|
|
||||||
const MAX_LIGHT_COUNT: usize = 16;
|
const MAX_LIGHT_COUNT: usize = 16;
|
||||||
|
|
||||||
|
/// A struct that stores a list of lights in a wgpu::Buffer.
|
||||||
pub struct LightBuffer<U: Default + bytemuck::Pod + bytemuck::Zeroable> {
|
pub struct LightBuffer<U: Default + bytemuck::Pod + bytemuck::Zeroable> {
|
||||||
_phantom: PhantomData<U>,
|
_phantom: PhantomData<U>,
|
||||||
/// The max amount of light casters that could fit in this buffer.
|
/// The max amount of light casters that could fit in this buffer.
|
||||||
|
@ -102,15 +110,16 @@ pub struct LightUniformBuffers {
|
||||||
pub bindgroup: wgpu::BindGroup,
|
pub bindgroup: wgpu::BindGroup,
|
||||||
pub lights_uniform: LightsUniform,
|
pub lights_uniform: LightsUniform,
|
||||||
pub point_lights: LightBuffer<PointLightUniform>,
|
pub point_lights: LightBuffer<PointLightUniform>,
|
||||||
|
pub spot_lights: LightBuffer<SpotLightUniform>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightUniformBuffers {
|
impl LightUniformBuffers {
|
||||||
pub fn new(device: &wgpu::Device) -> Self {
|
pub fn new(device: &wgpu::Device) -> Self {
|
||||||
let buffer = device.create_buffer(
|
let buffer = device.create_buffer(
|
||||||
&wgpu::BufferDescriptor {
|
&wgpu::BufferDescriptor {
|
||||||
label: Some("UB_Lights"),
|
label: Some("UBO_Lights"),
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
size: (mem::size_of::<LightsUniform>() * MAX_LIGHT_COUNT) as u64,
|
size: mem::size_of::<LightsUniform>() as u64,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -149,6 +158,7 @@ impl LightUniformBuffers {
|
||||||
});
|
});
|
||||||
|
|
||||||
let point_lights = LightBuffer::new(&bindgroup_layout, MAX_LIGHT_COUNT);
|
let point_lights = LightBuffer::new(&bindgroup_layout, MAX_LIGHT_COUNT);
|
||||||
|
let spot_lights = LightBuffer::new(&bindgroup_layout, MAX_LIGHT_COUNT);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
buffer,
|
buffer,
|
||||||
|
@ -156,6 +166,7 @@ impl LightUniformBuffers {
|
||||||
bindgroup,
|
bindgroup,
|
||||||
lights_uniform: LightsUniform::default(),
|
lights_uniform: LightsUniform::default(),
|
||||||
point_lights,
|
point_lights,
|
||||||
|
spot_lights,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,10 +177,29 @@ impl LightUniformBuffers {
|
||||||
if !self.point_lights.has_light(entity) || light_epoch == world_epoch || transform_epoch == world_epoch {
|
if !self.point_lights.has_light(entity) || light_epoch == world_epoch || transform_epoch == world_epoch {
|
||||||
let uniform = PointLightUniform::from_bundle(point_light, &transform.transform);
|
let uniform = PointLightUniform::from_bundle(point_light, &transform.transform);
|
||||||
self.point_lights.update_or_add(&mut self.lights_uniform.point_lights, entity, uniform);
|
self.point_lights.update_or_add(&mut self.lights_uniform.point_lights, entity, uniform);
|
||||||
|
debug!("Updated point light");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (entity, spot_light, transform, light_epoch, transform_epoch)
|
||||||
|
in world.query::<(edict::Entities, &SpotLight, &TransformComponent, EpochOf<SpotLight>, EpochOf<TransformComponent>)>().iter() {
|
||||||
|
|
||||||
|
if !self.spot_lights.has_light(entity) || light_epoch == world_epoch || transform_epoch == world_epoch {
|
||||||
|
let uniform = SpotLightUniform::from_bundle(spot_light, &transform.transform);
|
||||||
|
self.spot_lights.update_or_add(&mut self.lights_uniform.spot_lights, entity, uniform);
|
||||||
|
//debug!("Updated spot light");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((dir_light, transform)) =
|
||||||
|
world.query::<(&DirectionalLight, &TransformComponent)>().iter().next() {
|
||||||
|
|
||||||
|
let uniform = DirectionalLightUniform::from_bundle(dir_light, &transform.transform);
|
||||||
|
self.lights_uniform.directional_light = uniform;
|
||||||
|
}
|
||||||
|
|
||||||
self.lights_uniform.point_light_count = self.point_lights.buffer_count as u32;
|
self.lights_uniform.point_light_count = self.point_lights.buffer_count as u32;
|
||||||
|
self.lights_uniform.spot_light_count = self.spot_lights.buffer_count as u32;
|
||||||
queue.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[self.lights_uniform]));
|
queue.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[self.lights_uniform]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,6 +210,10 @@ pub struct LightsUniform {
|
||||||
point_lights: [PointLightUniform; MAX_LIGHT_COUNT],
|
point_lights: [PointLightUniform; MAX_LIGHT_COUNT],
|
||||||
point_light_count: u32,
|
point_light_count: u32,
|
||||||
_padding: [u32; 3],
|
_padding: [u32; 3],
|
||||||
|
spot_lights: [SpotLightUniform; MAX_LIGHT_COUNT],
|
||||||
|
spot_light_count: u32,
|
||||||
|
_padding2: [u32; 3],
|
||||||
|
directional_light: DirectionalLightUniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -188,17 +222,22 @@ pub struct PointLightUniform {
|
||||||
/// The position of the light
|
/// The position of the light
|
||||||
/// vec4 is used here for gpu padding, w is ignored in the shader
|
/// vec4 is used here for gpu padding, w is ignored in the shader
|
||||||
pub position: glam::Vec4,
|
pub position: glam::Vec4,
|
||||||
|
|
||||||
/// The color of the light
|
/// The color of the light
|
||||||
/// vec4 is used here for gpu padding, w is ignored in the shader
|
/// vec4 is used here for gpu padding, w is ignored in the shader
|
||||||
pub color: glam::Vec4,
|
pub color: glam::Vec4,
|
||||||
|
|
||||||
/// The intensity of the light
|
/// The intensity of the light
|
||||||
/// This works by just multiplying the result of the lighting
|
/// This works by just multiplying the result of the lighting
|
||||||
/// calculations by this scalar
|
/// calculations by this scalar
|
||||||
pub intensity: f32,
|
pub intensity: f32,
|
||||||
|
|
||||||
/// The constant used in the quadratic attenuation calculation. Its best to leave this at 1.0
|
/// The constant used in the quadratic attenuation calculation. Its best to leave this at 1.0
|
||||||
pub constant: f32,
|
pub constant: f32,
|
||||||
|
|
||||||
/// The linear factor used in the quadratic attenuation calculation.
|
/// The linear factor used in the quadratic attenuation calculation.
|
||||||
pub linear: f32,
|
pub linear: f32,
|
||||||
|
|
||||||
/// The quadratic factor used in the quadratic attenuation calculation.
|
/// The quadratic factor used in the quadratic attenuation calculation.
|
||||||
pub quadratic: f32,
|
pub quadratic: f32,
|
||||||
|
|
||||||
|
@ -230,3 +269,92 @@ impl PointLightUniform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Default, Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
|
pub struct DirectionalLightUniform {
|
||||||
|
/// The direction of the light
|
||||||
|
pub direction: glam::Vec3,
|
||||||
|
// gpu padding
|
||||||
|
pub _padding: u32,
|
||||||
|
/// The color of the light
|
||||||
|
pub color: glam::Vec3,
|
||||||
|
// no padding is needed here since ambient acts as the padding
|
||||||
|
// that would usually be needed for the vec3
|
||||||
|
|
||||||
|
/// The scalar of the ambient light created by this caster.
|
||||||
|
pub ambient: f32,
|
||||||
|
/// The scalar of the diffuse light created by this caster.
|
||||||
|
pub diffuse: f32,
|
||||||
|
/// The scalar of the specular reflections created by this caster.
|
||||||
|
pub specular: f32,
|
||||||
|
|
||||||
|
pub _padding2: [u32; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DirectionalLightUniform {
|
||||||
|
/// Create the DirectionalLightUniform from an ECS bundle
|
||||||
|
pub fn from_bundle(light: &DirectionalLight, transform: &Transform) -> Self {
|
||||||
|
//transform.forward()
|
||||||
|
Self {
|
||||||
|
direction: transform.forward(),
|
||||||
|
_padding: 0,
|
||||||
|
color: light.color,
|
||||||
|
ambient: light.ambient,
|
||||||
|
diffuse: light.diffuse,
|
||||||
|
specular: light.specular,
|
||||||
|
_padding2: [0; 2],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Default, Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
|
struct SpotLightUniform {
|
||||||
|
pub position: glam::Vec3,
|
||||||
|
pub _padding: u32,
|
||||||
|
pub direction: glam::Vec3,
|
||||||
|
pub _padding2: u32,
|
||||||
|
pub color: glam::Vec3,
|
||||||
|
// no padding is needed here since cutoff acts as the padding
|
||||||
|
// that would usually be needed for the vec3
|
||||||
|
|
||||||
|
pub cutoff: f32,
|
||||||
|
pub outer_cutoff: f32,
|
||||||
|
|
||||||
|
/// The constant used in the quadratic attenuation calculation. Its best to leave this at 1.0
|
||||||
|
pub constant: f32,
|
||||||
|
|
||||||
|
/// The linear factor used in the quadratic attenuation calculation.
|
||||||
|
pub linear: f32,
|
||||||
|
|
||||||
|
/// The quadratic factor used in the quadratic attenuation calculation.
|
||||||
|
pub quadratic: f32,
|
||||||
|
|
||||||
|
pub ambient: f32,
|
||||||
|
pub diffuse: f32,
|
||||||
|
pub specular: f32,
|
||||||
|
pub _padding3: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpotLightUniform {
|
||||||
|
/// Create the SpotLightUniform from an ECS bundle
|
||||||
|
pub fn from_bundle(light: &SpotLight, transform: &Transform) -> Self {
|
||||||
|
Self {
|
||||||
|
position: transform.translation,
|
||||||
|
_padding: 0,
|
||||||
|
direction: transform.forward(),
|
||||||
|
_padding2: 0,
|
||||||
|
color: light.color,
|
||||||
|
cutoff: light.cutoff.to_radians().cos(),
|
||||||
|
outer_cutoff: light.outer_cutoff.to_radians().cos(),
|
||||||
|
constant: light.constant,
|
||||||
|
linear: light.linear,
|
||||||
|
quadratic: light.quadratic,
|
||||||
|
ambient: light.ambient,
|
||||||
|
diffuse: light.diffuse,
|
||||||
|
specular: light.specular,
|
||||||
|
_padding3: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
#[repr(C)]
|
#[derive(Default, Debug, Clone, edict::Component)]
|
||||||
#[derive(Default, Debug, Copy, Clone, edict::Component)]
|
|
||||||
pub struct PointLight {
|
pub struct PointLight {
|
||||||
pub color: glam::Vec3,
|
pub color: glam::Vec3,
|
||||||
pub intensity: f32,
|
pub intensity: f32,
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
use crate::math;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, edict::Component)]
|
||||||
|
pub struct SpotLight {
|
||||||
|
pub color: glam::Vec3,
|
||||||
|
pub cutoff: math::Angle,
|
||||||
|
pub outer_cutoff: math::Angle,
|
||||||
|
|
||||||
|
pub constant: f32,
|
||||||
|
pub linear: f32,
|
||||||
|
pub quadratic: f32,
|
||||||
|
|
||||||
|
pub ambient: f32,
|
||||||
|
pub diffuse: f32,
|
||||||
|
pub specular: f32,
|
||||||
|
}
|
|
@ -40,9 +40,38 @@ struct PointLight {
|
||||||
specular: f32,
|
specular: f32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DirectionalLight {
|
||||||
|
direction: vec3<f32>,
|
||||||
|
color: vec3<f32>,
|
||||||
|
|
||||||
|
ambient: f32,
|
||||||
|
diffuse: f32,
|
||||||
|
specular: f32,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SpotLight {
|
||||||
|
position: vec3<f32>,
|
||||||
|
direction: vec3<f32>,
|
||||||
|
color: vec3<f32>,
|
||||||
|
|
||||||
|
cutoff: f32,
|
||||||
|
outer_cutoff: f32,
|
||||||
|
|
||||||
|
constant: f32,
|
||||||
|
linear: f32,
|
||||||
|
quadratic: f32,
|
||||||
|
|
||||||
|
ambient: f32,
|
||||||
|
diffuse: f32,
|
||||||
|
specular: f32,
|
||||||
|
};
|
||||||
|
|
||||||
struct Lights {
|
struct Lights {
|
||||||
point_lights: array<PointLight, max_light_count>,
|
point_lights: array<PointLight, max_light_count>,
|
||||||
point_light_count: u32,
|
point_light_count: u32,
|
||||||
|
spot_lights: array<SpotLight, max_light_count>,
|
||||||
|
spot_light_count: u32,
|
||||||
|
directional_light: DirectionalLight,
|
||||||
}
|
}
|
||||||
|
|
||||||
@group(1) @binding(0)
|
@group(1) @binding(0)
|
||||||
|
@ -110,22 +139,59 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
let object_color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.tex_coords);
|
let object_color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.tex_coords);
|
||||||
let specular_color: vec3<f32> = textureSample(t_specular, s_specular, in.tex_coords).xyz;
|
let specular_color: vec3<f32> = textureSample(t_specular, s_specular, in.tex_coords).xyz;
|
||||||
|
|
||||||
var light_res = vec3<f32>(0.0);
|
// this needs to be 0.0 for the math
|
||||||
|
//u_lights.directional_light.direction.w = 0.0;
|
||||||
|
|
||||||
|
var light_res = blinn_phong_dir_light(in.world_position, in.world_normal, u_lights.directional_light, u_material, specular_color);
|
||||||
|
|
||||||
for (var i = 0u; i < u_lights.point_light_count; i++) {
|
for (var i = 0u; i < u_lights.point_light_count; i++) {
|
||||||
light_res += blinn_phong_point_light(in.world_position, in.world_normal, u_lights.point_lights[i], u_material, specular_color);
|
light_res += blinn_phong_point_light(in.world_position, in.world_normal, u_lights.point_lights[i], u_material, specular_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var i = 0u; i < u_lights.spot_light_count; i++) {
|
||||||
|
light_res += blinn_phong_spot_light(in.world_position, in.world_normal, u_lights.spot_lights[i], u_material, specular_color);
|
||||||
|
}
|
||||||
|
|
||||||
let light_object_res = light_res * (object_color.xyz/* * u_material.diffuse.xyz*/);
|
let light_object_res = light_res * (object_color.xyz/* * u_material.diffuse.xyz*/);
|
||||||
|
|
||||||
return vec4<f32>(light_object_res, object_color.a);
|
return vec4<f32>(light_object_res, object_color.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn blinn_phong_dir_light(world_pos: vec3<f32>, world_norm: vec3<f32>, dir_light: DirectionalLight, material: Material, specular_factor: vec3<f32>) -> vec3<f32> {
|
||||||
|
let light_color = dir_light.color.xyz;
|
||||||
|
let camera_view_pos = u_camera.view_pos.xyz;
|
||||||
|
|
||||||
|
//// Ambient light ////
|
||||||
|
var ambient_color = light_color * material.ambient.xyz * material.diffuse.xyz;
|
||||||
|
|
||||||
|
//// diffuse ////
|
||||||
|
let light_dir = normalize(-dir_light.direction);
|
||||||
|
|
||||||
|
let diffuse_strength = max(dot(world_norm, light_dir), 0.0);
|
||||||
|
var diffuse_color = light_color * (diffuse_strength * material.diffuse.xyz);
|
||||||
|
//// end of diffuse ////
|
||||||
|
|
||||||
|
//// specular ////
|
||||||
|
let view_dir = normalize(camera_view_pos - world_pos);
|
||||||
|
let half_dir = normalize(view_dir + light_dir);
|
||||||
|
|
||||||
|
let specular_strength = pow(max(dot(world_norm, half_dir), 0.0), material.shininess);
|
||||||
|
var specular_color = specular_strength * (light_color * specular_factor);
|
||||||
|
//// end of specular ////
|
||||||
|
|
||||||
|
ambient_color *= dir_light.ambient;
|
||||||
|
diffuse_color *= dir_light.diffuse;
|
||||||
|
specular_color *= dir_light.specular;
|
||||||
|
|
||||||
|
return ambient_color + diffuse_color + specular_color;
|
||||||
|
}
|
||||||
|
|
||||||
fn blinn_phong_point_light(world_pos: vec3<f32>, world_norm: vec3<f32>, point_light: PointLight, material: Material, specular_factor: vec3<f32>) -> vec3<f32> {
|
fn blinn_phong_point_light(world_pos: vec3<f32>, world_norm: vec3<f32>, point_light: PointLight, material: Material, specular_factor: vec3<f32>) -> vec3<f32> {
|
||||||
let light_color = point_light.color.xyz;
|
let light_color = point_light.color.xyz;
|
||||||
let light_pos = point_light.position.xyz;
|
let light_pos = point_light.position.xyz;
|
||||||
let camera_view_pos = u_camera.view_pos.xyz;
|
let camera_view_pos = u_camera.view_pos.xyz;
|
||||||
|
|
||||||
// We don't need (or want) much ambient light, so 0.1 is fine
|
//// Ambient light ////
|
||||||
//let ambient_strength = 0.1;
|
|
||||||
var ambient_color = light_color * material.ambient.xyz * material.diffuse.xyz;
|
var ambient_color = light_color * material.ambient.xyz * material.diffuse.xyz;
|
||||||
|
|
||||||
//// diffuse ////
|
//// diffuse ////
|
||||||
|
@ -146,18 +212,69 @@ fn blinn_phong_point_light(world_pos: vec3<f32>, world_norm: vec3<f32>, point_li
|
||||||
//// end of specular ////
|
//// end of specular ////
|
||||||
|
|
||||||
//// point light attenuation ////
|
//// point light attenuation ////
|
||||||
/*let distance = length(light_pos - world_pos);
|
let distance = length(light_pos - world_pos);
|
||||||
let attenuation = 1.0 / (point_light.constant + point_light.linear * distance +
|
let attenuation = 1.0 / (point_light.constant + point_light.linear * distance +
|
||||||
point_light.quadratic * (distance * distance));*/
|
point_light.quadratic * (distance * distance));
|
||||||
|
|
||||||
//ambient_color *= attenuation * point_light.intensity * point_light.ambient;
|
//ambient_color *= attenuation * point_light.intensity * point_light.ambient;
|
||||||
//diffuse_color *= attenuation * point_light.intensity * point_light.diffuse;
|
//diffuse_color *= attenuation * point_light.intensity * point_light.diffuse;
|
||||||
//specular_color *= attenuation * point_light.intensity * point_light.specular;
|
//specular_color *= attenuation * point_light.intensity * point_light.specular;
|
||||||
//// end of point light attenuation ////
|
//// end of point light attenuation ////
|
||||||
|
|
||||||
ambient_color *= point_light.ambient;
|
ambient_color *= point_light.ambient * attenuation;
|
||||||
diffuse_color *= point_light.diffuse;
|
diffuse_color *= point_light.diffuse * attenuation;
|
||||||
specular_color *= point_light.specular;
|
specular_color *= point_light.specular * attenuation;
|
||||||
|
|
||||||
return (ambient_color + diffuse_color + specular_color) * /*attenuation * */ point_light.intensity;
|
return (ambient_color + diffuse_color + specular_color) * point_light.intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blinn_phong_spot_light(world_pos: vec3<f32>, world_norm: vec3<f32>, spot_light: SpotLight, material: Material, specular_factor: vec3<f32>) -> vec3<f32> {
|
||||||
|
let light_color = spot_light.color;//.xyz;
|
||||||
|
let light_pos = spot_light.position.xyz;
|
||||||
|
let camera_view_pos = u_camera.view_pos.xyz;
|
||||||
|
|
||||||
|
let light_dir = normalize(spot_light.position - world_pos);
|
||||||
|
|
||||||
|
|
||||||
|
//if (theta > spot_light.cutoff) {
|
||||||
|
var ambient_color = light_color * material.ambient.xyz * material.diffuse.xyz;
|
||||||
|
|
||||||
|
//// diffuse ////
|
||||||
|
//let light_dir = normalize(light_pos - world_pos);
|
||||||
|
|
||||||
|
let diffuse_strength = max(dot(world_norm, light_dir), 0.0);
|
||||||
|
var diffuse_color = light_color * (diffuse_strength * material.diffuse.xyz);
|
||||||
|
//// end of diffuse ////
|
||||||
|
|
||||||
|
//// specular ////
|
||||||
|
let view_dir = normalize(camera_view_pos - world_pos);
|
||||||
|
let half_dir = normalize(view_dir + light_dir);
|
||||||
|
|
||||||
|
let specular_strength = pow(max(dot(world_norm, half_dir), 0.0), material.shininess);
|
||||||
|
var specular_color = specular_strength * (light_color * specular_factor);
|
||||||
|
//// end of specular ////
|
||||||
|
|
||||||
|
//// spot light soft edges ////
|
||||||
|
let theta = dot(light_dir, normalize(-spot_light.direction));
|
||||||
|
let epsilon = spot_light.cutoff - spot_light.outer_cutoff;
|
||||||
|
let intensity = clamp((theta - spot_light.outer_cutoff) / epsilon, 0.0, 1.0);
|
||||||
|
//diffuse_color *= intensity;
|
||||||
|
//specular_color *= intensity;
|
||||||
|
//// end of spot light soft edges ////
|
||||||
|
|
||||||
|
//// spot light attenuation ////
|
||||||
|
let distance = length(light_pos - world_pos);
|
||||||
|
let attenuation = 1.0 / (spot_light.constant + spot_light.linear * distance +
|
||||||
|
spot_light.quadratic * (distance * distance));
|
||||||
|
|
||||||
|
ambient_color *= attenuation * intensity * spot_light.ambient;
|
||||||
|
diffuse_color *= attenuation * intensity * spot_light.diffuse;
|
||||||
|
specular_color *= attenuation * intensity * spot_light.specular;
|
||||||
|
//// end of spot light attenuation ////
|
||||||
|
|
||||||
|
|
||||||
|
return /*ambient_color +*/ diffuse_color + specular_color;
|
||||||
|
/*} else {
|
||||||
|
return vec3<f32>(0.0);
|
||||||
|
}*/
|
||||||
}
|
}
|
Loading…
Reference in New Issue