Create a PointLight component for light position
ci/woodpecker/push/build Pipeline was successful Details

This commit is contained in:
SeanOMik 2023-11-10 12:28:17 -05:00
parent e95a45fd53
commit d26e1ccfb4
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
5 changed files with 99 additions and 30 deletions

View File

@ -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}, 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}, change_tracker::Ct};
use lyra_engine::assets::{ResourceManager, Model}; use lyra_engine::assets::{ResourceManager, Model};
mod free_fly_camera; mod free_fly_camera;
@ -69,7 +69,7 @@ async fn main() {
let mut resman = world.get_resource_mut::<ResourceManager>().unwrap(); let mut resman = world.get_resource_mut::<ResourceManager>().unwrap();
//let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap(); //let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap(); let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
//let cube_model = resman.request::<Model>("assets/texture-sep/texture-sep.gltf").unwrap(); let cube_model = resman.request::<Model>("assets/cube-texture-bin.glb").unwrap();
drop(resman); drop(resman);
/* world.spawn(( /* world.spawn((
@ -82,6 +82,27 @@ async fn main() {
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),
position: Vec3::new(0.0, -5.0, -8.0),
constant: 1.0,
linear: 0.09,
quadratic: 0.032,
};
world.spawn((light,)); */
let pos = Vec3::new(0.0, 0.0, -10.0);
world.spawn((
PointLight {
color: Vec3::new(1.0, 1.0, 1.0),
intensity: 2.0,
constant: 1.0,
linear: 0.045,
quadratic: 0.0075,
},
TransformComponent::from(Transform::from_xyz(pos.x, pos.y, pos.z)),
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, 7.5);
//camera.transform.rotate_y(Angle::Degrees(-25.0)); //camera.transform.rotate_y(Angle::Degrees(-25.0));

View File

@ -1,6 +1,8 @@
pub mod point; pub mod point;
pub use point::*; pub use point::*;
use crate::math::Transform;
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct LightUniform { pub struct LightUniform {
@ -11,3 +13,40 @@ pub struct LightUniform {
// Due to uniforms requiring 16 byte (4 float) spacing, we need to use a padding field here // Due to uniforms requiring 16 byte (4 float) spacing, we need to use a padding field here
pub(crate) _padding2: u32, pub(crate) _padding2: u32,
} }
#[repr(C)]
#[derive(Default, Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct PointLightUniform {
/// The position of the light
/// vec4 is used here for gpu padding, w is ignored in the shader
pub position: glam::Vec4,
/// The color of the light
/// vec4 is used here for gpu padding, w is ignored in the shader
pub color: glam::Vec4,
/// The intensity of the light
/// This works by just multiplying the result of the lighting
/// calculations by this scalar
pub intensity: 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,
}
impl PointLightUniform {
/// Create the PointLightUniform from an ECS bundle
pub fn from_bundle(light: &PointLight, transform: &Transform) -> Self {
Self {
position: glam::Vec4::new(transform.translation.x, transform.translation.y, transform.translation.z, 0.0),
//_padding: 0,
color: glam::Vec4::new(light.color.x, light.color.y, light.color.z, 0.0),
//_padding2: 0,
intensity: light.intensity,
constant: light.constant,
linear: light.linear,
quadratic: light.quadratic,
}
}
}

View File

@ -1,6 +1,9 @@
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Default, Debug, Copy, Clone, edict::Component)]
pub struct PointLight { pub struct PointLight {
position: glam::Vec3, pub color: glam::Vec3,
color: glam::Vec3, pub intensity: f32,
pub constant: f32,
pub linear: f32,
pub quadratic: f32,
} }

View File

@ -18,10 +18,11 @@ use crate::ecs::components::camera::CameraComponent;
use crate::ecs::components::model::ModelComponent; use crate::ecs::components::model::ModelComponent;
use crate::ecs::components::transform::TransformComponent; use crate::ecs::components::transform::TransformComponent;
use crate::math::{Transform, self}; use crate::math::{Transform, self};
use crate::render::light::PointLightUniform;
use super::camera::{RenderCamera, CameraUniform}; use super::camera::{RenderCamera, CameraUniform};
use super::desc_buf_lay::DescVertexBufferLayout; use super::desc_buf_lay::DescVertexBufferLayout;
use super::light::LightUniform; use super::light::{LightUniform, PointLight};
use super::texture::RenderTexture; use super::texture::RenderTexture;
use super::transform_buffer_storage::{TransformBufferIndices, TransformBuffers}; use super::transform_buffer_storage::{TransformBufferIndices, TransformBuffers};
use super::vertex::Vertex; use super::vertex::Vertex;
@ -90,7 +91,6 @@ pub struct BasicRenderer {
default_texture_bind_group: BindGroup, default_texture_bind_group: BindGroup,
depth_buffer_texture: RenderTexture, depth_buffer_texture: RenderTexture,
point_light_uniform: LightUniform,
point_light_buffer: wgpu::Buffer, point_light_buffer: wgpu::Buffer,
point_light_bind_group_layout: BindGroupLayout, point_light_bind_group_layout: BindGroupLayout,
point_light_bind_group: BindGroup, point_light_bind_group: BindGroup,
@ -243,16 +243,10 @@ impl BasicRenderer {
next_indices: TransformBufferIndices { buffer_index: 0, transform_index: 0 }, next_indices: TransformBufferIndices { buffer_index: 0, transform_index: 0 },
}; };
let point_light_uniform = LightUniform {
position: glam::Vec3::new(0.0, -2.0, -13.0),
_padding: 0,
color: glam::Vec3::new(1.0, 1.0, 1.0),
_padding2: 0,
};
let point_light_buffer = device.create_buffer_init( let point_light_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor { &wgpu::util::BufferInitDescriptor {
label: Some("Point Light Buffer"), label: Some("Point Light Buffer"),
contents: bytemuck::cast_slice(&[glam::Mat4::IDENTITY]), contents: bytemuck::cast_slice(&[PointLightUniform::default()]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
} }
); );
@ -372,7 +366,6 @@ impl BasicRenderer {
depth_buffer_texture: depth_texture, depth_buffer_texture: depth_texture,
entity_last_transforms: HashMap::new(), entity_last_transforms: HashMap::new(),
point_light_uniform,
point_light_buffer, point_light_buffer,
point_light_bind_group_layout, point_light_bind_group_layout,
point_light_bind_group, point_light_bind_group,
@ -654,11 +647,9 @@ impl Renderer for BasicRenderer {
warn!("Missing camera!"); warn!("Missing camera!");
} }
{ for (point_light, transform) in main_world.query::<(&PointLight, &TransformComponent)>().iter() {
let old_pos = self.point_light_uniform.position; let uniform = PointLightUniform::from_bundle(point_light, &transform.transform);
self.point_light_uniform.position = glam::Quat::from_axis_angle(glam::Vec3::Z, self.queue.write_buffer(&self.point_light_buffer, 0, bytemuck::cast_slice(&[uniform]));
math::Angle::Degrees(1.0).to_radians()) * old_pos;
self.queue.write_buffer(&self.point_light_buffer, 0, bytemuck::cast_slice(&[self.point_light_uniform]));
} }
} }

View File

@ -19,8 +19,12 @@ struct CameraUniform {
}; };
struct PointLight { struct PointLight {
position: vec3<f32>, position: vec4<f32>,
color: vec3<f32>, color: vec4<f32>,
intensity: f32,
constant: f32,
linear: f32,
quadratic: f32,
}; };
@group(1) @binding(0) @group(1) @binding(0)
@ -32,7 +36,6 @@ var<uniform> camera: CameraUniform;
@group(3) @binding(0) @group(3) @binding(0)
var<uniform> point_light: PointLight; var<uniform> point_light: PointLight;
@vertex @vertex
fn vs_main( fn vs_main(
model: VertexInput, model: VertexInput,
@ -63,29 +66,41 @@ var s_diffuse: sampler;
@fragment @fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
//return textureSample(t_diffuse, s_diffuse, in.tex_coords); let light_color = point_light.color.xyz;
let light_pos = point_light.position.xyz;
let camera_view_pos = camera.view_pos.xyz;
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);
// We don't need (or want) much ambient light, so 0.1 is fine // We don't need (or want) much ambient light, so 0.1 is fine
let ambient_strength = 0.1; let ambient_strength = 0.1;
let ambient_color = point_light.color * ambient_strength; var ambient_color = light_color * ambient_strength;
//// diffuse //// //// diffuse ////
let light_dir = normalize(point_light.position - in.world_position); let light_dir = normalize(light_pos - in.world_position);
let diffuse_strength = max(dot(in.world_normal, light_dir), 0.0); let diffuse_strength = max(dot(in.world_normal, light_dir), 0.0);
let diffuse_color = point_light.color * diffuse_strength; var diffuse_color = light_color * diffuse_strength;
//// end of diffuse //// //// end of diffuse ////
//// specular //// //// specular ////
let view_dir = normalize(camera.view_pos.xyz - in.world_position); let view_dir = normalize(camera_view_pos - in.world_position);
let half_dir = normalize(view_dir + light_dir); let half_dir = normalize(view_dir + light_dir);
let specular_strength = pow(max(dot(in.world_normal, half_dir), 0.0), 32.0); let specular_strength = pow(max(dot(in.world_normal, half_dir), 0.0), 32.0);
let specular_color = specular_strength * point_light.color; var specular_color = specular_strength * light_color;
//// end of specular //// //// end of specular ////
//// point light attenuation ////
let distance = length(light_pos - in.world_position);
let attenuation = 1.0 / (point_light.constant + point_light.linear * distance +
point_light.quadratic * (distance * distance));
ambient_color *= attenuation * point_light.intensity;
diffuse_color *= attenuation * point_light.intensity;
specular_color *= attenuation * point_light.intensity;
//// end of point light attenuation ////
let result = (ambient_color + diffuse_color + specular_color) * object_color.xyz; let result = (ambient_color + diffuse_color + specular_color) * object_color.xyz;
return vec4<f32>(result, object_color.a); return vec4<f32>(result, object_color.a);