From 012ce430111b58806d4ef5a0b289d61b85d075a1 Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Thu, 7 Dec 2023 02:35:32 -0700 Subject: [PATCH 1/9] Define PointLight and supporting handles --- rend3-types/src/lib.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rend3-types/src/lib.rs b/rend3-types/src/lib.rs index 6397043e..84351281 100644 --- a/rend3-types/src/lib.rs +++ b/rend3-types/src/lib.rs @@ -187,6 +187,8 @@ pub type MaterialHandle = ResourceHandle; pub type ObjectHandle = ResourceHandle; /// Refcounted handle to a DirectionalLight pub type DirectionalLightHandle = ResourceHandle; +/// Refcounted handle to a PointLight +pub type PointLightHandle = ResourceHandle; /// Refcounted handle to a Skeleton pub type SkeletonHandle = ResourceHandle; /// Refcounted handle to an instance of GraphData with the type erased @@ -218,6 +220,8 @@ pub type RawMaterialHandle = RawResourceHandle; pub type RawObjectHandle = RawResourceHandle; /// Internal non-owning handle to a DirectionalLight pub type RawDirectionalLightHandle = RawResourceHandle; +/// Internal non-owning handle to a PointLight +pub type RawPointLightHandle = RawResourceHandle; /// Internal non-owning handle to a Skeleton pub type RawSkeletonHandle = RawResourceHandle; /// Internal non-owning handle to an instance of GraphData with the type erased @@ -1156,6 +1160,23 @@ changeable_struct! { } } +changeable_struct! { + /// Describes how point lights and their shadows should be processed. + pub struct PointLight <- PointLightChange { + /// The position of the light in the world. + pub position: Vec3, + + /// The color of the light. + pub color: Vec3, + + /// The radius of the light. + pub radius: f32, + + /// Constant multiplier for the light. + pub intensity: f32, + } +} + /// The sample count when doing multisampling. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[repr(u8)] From 3d0c1f4442b9dd8d6e7a27f397557becea73c391 Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Thu, 7 Dec 2023 02:57:56 -0700 Subject: [PATCH 2/9] Add point light Renderer API --- rend3/src/instruction.rs | 25 ++++++++-- rend3/src/lib.rs | 2 + rend3/src/managers/point.rs | 92 +++++++++++++++++++++++++++++++++++++ rend3/src/renderer/eval.rs | 11 +++++ rend3/src/renderer/mod.rs | 45 ++++++++++++++++-- rend3/src/renderer/setup.rs | 4 +- 6 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 rend3/src/managers/point.rs diff --git a/rend3/src/instruction.rs b/rend3/src/instruction.rs index 867a0767..8b8decf0 100644 --- a/rend3/src/instruction.rs +++ b/rend3/src/instruction.rs @@ -3,10 +3,10 @@ use std::{mem, panic::Location}; use glam::Mat4; use parking_lot::Mutex; use rend3_types::{ - trait_supertrait_alias, MaterialHandle, MeshHandle, ObjectChange, ObjectHandle, RawDirectionalLightHandle, - RawGraphDataHandleUntyped, RawMaterialHandle, RawMeshHandle, RawSkeletonHandle, RawTexture2DHandle, - RawTextureCubeHandle, Skeleton, SkeletonHandle, Texture2DHandle, TextureCubeHandle, TextureFromTexture, - WasmNotSend, WasmNotSync, + trait_supertrait_alias, MaterialHandle, MeshHandle, ObjectChange, ObjectHandle, PointLight, PointLightChange, + PointLightHandle, RawDirectionalLightHandle, RawGraphDataHandleUntyped, RawMaterialHandle, RawMeshHandle, + RawPointLightHandle, RawSkeletonHandle, RawTexture2DHandle, RawTextureCubeHandle, Skeleton, SkeletonHandle, + Texture2DHandle, TextureCubeHandle, TextureFromTexture, WasmNotSend, WasmNotSync, }; use wgpu::{CommandBuffer, Device}; @@ -62,6 +62,10 @@ pub enum InstructionKind { handle: DirectionalLightHandle, light: DirectionalLight, }, + AddPointLight { + handle: PointLightHandle, + light: PointLight, + }, AddGraphData { add_invoke: Box, }, @@ -73,6 +77,10 @@ pub enum InstructionKind { handle: RawDirectionalLightHandle, change: DirectionalLightChange, }, + ChangePointLight { + handle: RawPointLightHandle, + change: PointLightChange, + }, DeleteMesh { handle: RawMeshHandle, }, @@ -94,6 +102,9 @@ pub enum InstructionKind { DeleteDirectionalLight { handle: RawDirectionalLightHandle, }, + DeletePointLight { + handle: RawPointLightHandle, + }, DeleteGraphData { handle: RawGraphDataHandleUntyped, }, @@ -189,6 +200,12 @@ impl DeletableRawResourceHandle for RawDirectionalLightHandle { } } +impl DeletableRawResourceHandle for RawPointLightHandle { + fn into_delete_instruction_kind(self) -> InstructionKind { + InstructionKind::DeletePointLight { handle: self } + } +} + impl DeletableRawResourceHandle for RawGraphDataHandleUntyped { fn into_delete_instruction_kind(self) -> InstructionKind { InstructionKind::DeleteGraphData { handle: self } diff --git a/rend3/src/lib.rs b/rend3/src/lib.rs index 4ac94be3..73a5ec25 100644 --- a/rend3/src/lib.rs +++ b/rend3/src/lib.rs @@ -150,6 +150,7 @@ pub mod managers { mod material; mod mesh; mod object; + mod point; mod skeleton; mod texture; @@ -160,6 +161,7 @@ pub mod managers { pub use material::*; pub use mesh::*; pub use object::*; + pub use point::*; pub use skeleton::*; pub use texture::*; } diff --git a/rend3/src/managers/point.rs b/rend3/src/managers/point.rs new file mode 100644 index 00000000..724731ef --- /dev/null +++ b/rend3/src/managers/point.rs @@ -0,0 +1,92 @@ +use encase::{ArrayLength, ShaderType}; +use glam::{Vec3, Vec4}; +use rend3_types::{PointLight, PointLightChange, PointLightHandle, RawPointLightHandle}; +use wgpu::{BufferUsages, Device, ShaderStages}; + +use crate::{ + util::{ + bind_merge::{BindGroupBuilder, BindGroupLayoutBuilder}, + buffer::WrappedPotBuffer, + }, + Renderer, +}; + +#[derive(Debug, Clone, ShaderType)] +struct ShaderPointLightBuffer { + count: ArrayLength, + #[size(runtime)] + array: Vec, +} + +#[derive(Debug, Copy, Clone, ShaderType)] +struct ShaderPointLight { + pub position: Vec4, + pub color: Vec3, + pub radius: f32, +} + +/// Manages point lights and their associated shadow maps. +pub struct PointLightManager { + data: Vec>, + data_buffer: WrappedPotBuffer, +} + +impl PointLightManager { + pub fn new(device: &Device) -> Self { + Self { + data: Vec::new(), + data_buffer: WrappedPotBuffer::new(device, BufferUsages::STORAGE, "point light buffer"), + } + } + + pub fn add(&mut self, handle: &PointLightHandle, light: PointLight) { + if handle.idx >= self.data.len() { + self.data.resize(handle.idx + 1, None); + } + + self.data[handle.idx] = Some(light); + } + + pub fn update(&mut self, handle: RawPointLightHandle, change: PointLightChange) { + self.data[handle.idx].as_mut().unwrap().update_from_changes(change); + } + + pub fn remove(&mut self, handle: RawPointLightHandle) { + self.data[handle.idx].take().unwrap(); + } + + pub fn evaluate(&mut self, renderer: &Renderer) { + let buffer = ShaderPointLightBuffer { + count: ArrayLength, + array: self + .data + .iter() + .flatten() + .map(|light| ShaderPointLight { + position: light.position.extend(1.0), + color: light.color * light.intensity, + radius: light.radius, + }) + .collect(), + }; + + self.data_buffer + .write_to_buffer(&renderer.device, &renderer.queue, &buffer); + } + + pub fn add_to_bgl(bglb: &mut BindGroupLayoutBuilder) { + bglb.append( + ShaderStages::FRAGMENT, + wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: Some(ShaderPointLightBuffer::min_size()), + }, + None, + ); + } + + pub fn add_to_bg<'a>(&'a self, bgb: &mut BindGroupBuilder<'a>) { + bgb.append_buffer(&self.data_buffer); + } +} diff --git a/rend3/src/renderer/eval.rs b/rend3/src/renderer/eval.rs index aca3a623..4edc7f4e 100644 --- a/rend3/src/renderer/eval.rs +++ b/rend3/src/renderer/eval.rs @@ -116,6 +116,12 @@ pub fn evaluate_instructions(renderer: &Renderer) -> InstructionEvaluationOutput InstructionKind::ChangeDirectionalLight { handle, change } => { data_core.directional_light_manager.update(handle, change); } + InstructionKind::AddPointLight { handle, light } => { + data_core.point_light_manager.add(&handle, light); + } + InstructionKind::ChangePointLight { handle, change } => { + data_core.point_light_manager.update(handle, change); + } InstructionKind::SetAspectRatio { ratio } => data_core.camera_manager.set_aspect_ratio(Some(ratio)), InstructionKind::SetCameraData { data } => { data_core.camera_manager.set_data(data); @@ -163,6 +169,10 @@ pub fn evaluate_instructions(renderer: &Renderer) -> InstructionEvaluationOutput renderer.resource_handle_allocators.directional_light.deallocate(handle); data_core.directional_light_manager.remove(handle) } + InstructionKind::DeletePointLight { handle } => { + renderer.resource_handle_allocators.point_light.deallocate(handle); + data_core.point_light_manager.remove(handle); + } InstructionKind::DeleteGraphData { handle } => { renderer.resource_handle_allocators.graph_storage.deallocate(handle); data_core.graph_storage.remove(&handle); @@ -199,6 +209,7 @@ pub fn evaluate_instructions(renderer: &Renderer) -> InstructionEvaluationOutput let (shadow_target_size, shadows) = data_core .directional_light_manager .evaluate(renderer, &data_core.camera_manager); + data_core.point_light_manager.evaluate(renderer); let mesh_buffer = renderer.mesh_manager.evaluate(); cmd_bufs.push(encoder.finish()); diff --git a/rend3/src/renderer/mod.rs b/rend3/src/renderer/mod.rs index 68a9115a..3e36fee1 100644 --- a/rend3/src/renderer/mod.rs +++ b/rend3/src/renderer/mod.rs @@ -3,8 +3,9 @@ use std::{marker::PhantomData, panic::Location, sync::Arc}; use glam::Mat4; use parking_lot::Mutex; use rend3_types::{ - GraphDataHandle, GraphDataTag, Handedness, Material, MaterialTag, ObjectChange, Skeleton, SkeletonHandle, - Texture2DTag, TextureCubeHandle, TextureCubeTag, TextureFromTexture, WasmNotSend, + GraphDataHandle, GraphDataTag, Handedness, Material, MaterialTag, ObjectChange, PointLight, PointLightChange, + PointLightHandle, Skeleton, SkeletonHandle, Texture2DTag, TextureCubeHandle, TextureCubeTag, TextureFromTexture, + WasmNotSend, }; use wgpu::{CommandEncoderDescriptor, Device, DownlevelCapabilities, Features, Limits, Queue}; use wgpu_profiler::GpuProfiler; @@ -14,7 +15,7 @@ use crate::{ instruction::{InstructionKind, InstructionStreamPair}, managers::{ CameraManager, DirectionalLightManager, GraphStorage, HandleAllocator, MaterialManager, MeshManager, - ObjectManager, SkeletonManager, TextureManager, + ObjectManager, PointLightManager, SkeletonManager, TextureManager, }, types::{ Camera, DirectionalLight, DirectionalLightChange, DirectionalLightHandle, MaterialHandle, Mesh, MeshHandle, @@ -73,6 +74,7 @@ struct HandleAllocators { pub material: HandleAllocator, pub object: HandleAllocator, pub directional_light: HandleAllocator, + pub point_light: HandleAllocator, pub graph_storage: HandleAllocator, } @@ -86,6 +88,7 @@ impl Default for HandleAllocators { material: HandleAllocator::new(false), object: HandleAllocator::new(true), directional_light: HandleAllocator::new(false), + point_light: HandleAllocator::new(false), graph_storage: HandleAllocator::new(false), } } @@ -105,6 +108,8 @@ pub struct RendererDataCore { pub object_manager: ObjectManager, /// Manages all directional lights, including their shadow maps. pub directional_light_manager: DirectionalLightManager, + /// Manages all point lights, including their shadow maps. + pub point_light_manager: PointLightManager, /// Manages skeletons, and their owned portion of the MeshManager's buffers pub skeleton_manager: SkeletonManager, /// Managed long term storage of data for the graph and it's routines @@ -386,6 +391,28 @@ impl Renderer { handle } + /// Add a point (aka punctual) light into the world. + /// + /// **WARNING**: point lighting is currently very inefficient, as every + /// fragment in the forward pass is shaded with every point light in the + /// world. + /// + /// The handle will keep the light alive. + #[track_caller] + pub fn add_point_light(self: &Arc, light: PointLight) -> PointLightHandle { + let handle = self.resource_handle_allocators.point_light.allocate(self); + + self.instructions.push( + InstructionKind::AddPointLight { + handle: handle.clone(), + light, + }, + *Location::caller(), + ); + + handle + } + /// Updates the settings for given directional light. #[track_caller] pub fn update_directional_light(&self, handle: &DirectionalLightHandle, change: DirectionalLightChange) { @@ -398,6 +425,18 @@ impl Renderer { ) } + /// Updates the settings for given point light. + #[track_caller] + pub fn update_point_light(&self, handle: &PointLightHandle, change: PointLightChange) { + self.instructions.push( + InstructionKind::ChangePointLight { + handle: handle.get_raw(), + change, + }, + *Location::caller(), + ) + } + /// Adds a piece of data for long term storage and convienient use in the RenderGraph /// /// The handle will keep the data alive. diff --git a/rend3/src/renderer/setup.rs b/rend3/src/renderer/setup.rs index 78a977c1..9c477e84 100644 --- a/rend3/src/renderer/setup.rs +++ b/rend3/src/renderer/setup.rs @@ -10,7 +10,7 @@ use crate::{ instruction::InstructionStreamPair, managers::{ CameraManager, DirectionalLightManager, GraphStorage, MaterialManager, MeshManager, ObjectManager, - SkeletonManager, TextureManager, + PointLightManager, SkeletonManager, TextureManager, }, renderer::{HandleAllocators, RendererDataCore}, util::{mipmap::MipmapGenerator, scatter_copy::ScatterCopy}, @@ -46,6 +46,7 @@ pub fn create_renderer( let material_manager = MaterialManager::new(&iad.device); let object_manager = ObjectManager::new(); let directional_light_manager = DirectionalLightManager::new(&iad.device); + let point_light_manager = PointLightManager::new(&iad.device); let skeleton_manager = SkeletonManager::new(); let graph_storage = GraphStorage::new(); @@ -93,6 +94,7 @@ pub fn create_renderer( material_manager, object_manager, directional_light_manager, + point_light_manager, skeleton_manager, graph_storage, profiler, From ad7cf6172f3b0ef062163193a83a620f95950c75 Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Thu, 7 Dec 2023 03:00:54 -0700 Subject: [PATCH 3/9] Shade point lights in opaque pass --- rend3-routine/shaders/src/depth.wgsl | 2 ++ rend3-routine/shaders/src/opaque.wgsl | 41 +++++++++++++++++++---- rend3-routine/shaders/src/structures.wgsl | 16 ++++++++- rend3-routine/src/common/interfaces.rs | 7 +++- rend3-routine/src/uniforms.rs | 1 + 5 files changed, 59 insertions(+), 8 deletions(-) diff --git a/rend3-routine/shaders/src/depth.wgsl b/rend3-routine/shaders/src/depth.wgsl index 9705f756..2dd92ad7 100644 --- a/rend3-routine/shaders/src/depth.wgsl +++ b/rend3-routine/shaders/src/depth.wgsl @@ -8,6 +8,8 @@ var primary_sampler: sampler; var uniforms: UniformData; @group(0) @binding(4) var directional_lights: DirectionalLightData; +@group(0) @binding(5) +var point_lights: PointLightData; @group(1) @binding(0) var object_buffer: array; diff --git a/rend3-routine/shaders/src/opaque.wgsl b/rend3-routine/shaders/src/opaque.wgsl index 3d805515..31502d86 100644 --- a/rend3-routine/shaders/src/opaque.wgsl +++ b/rend3-routine/shaders/src/opaque.wgsl @@ -17,6 +17,8 @@ var uniforms: UniformData; @group(0) @binding(4) var directional_lights: DirectionalLightData; @group(0) @binding(5) +var point_lights: PointLightData; +@group(0) @binding(6) var shadows: texture_depth_2d; @group(1) @binding(0) @@ -435,10 +437,7 @@ fn get_pixel_data(material: Material, vs_out: VertexOutput) -> PixelData { } {{/if}} -fn surface_shading(light: DirectionalLight, pixel: PixelData, view_pos: vec3, occlusion: f32) -> vec3 { - let view_mat3 = mat3x3(uniforms.view[0].xyz, uniforms.view[1].xyz, uniforms.view[2].xyz); - let l = normalize(view_mat3 * -light.direction); - +fn surface_shading(l: vec3, intensity: vec3, pixel: PixelData, view_pos: vec3, occlusion: f32) -> vec3 { let n = pixel.normal; let h = normalize(view_pos + l); @@ -465,7 +464,7 @@ fn surface_shading(light: DirectionalLight, pixel: PixelData, view_pos: vec3 @location(0) vec4 { return pixel.albedo; } + // View vector let v = -normalize(vs_out.view_position.xyz); + // Transform vectors into view space + let view_mat3 = mat3x3(uniforms.view[0].xyz, uniforms.view[1].xyz, uniforms.view[2].xyz); + var color = pixel.emissive.rgb; for (var i = 0; i < i32(directional_lights.count); i += 1) { let light = directional_lights.data[i]; @@ -512,7 +515,33 @@ fn fs_main(vs_out: VertexOutput) -> @location(0) vec4 { shadow_value = shadow_sample_pcf5(shadows, comparison_sampler, shadow_coords, shadow_ndc.z); } - color += surface_shading(light, pixel, v, shadow_value * pixel.ambient_occlusion); + // Calculate light source vector + let l = normalize(view_mat3 * -light.direction); + + color += surface_shading(l, light.color, pixel, v, shadow_value * pixel.ambient_occlusion); + } + + for (var i = 0; i < i32(point_lights.count); i += 1) { + let light = point_lights.data[i]; + + // Delta to light + let delta = (uniforms.view * light.position).xyz - vs_out.view_position.xyz; + + // Distance + let d = length(delta); + + // Attenuate from light and cusp at radius + // Derivative is 0 at both d = 0 and d = radius + // Source: https://lisyarus.github.io/blog/graphics/2022/07/30/point-light-attenuation.html + let s = saturate(d / light.radius); + let s2 = pow(s, 2.0); + let att = pow(1.0 - s2, 2.0) / (1.0 + s2); + let intensity = light.color * att; + + // Calculate light source vector + let l = delta / d; + + color += max(surface_shading(l, intensity, pixel, v, pixel.ambient_occlusion), vec3(0.0)); } let ambient = uniforms.ambient * pixel.albedo; diff --git a/rend3-routine/shaders/src/structures.wgsl b/rend3-routine/shaders/src/structures.wgsl index 0d85bda4..f10b05a2 100644 --- a/rend3-routine/shaders/src/structures.wgsl +++ b/rend3-routine/shaders/src/structures.wgsl @@ -92,6 +92,20 @@ struct DirectionalLightData { data: array, } +struct PointLight { + /// The position of the light in world space. + position: vec4, + // Color/intensity of the light. + color: vec3, + /// The radius of the light. + radius: f32, +} + +struct PointLightData { + count: u32, + data: array, +} + struct PixelData { albedo: vec4, diffuse_color: vec3, @@ -108,4 +122,4 @@ struct PixelData { anisotropy: f32, ambient_occlusion: f32, material_flags: u32, -} \ No newline at end of file +} diff --git a/rend3-routine/src/common/interfaces.rs b/rend3-routine/src/common/interfaces.rs index cef01b7e..e0f7b3b6 100644 --- a/rend3-routine/src/common/interfaces.rs +++ b/rend3-routine/src/common/interfaces.rs @@ -1,7 +1,11 @@ use std::{marker::PhantomData, mem, num::NonZeroU64}; use glam::{Mat4, Vec3}; -use rend3::{managers::DirectionalLightManager, types::Material, util::bind_merge::BindGroupLayoutBuilder}; +use rend3::{ + managers::{DirectionalLightManager, PointLightManager}, + types::Material, + util::bind_merge::BindGroupLayoutBuilder, +}; use wgpu::{ BindGroupLayout, BindingType, BufferBindingType, Device, ShaderStages, TextureSampleType, TextureViewDimension, }; @@ -39,6 +43,7 @@ impl WholeFrameInterfaces { ); DirectionalLightManager::add_to_bgl(&mut uniform_bglb); + PointLightManager::add_to_bgl(&mut uniform_bglb); let shadow_uniform_bgl = uniform_bglb.build(device, Some("shadow uniform bgl")); diff --git a/rend3-routine/src/uniforms.rs b/rend3-routine/src/uniforms.rs index 5edcd1ae..735c7020 100644 --- a/rend3-routine/src/uniforms.rs +++ b/rend3-routine/src/uniforms.rs @@ -93,6 +93,7 @@ pub fn add_to_graph<'node>( bgb.append_buffer(&uniform_buffer); ctx.data_core.directional_light_manager.add_to_bg(&mut bgb); + ctx.data_core.point_light_manager.add_to_bg(&mut bgb); let shadow_uniform_bg = bgb.build( &ctx.renderer.device, From ba64b7038ee23bcf8fb18fceb699f18365db7983 Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Thu, 7 Dec 2023 03:01:11 -0700 Subject: [PATCH 4/9] Add point lights to cube example --- examples/cube/src/lib.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/examples/cube/src/lib.rs b/examples/cube/src/lib.rs index 14faa4d0..ce78eb1a 100644 --- a/examples/cube/src/lib.rs +++ b/examples/cube/src/lib.rs @@ -59,6 +59,7 @@ const SAMPLE_COUNT: rend3::types::SampleCount = rend3::types::SampleCount::One; struct CubeExample { object_handle: Option, directional_light_handle: Option, + point_lights: Vec, } impl rend3_framework::App for CubeExample { @@ -87,7 +88,7 @@ impl rend3_framework::App for CubeExample { // Add PBR material with all defaults except a single color. let material = rend3_routine::pbr::PbrMaterial { - albedo: rend3_routine::pbr::AlbedoComponent::Value(glam::Vec4::new(0.0, 0.5, 0.5, 1.0)), + albedo: rend3_routine::pbr::AlbedoComponent::Value(glam::Vec4::new(0.5, 0.5, 0.5, 1.0)), ..rend3_routine::pbr::PbrMaterial::default() }; let material_handle = renderer.add_material(material); @@ -119,12 +120,25 @@ impl rend3_framework::App for CubeExample { // We need to keep the directional light handle alive. self.directional_light_handle = Some(renderer.add_directional_light(rend3::types::DirectionalLight { color: glam::Vec3::ONE, - intensity: 10.0, + intensity: 1.0, // Direction will be normalized direction: glam::Vec3::new(-1.0, -4.0, 2.0), distance: 400.0, resolution: 2048, })); + + let mut add_point_light = |position, color| { + self.point_lights + .push(renderer.add_point_light(rend3::types::PointLight { + position, + color, + radius: 2.0, + intensity: 4.0, + })); + }; + + add_point_light(glam::vec3(0.1, 1.2, -1.5), glam::vec3(1.0, 0.0, 0.0)); + add_point_light(glam::vec3(1.5, 1.2, -0.1), glam::vec3(0.0, 1.0, 0.0)); } fn handle_event( From d6778fdc277f9c7f108fa5af6466c3b58d77931e Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Thu, 7 Dec 2023 03:04:27 -0700 Subject: [PATCH 5/9] Add point lights to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39406f72..4c2c04e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Per Keep a Changelog there are 6 main categories of changes: - rend3-routine: Added the option to set a custom primitive topology value when building a forward routine. @setzer22 - rend3-routine: Added a resolution field to the per-frame uniforms. @setzer22 - rend3-routine: Added add_clear_to_graph to make clears explicit and add `clear_color` argument to base rendergraph. +- rend3: Added basic (no shadow maps, no clustering) point light support to the renderer API. @marceline-cramer ### Changes - rend3: Update to wgpu 0.13, naga 0.9 @garyttierney From fb3184f58ddadc8fec0f0c5f9bd7d1d5dcebbcb3 Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Mon, 11 Dec 2023 20:25:41 -0700 Subject: [PATCH 6/9] Cleaner point light init in cube example --- examples/cube/src/lib.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/cube/src/lib.rs b/examples/cube/src/lib.rs index ce78eb1a..f7cf1bae 100644 --- a/examples/cube/src/lib.rs +++ b/examples/cube/src/lib.rs @@ -127,7 +127,13 @@ impl rend3_framework::App for CubeExample { resolution: 2048, })); - let mut add_point_light = |position, color| { + let lights = [ + // position, color + (glam::vec3(0.1, 1.2, -1.5), glam::vec3(1.0, 0.0, 0.0)), + (glam::vec3(1.5, 1.2, -0.1), glam::vec3(0.0, 1.0, 0.0)), + ]; + + for (position, color) in lights { self.point_lights .push(renderer.add_point_light(rend3::types::PointLight { position, @@ -135,10 +141,7 @@ impl rend3_framework::App for CubeExample { radius: 2.0, intensity: 4.0, })); - }; - - add_point_light(glam::vec3(0.1, 1.2, -1.5), glam::vec3(1.0, 0.0, 0.0)); - add_point_light(glam::vec3(1.5, 1.2, -0.1), glam::vec3(0.0, 1.0, 0.0)); + } } fn handle_event( From d81e93ab2ddba05aa7668a6bf1f56798e185f69a Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Mon, 11 Dec 2023 20:26:40 -0700 Subject: [PATCH 7/9] Remove unnecessary binds from depth shader --- rend3-routine/shaders/src/depth.wgsl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rend3-routine/shaders/src/depth.wgsl b/rend3-routine/shaders/src/depth.wgsl index 2dd92ad7..d7dab49f 100644 --- a/rend3-routine/shaders/src/depth.wgsl +++ b/rend3-routine/shaders/src/depth.wgsl @@ -6,10 +6,6 @@ var primary_sampler: sampler; @group(0) @binding(3) var uniforms: UniformData; -@group(0) @binding(4) -var directional_lights: DirectionalLightData; -@group(0) @binding(5) -var point_lights: PointLightData; @group(1) @binding(0) var object_buffer: array; From 92a0bf1ed7d29bfdd23e5fa17947a4a161b394fe Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Mon, 11 Dec 2023 20:27:51 -0700 Subject: [PATCH 8/9] Descriptive name for light_dir in surface_shading() --- rend3-routine/shaders/src/opaque.wgsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rend3-routine/shaders/src/opaque.wgsl b/rend3-routine/shaders/src/opaque.wgsl index 31502d86..c21df3f3 100644 --- a/rend3-routine/shaders/src/opaque.wgsl +++ b/rend3-routine/shaders/src/opaque.wgsl @@ -437,14 +437,14 @@ fn get_pixel_data(material: Material, vs_out: VertexOutput) -> PixelData { } {{/if}} -fn surface_shading(l: vec3, intensity: vec3, pixel: PixelData, view_pos: vec3, occlusion: f32) -> vec3 { +fn surface_shading(light_dir: vec3, intensity: vec3, pixel: PixelData, view_pos: vec3, occlusion: f32) -> vec3 { let n = pixel.normal; - let h = normalize(view_pos + l); + let h = normalize(view_pos + light_dir); let nov = abs(dot(n, view_pos)) + 0.00001; - let nol = saturate(dot(n, l)); + let nol = saturate(dot(n, light_dir)); let noh = saturate(dot(n, h)); - let loh = saturate(dot(l, h)); + let loh = saturate(dot(light_dir, h)); let f90 = saturate(dot(pixel.f0, vec3(50.0 * 0.33))); From 6499bd1bb310f158492a0bd83a160b5e19aea6a6 Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Mon, 11 Dec 2023 20:28:42 -0700 Subject: [PATCH 9/9] Replace pow() with explicit square in point light shader --- rend3-routine/shaders/src/opaque.wgsl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rend3-routine/shaders/src/opaque.wgsl b/rend3-routine/shaders/src/opaque.wgsl index c21df3f3..e398d0fc 100644 --- a/rend3-routine/shaders/src/opaque.wgsl +++ b/rend3-routine/shaders/src/opaque.wgsl @@ -534,8 +534,9 @@ fn fs_main(vs_out: VertexOutput) -> @location(0) vec4 { // Derivative is 0 at both d = 0 and d = radius // Source: https://lisyarus.github.io/blog/graphics/2022/07/30/point-light-attenuation.html let s = saturate(d / light.radius); - let s2 = pow(s, 2.0); - let att = pow(1.0 - s2, 2.0) / (1.0 + s2); + let s2 = s * s; + let inv_s2 = 1.0 - s2; + let att = inv_s2 * inv_s2 / (1.0 + s2); let intensity = light.color * att; // Calculate light source vector