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};
mod free_fly_camera;
@ -69,7 +69,7 @@ async fn main() {
let mut resman = world.get_resource_mut::<ResourceManager>().unwrap();
//let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").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);
/* world.spawn((
@ -82,6 +82,27 @@ async fn main() {
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();
camera.transform.translation += math::Vec3::new(0.0, 0.0, 7.5);
//camera.transform.rotate_y(Angle::Degrees(-25.0));

View File

@ -1,6 +1,8 @@
pub mod point;
pub use point::*;
use crate::math::Transform;
#[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
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
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)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
#[derive(Default, Debug, Copy, Clone, edict::Component)]
pub struct PointLight {
position: glam::Vec3,
color: glam::Vec3,
pub 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::transform::TransformComponent;
use crate::math::{Transform, self};
use crate::render::light::PointLightUniform;
use super::camera::{RenderCamera, CameraUniform};
use super::desc_buf_lay::DescVertexBufferLayout;
use super::light::LightUniform;
use super::light::{LightUniform, PointLight};
use super::texture::RenderTexture;
use super::transform_buffer_storage::{TransformBufferIndices, TransformBuffers};
use super::vertex::Vertex;
@ -90,7 +91,6 @@ pub struct BasicRenderer {
default_texture_bind_group: BindGroup,
depth_buffer_texture: RenderTexture,
point_light_uniform: LightUniform,
point_light_buffer: wgpu::Buffer,
point_light_bind_group_layout: BindGroupLayout,
point_light_bind_group: BindGroup,
@ -243,16 +243,10 @@ impl BasicRenderer {
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(
&wgpu::util::BufferInitDescriptor {
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,
}
);
@ -372,7 +366,6 @@ impl BasicRenderer {
depth_buffer_texture: depth_texture,
entity_last_transforms: HashMap::new(),
point_light_uniform,
point_light_buffer,
point_light_bind_group_layout,
point_light_bind_group,
@ -654,11 +647,9 @@ impl Renderer for BasicRenderer {
warn!("Missing camera!");
}
{
let old_pos = self.point_light_uniform.position;
self.point_light_uniform.position = glam::Quat::from_axis_angle(glam::Vec3::Z,
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]));
for (point_light, transform) in main_world.query::<(&PointLight, &TransformComponent)>().iter() {
let uniform = PointLightUniform::from_bundle(point_light, &transform.transform);
self.queue.write_buffer(&self.point_light_buffer, 0, bytemuck::cast_slice(&[uniform]));
}
}

View File

@ -19,8 +19,12 @@ struct CameraUniform {
};
struct PointLight {
position: vec3<f32>,
color: vec3<f32>,
position: vec4<f32>,
color: vec4<f32>,
intensity: f32,
constant: f32,
linear: f32,
quadratic: f32,
};
@group(1) @binding(0)
@ -32,7 +36,6 @@ var<uniform> camera: CameraUniform;
@group(3) @binding(0)
var<uniform> point_light: PointLight;
@vertex
fn vs_main(
model: VertexInput,
@ -63,29 +66,41 @@ var s_diffuse: sampler;
@fragment
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);
// We don't need (or want) much ambient light, so 0.1 is fine
let ambient_strength = 0.1;
let ambient_color = point_light.color * ambient_strength;
var ambient_color = light_color * ambient_strength;
//// 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_color = point_light.color * diffuse_strength;
var diffuse_color = light_color * diffuse_strength;
//// end of diffuse ////
//// 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 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 ////
//// 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;
return vec4<f32>(result, object_color.a);