diff --git a/src/main.rs b/src/main.rs index 804a0f3..f5b24fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use bytemuck::__core::ops::Range; -use cgmath::{Matrix4, Point3}; +use cgmath::{Matrix4, Point3, Decomposed, Quaternion, Rotation3, Deg, InnerSpace, SquareMatrix}; use futures::task::LocalSpawn; use legion::*; use wgpu::{BindGroup, Buffer, TextureView}; @@ -138,6 +138,9 @@ pub struct Mesh { fn main() { + + + // #[cfg(not(target_arch = "wasm32"))] // { // let chrome_tracing_dir = std::env::var("WGPU_CHROME_TRACE"); @@ -215,9 +218,18 @@ fn main() { let mut renderer = render::Renderer::init(window); let untitled_mesh = - renderer.load_mesh_to_buffer("./resources/untitled.obj"); + renderer.load_mesh_to_buffer("./resources/monkey.obj"); // This could be used for relationships between entities...??? + let light_entity: Entity = world.push(( + cgmath::Point3 { + x: 7.0 as f32, + y: -5.0 as f32, + z: 10.0 as f32, + }, + renderer.create_light(), + )); + let light_entity: Entity = world.push(( cgmath::Point3 { x: -5.0 as f32, @@ -227,12 +239,19 @@ fn main() { renderer.create_light(), )); + let offset = cgmath::vec3(2.0, 2.0, 2.0); + let transform = Decomposed { + disp: offset.clone(), + rot: Quaternion::from_axis_angle(offset.normalize(), Deg(50.0)), + scale: 1.0, + }; + let mesh_entity: Entity = world.push(( Position { - x: -5.0, - y: 7.0, + x: 17.0, + y: 15.0, z: 10.0, - mx: OPENGL_TO_WGPU_MATRIX, + mx: cgmath::Matrix4::from(transform), }, untitled_mesh, Color { @@ -243,47 +262,25 @@ fn main() { }, )); - let entities: &[Entity] = world.extend(vec![ - ( - Position { - x: 0.0, - y: 0.0, - z: 0.0, - mx: OPENGL_TO_WGPU_MATRIX, - }, - Velocity { - dx: 0.0, - dy: 0.0, - rs: 0.0, - }, - ), - ( - Position { - x: 1.0, - y: 1.0, - z: 0.0, - mx: OPENGL_TO_WGPU_MATRIX, - }, - Velocity { - dx: 0.0, - dy: 0.0, - rs: 0.0, - }, - ), - ( - Position { - x: 2.0, - y: 2.0, - z: 0.0, - mx: OPENGL_TO_WGPU_MATRIX, - }, - Velocity { - dx: 0.0, - dy: 0.0, - rs: 0.0, - }, - ), - ]); + let plane_mesh = + renderer.create_plane(7.0); + + // let plane_entity: Entity = world.push(( + // Position { + // x: 0.0, + // y: 0.0, + // z: 0.0, + // mx: cgmath::Matrix4::identity(), + // }, + // plane_mesh, + // Color { + // r: 1.0, + // g: 0.5, + // b: 0.5, + // a: 1.0, + // }, + // )); + // Init, this wants the references to the buffers... let mut runtime = runtime::Runtime::init(); diff --git a/src/render.rs b/src/render.rs index 2f81f74..232af00 100644 --- a/src/render.rs +++ b/src/render.rs @@ -8,16 +8,18 @@ use futures::executor::LocalPool; use legion::world::SubWorld; use legion::*; use wgpu::util::DeviceExt; -use wgpu::{BindGroup, BindGroupLayout, Buffer, Device, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame, TextureView}; +use wgpu::{ + BindGroup, BindGroupLayout, Buffer, Device, Instance, Queue, Surface, SwapChain, + SwapChainDescriptor, SwapChainFrame, TextureView, +}; use winit::dpi::PhysicalSize; use winit::platform::unix::x11::ffi::Time; use winit::window::Window; -use crate::geometry::{create_plane, import_mesh, Vertex}; +use crate::geometry::{create_plane, import_mesh, vertex, Vertex}; use crate::light::LightRaw; use crate::{Color, DirectionalLight, Mesh, Position, RangeCopy, Velocity, OPENGL_TO_WGPU_MATRIX}; - #[repr(C)] #[derive(Clone, Copy)] pub struct ForwardUniforms { @@ -69,6 +71,7 @@ pub struct Renderer { entity_bind_group_layout: BindGroupLayout, shadow_target_views: Vec>, + views_given: u32, light_uniform_buf: wgpu::Buffer, } @@ -102,14 +105,21 @@ impl Renderer { #[write_component(Color)] #[write_component(DirectionalLight)] pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) { + let mut encoder = renderer + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); + encoder.push_debug_group("start render function"); + let frame = renderer.get_current_frame(); let mut query = <(&mut Position, &mut Mesh, &mut Color)>::query(); + let mut mesh_stack = Vec::new(); + // Update the entity uniforms for (pos, mesh, color) in query.iter_mut(world) { - let rotation = cgmath::Matrix4::from_angle_x(cgmath::Deg(1.0)); - pos.mx = pos.mx * rotation; + // let rotation = cgmath::Matrix4::from_angle_x(cgmath::Deg(1.0)); + // pos.mx = pos.mx * rotation; let data = EntityUniforms { model: pos.mx.into(), @@ -123,10 +133,12 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) { renderer .queue .write_buffer(&mesh.uniform_buffer, 0, bytemuck::bytes_of(&data)); + + mesh_stack.push(mesh.clone()); } if renderer.lights_are_dirty { - renderer.lights_are_dirty = false; + //renderer.lights_are_dirty = false; let mut query = <(&mut DirectionalLight, &mut Position)>::query(); for (i, (light, pos)) in query.iter_mut(world).enumerate() { renderer.queue.write_buffer( @@ -137,22 +149,13 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) { } } - let mut encoder = renderer - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); - encoder.push_debug_group("shadow passes"); let mut query = <(&mut DirectionalLight, &mut Point3)>::query(); - let mut light_stack = Vec::new(); for (i, (light, pos)) in query.iter_mut(world).enumerate() { - light_stack.push(light.clone()); - encoder.push_debug_group(&format!( - "shadow pass {} (light at position {:?})", - i, pos - )); + encoder.insert_debug_marker(&format!("shadow pass {} (light at position {:?})", i, pos)); // The light uniform buffer already has the projection, // let's just copy it over to the shadow uniform buffer. @@ -164,41 +167,33 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) { 64, ); - encoder.pop_debug_group(); - } - - for light in light_stack { encoder.insert_debug_marker("render entities"); - { - let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[], - depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &light.target_view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: true, - }), - stencil_ops: None, - }), - }); - pass.set_pipeline(&renderer.shadow_pass.pipeline); - pass.set_bind_group(0, &renderer.shadow_pass.bind_group, &[]); - let mut query = <(&mut Position, &mut Mesh, &mut Color)>::query(); + let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &light.target_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }), + }); + pass.set_pipeline(&renderer.shadow_pass.pipeline); + pass.set_bind_group(0, &renderer.shadow_pass.bind_group, &[]); - for (pos, mesh, color) in query.iter_mut(world) { - pass.set_bind_group(1, &mesh.bind_group, &[]); - pass.set_index_buffer(mesh.index_buffer.slice(..)); - pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..)); - pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1); - } - } - } + for mesh in &mesh_stack { + pass.set_bind_group(1, &mesh.bind_group, &[]); + pass.set_index_buffer(mesh.index_buffer.slice(..)); + pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..)); + pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1); + } + } encoder.pop_debug_group(); - // forward pass encoder.push_debug_group("forward rendering pass"); { @@ -235,21 +230,10 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) { pass.set_index_buffer(mesh.index_buffer.slice(..)); pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..)); pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1); - let data = EntityUniforms { - model: pos.mx.into(), - color: [ - color.r as f32, - color.g as f32, - color.b as f32, - color.a as f32, - ], - }; - renderer - .queue - .write_buffer(&mesh.uniform_buffer, 0, bytemuck::bytes_of(&data)); } } encoder.pop_debug_group(); + encoder.pop_debug_group(); renderer.queue.submit(iter::once(encoder.finish())); } @@ -275,9 +259,6 @@ impl Renderer { indices: Vec, vertices: Vec, ) -> (Arc, Arc) { - // Creates the vertex and index buffers for the cube - let vertex_size = mem::size_of::(); - //import_mesh("/home/mrh/source/3d-min-viable-eng/resources/my_tree.obj"); let vertex_buf = Arc::new( device.create_buffer_init(&wgpu::util::BufferInitDescriptor { @@ -298,9 +279,9 @@ impl Renderer { (vertex_buf, index_buf) } - pub fn create_light(&self) -> DirectionalLight { - - let target = self.shadow_target_views.get(0).take().unwrap(); + pub fn create_light(&mut self) -> DirectionalLight { + let target = self.shadow_target_views.get(self.views_given as usize).take().unwrap(); + self.views_given = self.views_given + 1; DirectionalLight { color: wgpu::Color { r: 1.0, @@ -313,7 +294,46 @@ impl Renderer { start: 1.0, end: 20.0, }, - target_view: target.clone() + target_view: target.clone(), + } + } + + pub fn create_plane(&self, size: f32) -> Mesh { + let vertices = [ + vertex([size, -size, 0.0], [0.0, 0.0, 1.0]), + vertex([size, size, 0.0], [0.0, 0.0, 1.0]), + vertex([-size, -size, 0.0], [0.0, 0.0, 1.0]), + vertex([-size, size, 0.0], [0.0, 0.0, 1.0]), + ]; + + let indices: &[u32] = &[0, 1, 2, 2, 1, 3]; + + let index_count = indices.len(); + let (vertex_buf, index_buf) = + Renderer::create_buffer(&self.device, indices.to_vec(), vertices.to_vec()); + + let uniform_buf = Arc::new(self.device.create_buffer(&wgpu::BufferDescriptor { + label: Some("Plane Uniform Buf"), + size: mem::size_of::() as wgpu::BufferAddress, + usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + mapped_at_creation: false, + })); + + let bind_group = Arc::new(self.device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &self.entity_bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)), + }], + label: Some("Plane Bind Group"), + })); + + Mesh { + index_buffer: index_buf, + index_count: index_count, + vertex_buffer: vertex_buf, + uniform_buffer: uniform_buf, + bind_group: bind_group, } } @@ -323,7 +343,7 @@ impl Renderer { let (vertex_buf, index_buf) = Renderer::create_buffer(&self.device, indices, vertices); let uniform_buf = Arc::new(self.device.create_buffer(&wgpu::BufferDescriptor { - label: None, + label: Some("Mesh Uniform Buf"), size: mem::size_of::() as wgpu::BufferAddress, usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, mapped_at_creation: false, @@ -335,7 +355,7 @@ impl Renderer { binding: 0, resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)), }], - label: None, + label: Some("Mesh Bind Group"), })); Mesh { @@ -440,12 +460,6 @@ impl Renderer { let mut swap_chain = device.create_swap_chain(&surface, &sc_desc); let entity_uniform_size = mem::size_of::() as wgpu::BufferAddress; - let plane_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { - label: None, - size: entity_uniform_size, - usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - mapped_at_creation: false, - }); // This seems way way way way easier than what I was doing in tracer // Though the attr thing is still a macro. Which would cause issues if @@ -461,7 +475,7 @@ impl Renderer { // This is also in the runtime which really shouldn't have this let entity_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, + label: Some("Entity Bind Group Layout"), entries: &[wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, @@ -486,7 +500,7 @@ impl Renderer { // I believe this is just making a_Pos or u_ViewProj available in the vert shader let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: None, + label: Some("Shadow pass bind group layout"), entries: &[wgpu::BindGroupLayoutEntry { binding: 0, // global visibility: wgpu::ShaderStage::VERTEX, @@ -500,14 +514,14 @@ impl Renderer { // Pipeline is similar between passes, but with a different label let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("shadow"), + label: Some("shadow pass pipeline layout"), bind_group_layouts: &[&bind_group_layout, &entity_bind_group_layout], push_constant_ranges: &[], }); // Holds the shadow uniforms, which is just a 4 vec of quaternians let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { - label: None, + label: Some("shadow pass shadow uniform buffer"), size: uniform_size, usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, mapped_at_creation: false, @@ -520,7 +534,7 @@ impl Renderer { binding: 0, resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)), }], - label: None, + label: Some("Shadow uniform bind group"), }); // Create the render pipeline @@ -577,7 +591,7 @@ impl Renderer { (Self::MAX_LIGHTS * mem::size_of::()) as wgpu::BufferAddress; let light_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { - label: None, + label: Some("Light uniform buffer"), size: light_uniform_size, usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_SRC @@ -592,7 +606,7 @@ impl Renderer { dimension: wgpu::TextureDimension::D2, format: Self::SHADOW_FORMAT, usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::SAMPLED, - label: None, + label: Some("Shadow texture"), }); let mut shadow_target_views = (0..2) @@ -654,7 +668,7 @@ impl Renderer { count: None, }, ], - label: None, + label: Some("Forward pass bind group layout"), }); let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { @@ -669,21 +683,15 @@ impl Renderer { let forward_uniforms = ForwardUniforms { proj: *mx_total.as_ref(), //num_lights: [lights.len() as u32, 0, 0, 0], - num_lights: [1 as u32, 0, 0, 0], + num_lights: [2 as u32, 0, 0, 0], }; let uniform_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Uniform Buffer"), + label: Some("Forward pass binding 0 uniform buffer"), contents: bytemuck::bytes_of(&forward_uniforms), usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, }); - - // shadow_target_views[0].take().unwrap(), - // pub(crate) target_view: wgpu::TextureView, - - let shadow_view = shadow_texture.create_view(&wgpu::TextureViewDescriptor::default()); - let shadow_sampler = device.create_sampler(&wgpu::SamplerDescriptor { label: Some("shadow"), address_mode_u: wgpu::AddressMode::ClampToEdge, @@ -696,6 +704,8 @@ impl Renderer { ..Default::default() }); + let shadow_view = shadow_texture.create_view(&wgpu::TextureViewDescriptor::default()); + // Create bind group let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &bind_group_layout, @@ -717,7 +727,7 @@ impl Renderer { resource: wgpu::BindingResource::Sampler(&shadow_sampler), }, ], - label: None, + label: Some("Forward pass bind group"), }); // Create the render pipeline @@ -777,7 +787,7 @@ impl Renderer { dimension: wgpu::TextureDimension::D2, format: Self::DEPTH_FORMAT, usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, - label: None, + label: Some("Depth Texture"), }); Renderer { @@ -786,7 +796,7 @@ impl Renderer { queue: queue, size, device: device, - lights_are_dirty: false, + lights_are_dirty: true, shadow_pass, forward_pass, forward_depth: depth_texture.create_view(&wgpu::TextureViewDescriptor::default()), @@ -796,6 +806,7 @@ impl Renderer { swapchain_description: sc_desc, surface, instance: Arc::new(instance), + views_given: 0, } } @@ -828,7 +839,7 @@ impl Renderer { dimension: wgpu::TextureDimension::D2, format: Self::DEPTH_FORMAT, usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, - label: None, + label: Some("Depth Texture"), }); self.forward_depth = depth_texture.create_view(&wgpu::TextureViewDescriptor::default()); }