From 188d355d1054a102b55d64e5921cf5f15c019b78 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sun, 1 Dec 2019 20:03:04 -0800 Subject: [PATCH] render refactors. ecs integration --- src/application.rs | 193 +++++++++++------------------------- src/core/mod.rs | 3 + src/{ => core}/transform.rs | 6 +- src/lib.rs | 4 +- src/render/camera.rs | 22 ++++ src/render/forward/mod.rs | 74 +++++++++----- src/render/light.rs | 35 +++++++ src/render/mod.rs | 14 ++- src/render/pass.rs | 6 ++ src/render/shader.rs | 16 +++ src/render/shadow/mod.rs | 90 +++++++++++++++-- src/temp.rs | 92 +---------------- tiny-town/src/main.rs | 4 - 13 files changed, 296 insertions(+), 263 deletions(-) create mode 100644 src/core/mod.rs rename src/{ => core}/transform.rs (56%) create mode 100644 src/render/camera.rs create mode 100644 src/render/light.rs create mode 100644 src/render/pass.rs create mode 100644 src/render/shader.rs diff --git a/src/application.rs b/src/application.rs index 5169bc25a1..dcb16f2ebc 100644 --- a/src/application.rs +++ b/src/application.rs @@ -5,36 +5,41 @@ use winit::{ }; use zerocopy::AsBytes; +use legion::prelude::*; -use std::rc::Rc; +use std::sync::Arc; use std::mem; -use crate::{temp::*, vertex::*, render::*, math}; +use crate::{temp::*, vertex::*, render::*, math, Transform}; pub struct Application { - entities: Vec, - lights: Vec, - lights_are_dirty: bool, - shadow_pass: ShadowPass, - forward_pass: ForwardPass, + pub universe: Universe, + pub world: World, + pub shadow_pass: ShadowPass, + pub forward_pass: ForwardPass, camera_position: math::Vec3, camera_fov: f32, } impl Application { + pub const MAX_LIGHTS: usize = 10; + fn init( sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device, ) -> (Self, Option) { + let universe = Universe::new(); + let mut world = universe.create_world(); + let vertex_size = mem::size_of::(); let (cube_vertex_data, cube_index_data) = create_cube(); - let cube_vertex_buf = Rc::new( + let cube_vertex_buf = Arc::new( device.create_buffer_with_data(cube_vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX), ); - let cube_index_buf = Rc::new( + let cube_index_buf = Arc::new( device.create_buffer_with_data(cube_index_data.as_bytes(), wgpu::BufferUsage::INDEX), ); @@ -71,16 +76,15 @@ impl Application { }, }], }); - Entity { - mx_world: math::identity(), + (CubeEnt { rotation_speed: 0.0, color: wgpu::Color::WHITE, - vertex_buf: Rc::new(plane_vertex_buf), - index_buf: Rc::new(plane_index_buf), + vertex_buf: Arc::new(plane_vertex_buf), + index_buf: Arc::new(plane_index_buf), index_count: plane_index_data.len(), bind_group, uniform_buf: plane_uniform_buf, - } + }, Transform::new()) }]; let camera_position = math::vec3(3.0f32, -10.0, 6.0); @@ -114,12 +118,11 @@ impl Application { size: entity_uniform_size, usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, }); - entities.push(Entity { - mx_world: math::translation(&cube.offset), + entities.push((CubeEnt { rotation_speed: cube.rotation, color: wgpu::Color::GREEN, - vertex_buf: Rc::clone(&cube_vertex_buf), - index_buf: Rc::clone(&cube_index_buf), + vertex_buf: Arc::clone(&cube_vertex_buf), + index_buf: Arc::clone(&cube_index_buf), index_count: cube_index_data.len(), bind_group: device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &local_bind_group_layout, @@ -132,9 +135,11 @@ impl Application { }], }), uniform_buf, - }); + }, Transform { value: math::translation(&cube.offset)})); } + world.insert((), entities); + let vb_desc = wgpu::VertexBufferDescriptor { stride: vertex_size as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, @@ -152,7 +157,20 @@ impl Application { ], }; - let shadow_pass = ShadowPass::new(device, vb_desc.clone(), &local_bind_group_layout); + let light_uniform_size = + (Self::MAX_LIGHTS * mem::size_of::()) as wgpu::BufferAddress; + + let light_uniform_buffer = Arc::new(UniformBuffer { + buffer: device.create_buffer(&wgpu::BufferDescriptor { + size: light_uniform_size, + usage: wgpu::BufferUsage::UNIFORM + | wgpu::BufferUsage::COPY_SRC + | wgpu::BufferUsage::COPY_DST, + }), + size: light_uniform_size, + }); + + let shadow_pass = ShadowPass::new(device, light_uniform_buffer.clone(), vb_desc.clone(), &local_bind_group_layout, Self::MAX_LIGHTS as u32); let mut shadow_target_views = (0 .. 2) .map(|i| { @@ -167,8 +185,9 @@ impl Application { })) }) .collect::>(); + let lights = vec![ - Light { + (Light { pos: math::vec3(7.0, -5.0, 10.0), color: wgpu::Color { r: 0.5, @@ -179,8 +198,8 @@ impl Application { fov: f32::to_radians(60.0), depth: 1.0 .. 20.0, target_view: shadow_target_views[0].take().unwrap(), - }, - Light { + },), + (Light { pos: math::vec3(-5.0, 7.0, 10.0), color: wgpu::Color { r: 1.0, @@ -191,21 +210,23 @@ impl Application { fov: f32::to_radians(45.0), depth: 1.0 .. 20.0, target_view: shadow_target_views[1].take().unwrap(), - }, + },), ]; + + let light_count = lights.len(); + world.insert((), lights); - let matrix = generate_matrix(&camera_position, camera_fov, sc_desc.width as f32 / sc_desc.height as f32, 1.0, 20.0); + let matrix = camera::get_projection_view_matrix(&camera_position, camera_fov, sc_desc.width as f32 / sc_desc.height as f32, 1.0, 20.0); let forward_uniforms = ForwardUniforms { proj: *matrix.as_ref(), - num_lights: [lights.len() as u32, 0, 0, 0], + num_lights: [light_count as u32, 0, 0, 0], }; - let forward_pass = ForwardPass::new(device, forward_uniforms, &shadow_pass, vb_desc, &local_bind_group_layout, sc_desc); + let forward_pass = ForwardPass::new(device, forward_uniforms, light_uniform_buffer.clone(), &shadow_pass, vb_desc, &local_bind_group_layout, sc_desc); let this = Application { - entities, - lights, - lights_are_dirty: true, + universe, + world, shadow_pass, forward_pass, camera_position, @@ -221,7 +242,7 @@ impl Application { ) -> Option { let command_buf = { - let mx_total = generate_matrix(&self.camera_position, self.camera_fov, sc_desc.width as f32 / sc_desc.height as f32, 1.0, 20.0); + let mx_total = camera::get_projection_view_matrix(&self.camera_position, self.camera_fov, sc_desc.width as f32 / sc_desc.height as f32, 1.0, 20.0); let mx_ref: [[f32; 4]; 4] = mx_total.into(); let temp_buf = device.create_buffer_with_data(mx_ref.as_bytes(), wgpu::BufferUsage::COPY_SRC); @@ -251,23 +272,18 @@ impl Application { device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); { + let mut entities = <(Read, Read)>::query(); + let entities_count = entities.iter(&mut self.world).count(); let size = mem::size_of::(); let temp_buf_data = device - .create_buffer_mapped(self.entities.len() * size, wgpu::BufferUsage::COPY_SRC); + .create_buffer_mapped(entities_count * size, wgpu::BufferUsage::COPY_SRC); - for (entity, slot) in self - .entities - .iter_mut() + for ((entity, transform), slot) in entities.iter(&mut self.world) .zip(temp_buf_data.data.chunks_exact_mut(size)) { - if entity.rotation_speed != 0.0 { - let rotation = - math::rotation(entity.rotation_speed, &math::vec3(0.0, 1.0, 0.0)); - entity.mx_world = entity.mx_world * rotation; - } slot.copy_from_slice( EntityUniforms { - model: entity.mx_world.into(), + model: transform.value.into(), color: [ entity.color.r as f32, entity.color.g as f32, @@ -281,7 +297,7 @@ impl Application { let temp_buf = temp_buf_data.finish(); - for (i, entity) in self.entities.iter().enumerate() { + for (i, (entity, _)) in entities.iter(&mut self.world).enumerate() { encoder.copy_buffer_to_buffer( &temp_buf, (i * size) as wgpu::BufferAddress, @@ -292,97 +308,8 @@ impl Application { } } - if self.lights_are_dirty { - self.lights_are_dirty = false; - let size = mem::size_of::(); - let total_size = size * self.lights.len(); - let temp_buf_data = - device.create_buffer_mapped(total_size, wgpu::BufferUsage::COPY_SRC); - for (light, slot) in self - .lights - .iter() - .zip(temp_buf_data.data.chunks_exact_mut(size)) - { - slot.copy_from_slice(light.to_raw().as_bytes()); - } - encoder.copy_buffer_to_buffer( - &temp_buf_data.finish(), - 0, - &self.forward_pass.light_uniform_buffer, - 0, - total_size as wgpu::BufferAddress, - ); - } - - for (i, light) in self.lights.iter().enumerate() { - // The light uniform buffer already has the projection, - // let's just copy it over to the shadow uniform buffer. - encoder.copy_buffer_to_buffer( - &self.forward_pass.light_uniform_buffer, - (i * mem::size_of::()) as wgpu::BufferAddress, - &self.shadow_pass.uniform_buf, - 0, - 64, - ); - - let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[], - depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &light.target_view, - depth_load_op: wgpu::LoadOp::Clear, - depth_store_op: wgpu::StoreOp::Store, - stencil_load_op: wgpu::LoadOp::Clear, - stencil_store_op: wgpu::StoreOp::Store, - clear_depth: 1.0, - clear_stencil: 0, - }), - }); - pass.set_pipeline(&self.shadow_pass.pipeline); - pass.set_bind_group(0, &self.shadow_pass.bind_group, &[]); - - for entity in &self.entities { - pass.set_bind_group(1, &entity.bind_group, &[]); - pass.set_index_buffer(&entity.index_buf, 0); - pass.set_vertex_buffers(0, &[(&entity.vertex_buf, 0)]); - pass.draw_indexed(0 .. entity.index_count as u32, 0, 0 .. 1); - } - } - - // forward pass - { - let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &frame.view, - resolve_target: None, - load_op: wgpu::LoadOp::Clear, - store_op: wgpu::StoreOp::Store, - clear_color: wgpu::Color { - r: 0.1, - g: 0.2, - b: 0.3, - a: 1.0, - }, - }], - depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &self.forward_pass.depth_texture, - depth_load_op: wgpu::LoadOp::Clear, - depth_store_op: wgpu::StoreOp::Store, - stencil_load_op: wgpu::LoadOp::Clear, - stencil_store_op: wgpu::StoreOp::Store, - clear_depth: 1.0, - clear_stencil: 0, - }), - }); - pass.set_pipeline(&self.forward_pass.pipeline); - pass.set_bind_group(0, &self.forward_pass.bind_group, &[]); - - for entity in &self.entities { - pass.set_bind_group(1, &entity.bind_group, &[]); - pass.set_index_buffer(&entity.index_buf, 0); - pass.set_vertex_buffers(0, &[(&entity.vertex_buf, 0)]); - pass.draw_indexed(0 .. entity.index_count as u32, 0, 0 .. 1); - } - } + self.shadow_pass.render(device, frame, &mut encoder, &mut self.world); + self.forward_pass.render(device, frame, &mut encoder, &mut self.world); encoder.finish() } diff --git a/src/core/mod.rs b/src/core/mod.rs new file mode 100644 index 0000000000..96b0a770ad --- /dev/null +++ b/src/core/mod.rs @@ -0,0 +1,3 @@ +mod transform; + +pub use transform::*; \ No newline at end of file diff --git a/src/transform.rs b/src/core/transform.rs similarity index 56% rename from src/transform.rs rename to src/core/transform.rs index 4cbd7bac65..88d3cfd88c 100644 --- a/src/transform.rs +++ b/src/core/transform.rs @@ -2,15 +2,13 @@ use crate::math; #[derive(Clone, Copy, Debug, PartialEq)] pub struct Transform { - pub local: math::Mat4, - pub global: math::Mat4, + pub value: math::Mat4, } impl Transform { pub fn new() -> Transform { Transform { - local: math::identity(), - global: math::identity(), + value: math::identity(), } } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 8fe3809b08..c7228330a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,11 @@ -mod transform; +mod core; mod application; mod vertex; mod temp; mod render; -pub use transform::Transform; pub use application::Application; +pub use crate::core::*; pub use legion; pub use nalgebra_glm as math; \ No newline at end of file diff --git a/src/render/camera.rs b/src/render/camera.rs new file mode 100644 index 0000000000..1e8634da01 --- /dev/null +++ b/src/render/camera.rs @@ -0,0 +1,22 @@ +use crate::math; + +pub fn get_projection_view_matrix(eye: &math::Vec3, fov: f32, aspect_ratio: f32, near: f32, far: f32) -> math::Mat4 { + let projection = math::perspective(aspect_ratio, fov, near, far); + + let view = math::look_at_rh::( + &eye, + &math::vec3(0.0, 0.0, 0.0), + &math::vec3(0.0, 0.0, 1.0), + ); + + opengl_to_wgpu_matrix() * projection * view +} + +pub fn opengl_to_wgpu_matrix() -> math::Mat4 { + math::mat4( + 1.0, 0.0, 0.0, 0.0, + 0.0, -1.0, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.0, 0.0, 0.5, 1.0, + ) +} \ No newline at end of file diff --git a/src/render/forward/mod.rs b/src/render/forward/mod.rs index 01d68df750..19ab3867e5 100644 --- a/src/render/forward/mod.rs +++ b/src/render/forward/mod.rs @@ -1,8 +1,8 @@ -use crate::{temp::*, render::shadow::ShadowPass}; - -use std::mem; +use crate::{render::*, temp::*}; +use legion::prelude::*; +use std::{mem, sync::Arc}; use zerocopy::{AsBytes, FromBytes}; -use wgpu::{Device, BindGroupLayout, VertexBufferDescriptor, SwapChainDescriptor}; +use wgpu::{CommandEncoder, Device, BindGroupLayout, VertexBufferDescriptor, SwapChainDescriptor, SwapChainOutput}; #[repr(C)] #[derive(Clone, Copy, AsBytes, FromBytes)] @@ -15,22 +15,59 @@ pub struct ForwardPass { pub pipeline: wgpu::RenderPipeline, pub bind_group: wgpu::BindGroup, pub forward_uniform_buffer: wgpu::Buffer, - pub light_uniform_buffer: wgpu::Buffer, + pub light_uniform_buffer: Arc::, pub depth_texture: wgpu::TextureView, } +impl Pass for ForwardPass { + fn render(&mut self, device: &Device, frame: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World) { + let mut entities = >::query(); + let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &frame.view, + resolve_target: None, + load_op: wgpu::LoadOp::Clear, + store_op: wgpu::StoreOp::Store, + clear_color: wgpu::Color { + r: 0.1, + g: 0.2, + b: 0.3, + a: 1.0, + }, + }], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &self.depth_texture, + depth_load_op: wgpu::LoadOp::Clear, + depth_store_op: wgpu::StoreOp::Store, + stencil_load_op: wgpu::LoadOp::Clear, + stencil_store_op: wgpu::StoreOp::Store, + clear_depth: 1.0, + clear_stencil: 0, + }), + }); + pass.set_pipeline(&self.pipeline); + pass.set_bind_group(0, &self.bind_group, &[]); + + for entity in entities.iter_immutable(world) { + pass.set_bind_group(1, &entity.bind_group, &[]); + pass.set_index_buffer(&entity.index_buf, 0); + pass.set_vertex_buffers(0, &[(&entity.vertex_buf, 0)]); + pass.draw_indexed(0 .. entity.index_count as u32, 0, 0 .. 1); + } + } +} + impl ForwardPass { - pub const MAX_LIGHTS: usize = 10; pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; - pub fn new(device: &Device, forward_uniforms: ForwardUniforms, shadow_pass: &ShadowPass, vertex_buffer_descriptor: VertexBufferDescriptor, local_bind_group_layout: &BindGroupLayout, swap_chain_descriptor: &SwapChainDescriptor) -> ForwardPass { - let vs_bytes = load_glsl( + pub fn new(device: &Device, forward_uniforms: ForwardUniforms, light_uniform_buffer: Arc::, shadow_pass: &shadow::ShadowPass, vertex_buffer_descriptor: VertexBufferDescriptor, local_bind_group_layout: &BindGroupLayout, swap_chain_descriptor: &SwapChainDescriptor) -> ForwardPass { + let vs_bytes = shader::load_glsl( include_str!("forward.vert"), - ShaderStage::Vertex, + shader::ShaderStage::Vertex, ); - let fs_bytes = load_glsl( + let fs_bytes = shader::load_glsl( include_str!("forward.frag"), - ShaderStage::Fragment, + shader::ShaderStage::Fragment, ); let bind_group_layout = @@ -68,16 +105,6 @@ impl ForwardPass { wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, ); - let light_uniform_size = - (Self::MAX_LIGHTS * mem::size_of::()) as wgpu::BufferAddress; - - let light_uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor { - size: light_uniform_size, - usage: wgpu::BufferUsage::UNIFORM - | wgpu::BufferUsage::COPY_SRC - | wgpu::BufferUsage::COPY_DST, - }); - // Create bind group let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &bind_group_layout, @@ -92,8 +119,8 @@ impl ForwardPass { wgpu::Binding { binding: 1, resource: wgpu::BindingResource::Buffer { - buffer: &light_uniform_buffer, - range: 0 .. light_uniform_size, + buffer: &light_uniform_buffer.buffer, + range: 0 .. light_uniform_buffer.size, }, }, wgpu::Binding { @@ -157,7 +184,6 @@ impl ForwardPass { alpha_to_coverage_enabled: false, }); - ForwardPass { pipeline, bind_group, diff --git a/src/render/light.rs b/src/render/light.rs new file mode 100644 index 0000000000..002f7ff385 --- /dev/null +++ b/src/render/light.rs @@ -0,0 +1,35 @@ +use crate::{math, render::camera}; +use std::ops::Range; +use zerocopy::{AsBytes, FromBytes}; + + +pub struct Light { + pub pos: math::Vec3, + pub color: wgpu::Color, + pub fov: f32, + pub depth: Range, + pub target_view: wgpu::TextureView, +} + +#[repr(C)] +#[derive(Clone, Copy, AsBytes, FromBytes)] +pub struct LightRaw { + pub proj: [[f32; 4]; 4], + pub pos: [f32; 4], + pub color: [f32; 4], +} + +impl Light { + pub fn to_raw(&self) -> LightRaw { + LightRaw { + proj: camera::get_projection_view_matrix(&self.pos, self.fov, 1.0, self.depth.start, self.depth.end).into(), + pos: [self.pos.x, self.pos.y, self.pos.z, 1.0], + color: [ + self.color.r as f32, + self.color.g as f32, + self.color.b as f32, + 1.0, + ], + } + } +} \ No newline at end of file diff --git a/src/render/mod.rs b/src/render/mod.rs index 1d416a5bef..2836b6ff50 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -1,5 +1,17 @@ +pub mod camera; +pub mod shader; mod forward; mod shadow; +mod light; +mod pass; pub use forward::{ForwardPass, ForwardUniforms}; -pub use shadow::ShadowPass; \ No newline at end of file +pub use shadow::ShadowPass; +pub use light::*; +pub use shader::*; +pub use pass::*; + +pub struct UniformBuffer { + pub buffer: wgpu::Buffer, + pub size: u64, +} \ No newline at end of file diff --git a/src/render/pass.rs b/src/render/pass.rs new file mode 100644 index 0000000000..04ae952280 --- /dev/null +++ b/src/render/pass.rs @@ -0,0 +1,6 @@ +use legion::world::World; +use wgpu::{CommandEncoder, Device, SwapChainOutput}; + +pub trait Pass { + fn render(&mut self, device: &Device, frame: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World); +} \ No newline at end of file diff --git a/src/render/shader.rs b/src/render/shader.rs new file mode 100644 index 0000000000..a347ddeb78 --- /dev/null +++ b/src/render/shader.rs @@ -0,0 +1,16 @@ +#[allow(dead_code)] +pub enum ShaderStage { + Vertex, + Fragment, + Compute, +} + +pub fn load_glsl(code: &str, stage: ShaderStage) -> Vec { + let ty = match stage { + ShaderStage::Vertex => glsl_to_spirv::ShaderType::Vertex, + ShaderStage::Fragment => glsl_to_spirv::ShaderType::Fragment, + ShaderStage::Compute => glsl_to_spirv::ShaderType::Compute, + }; + + wgpu::read_spirv(glsl_to_spirv::compile(&code, ty).unwrap()).unwrap() +} \ No newline at end of file diff --git a/src/render/shadow/mod.rs b/src/render/shadow/mod.rs index d6f57eb01c..89048b45fe 100644 --- a/src/render/shadow/mod.rs +++ b/src/render/shadow/mod.rs @@ -1,6 +1,8 @@ -use crate::{temp::*, render::forward}; -use wgpu::{Device, BindGroupLayout, VertexBufferDescriptor}; -use std::mem; +use crate::{render::*, temp::*}; +use wgpu::{BindGroupLayout, CommandEncoder, Device, VertexBufferDescriptor, SwapChainOutput}; +use legion::prelude::*; +use zerocopy::AsBytes; +use std::{mem, sync::Arc}; pub struct ShadowPass { pub pipeline: wgpu::RenderPipeline, @@ -9,6 +11,76 @@ pub struct ShadowPass { pub shadow_texture: wgpu::Texture, pub shadow_view: wgpu::TextureView, pub shadow_sampler: wgpu::Sampler, + pub light_uniform_buffer: Arc::, + pub lights_are_dirty: bool, +} + +#[repr(C)] +pub struct ShadowUniforms { + pub proj: [[f32; 4]; 4], +} + +impl Pass for ShadowPass { + fn render(&mut self, device: &Device, _: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World) { + let mut light_query = >::query(); + let mut entity_query = >::query(); + let light_count = light_query.iter(world).count(); + + if self.lights_are_dirty { + self.lights_are_dirty = false; + let size = mem::size_of::(); + let total_size = size * light_count; + let temp_buf_data = + device.create_buffer_mapped(total_size, wgpu::BufferUsage::COPY_SRC); + for (light, slot) in light_query + .iter(world) + .zip(temp_buf_data.data.chunks_exact_mut(size)) + { + slot.copy_from_slice(light.to_raw().as_bytes()); + } + encoder.copy_buffer_to_buffer( + &temp_buf_data.finish(), + 0, + &self.light_uniform_buffer.buffer, + 0, + total_size as wgpu::BufferAddress, + ); + } + + for (i, light) in light_query.iter_immutable(world).enumerate() { + // The light uniform buffer already has the projection, + // let's just copy it over to the shadow uniform buffer. + encoder.copy_buffer_to_buffer( + &self.light_uniform_buffer.buffer, + (i * mem::size_of::()) as wgpu::BufferAddress, + &self.uniform_buf, + 0, + 64, + ); + + let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &light.target_view, + depth_load_op: wgpu::LoadOp::Clear, + depth_store_op: wgpu::StoreOp::Store, + stencil_load_op: wgpu::LoadOp::Clear, + stencil_store_op: wgpu::StoreOp::Store, + clear_depth: 1.0, + clear_stencil: 0, + }), + }); + pass.set_pipeline(&self.pipeline); + pass.set_bind_group(0, &self.bind_group, &[]); + + for entity in entity_query.iter_immutable(world) { + pass.set_bind_group(1, &entity.bind_group, &[]); + pass.set_index_buffer(&entity.index_buf, 0); + pass.set_vertex_buffers(0, &[(&entity.vertex_buf, 0)]); + pass.draw_indexed(0 .. entity.index_count as u32, 0, 0 .. 1); + } + } + } } impl ShadowPass { @@ -19,7 +91,7 @@ impl ShadowPass { depth: 1, }; - pub fn new(device: &Device, vertex_buffer_descriptor: VertexBufferDescriptor, local_bind_group_layout: &BindGroupLayout) -> ShadowPass { + pub fn new(device: &Device, light_uniform_buffer: Arc::, vertex_buffer_descriptor: VertexBufferDescriptor, local_bind_group_layout: &BindGroupLayout, max_lights: u32) -> ShadowPass { // Create pipeline layout let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -53,7 +125,7 @@ impl ShadowPass { let shadow_texture = device.create_texture(&wgpu::TextureDescriptor { size: Self::SHADOW_SIZE, - array_layer_count: forward::ForwardPass::MAX_LIGHTS as u32, + array_layer_count: max_lights, mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, @@ -78,9 +150,9 @@ impl ShadowPass { // Create the render pipeline let vs_bytes = - load_glsl(include_str!("shadow.vert"), ShaderStage::Vertex); + shader::load_glsl(include_str!("shadow.vert"), shader::ShaderStage::Vertex); let fs_bytes = - load_glsl(include_str!("shadow.frag"), ShaderStage::Fragment); + shader::load_glsl(include_str!("shadow.frag"), shader::ShaderStage::Fragment); let vs_module = device.create_shader_module(&vs_bytes); let fs_module = device.create_shader_module(&fs_bytes); @@ -125,7 +197,9 @@ impl ShadowPass { uniform_buf, shadow_texture, shadow_view, - shadow_sampler + shadow_sampler, + light_uniform_buffer, + lights_are_dirty: true, } } } diff --git a/src/temp.rs b/src/temp.rs index b6a18e15f5..28f842460a 100644 --- a/src/temp.rs +++ b/src/temp.rs @@ -1,101 +1,19 @@ -use std::{rc::Rc, ops::Range}; +use std::{sync::Arc}; use zerocopy::{AsBytes, FromBytes}; -use crate::math; - -pub fn opengl_to_wgpu_matrix() -> math::Mat4 { - math::mat4( - 1.0, 0.0, 0.0, 0.0, - 0.0, -1.0, 0.0, 0.0, - 0.0, 0.0, 0.5, 0.0, - 0.0, 0.0, 0.5, 1.0, - ) -} -pub struct Entity { - pub mx_world: math::Mat4, +pub struct CubeEnt { pub rotation_speed: f32, pub color: wgpu::Color, - pub vertex_buf: Rc, - pub index_buf: Rc, + pub vertex_buf: Arc, + pub index_buf: Arc, pub index_count: usize, pub bind_group: wgpu::BindGroup, pub uniform_buf: wgpu::Buffer, } -pub struct Light { - pub pos: math::Vec3, - pub color: wgpu::Color, - pub fov: f32, - pub depth: Range, - pub target_view: wgpu::TextureView, -} - -#[repr(C)] -#[derive(Clone, Copy, AsBytes, FromBytes)] -pub struct LightRaw { - pub proj: [[f32; 4]; 4], - pub pos: [f32; 4], - pub color: [f32; 4], -} - -impl Light { - pub fn to_raw(&self) -> LightRaw { - LightRaw { - proj: generate_matrix(&self.pos, self.fov, 1.0, self.depth.start, self.depth.end).into(), - pos: [self.pos.x, self.pos.y, self.pos.z, 1.0], - color: [ - self.color.r as f32, - self.color.g as f32, - self.color.b as f32, - 1.0, - ], - } - } -} - #[repr(C)] #[derive(Clone, Copy, AsBytes, FromBytes)] pub struct EntityUniforms { pub model: [[f32; 4]; 4], pub color: [f32; 4], -} - -#[repr(C)] -pub struct ShadowUniforms { - pub proj: [[f32; 4]; 4], -} - -// pub struct Pass { -// pub pipeline: wgpu::RenderPipeline, -// pub bind_group: wgpu::BindGroup, -// pub uniform_buf: wgpu::Buffer, -// } - -#[allow(dead_code)] -pub enum ShaderStage { - Vertex, - Fragment, - Compute, -} - -pub fn load_glsl(code: &str, stage: ShaderStage) -> Vec { - let ty = match stage { - ShaderStage::Vertex => glsl_to_spirv::ShaderType::Vertex, - ShaderStage::Fragment => glsl_to_spirv::ShaderType::Fragment, - ShaderStage::Compute => glsl_to_spirv::ShaderType::Compute, - }; - - wgpu::read_spirv(glsl_to_spirv::compile(&code, ty).unwrap()).unwrap() -} - -pub fn generate_matrix(eye: &math::Vec3, fov: f32, aspect_ratio: f32, near: f32, far: f32) -> math::Mat4 { - let projection = math::perspective(aspect_ratio, fov, near, far); - - let view = math::look_at_rh::( - &eye, - &math::vec3(0.0, 0.0, 0.0), - &math::vec3(0.0, 0.0, 1.0), - ); - - opengl_to_wgpu_matrix() * projection * view -} +} \ No newline at end of file diff --git a/tiny-town/src/main.rs b/tiny-town/src/main.rs index 4cabc14e0f..7dfe8c89c7 100644 --- a/tiny-town/src/main.rs +++ b/tiny-town/src/main.rs @@ -2,10 +2,6 @@ use bevy::*; use bevy::legion::prelude::*; fn main() { - let universe = Universe::new(); - let mut world = universe.create_world(); - world.insert((), vec![(Transform::new(),)]); - // Create a query which finds all `Position` and `Velocity` components // let mut query = Read::::query(); Application::run();