diff --git a/examples/simple.rs b/examples/simple.rs index fc4b0f001d..1855901c31 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,8 +1,6 @@ use bevy::{Application, Transform}; use legion::prelude::*; -struct SimpleApp; - fn main() { Application::run(); // Create a world to store our entities @@ -14,7 +12,7 @@ fn main() { let mut query = Read::::query(); // // Iterate through all entities that match the query in the world - for mut trans in query.iter(&mut world) { + for _ in query.iter(&mut world) { // println!("{} hi", trans.global); } } diff --git a/notes/outline.md b/notes/outline.md index 73bce93793..a197ed58fb 100644 --- a/notes/outline.md +++ b/notes/outline.md @@ -86,5 +86,4 @@ * UpdateCollisions2d/NCollide * Dep: CollisionShape2d, PhysicsBody2d, GlobalTransform2d * UpdateRigidBodies2d/NCollide - * Dep: PhysicsBody2d, RigidBody2d, GlobalTransform2d - + * Dep: PhysicsBody2d, RigidBody2d, GlobalTransform2d \ No newline at end of file diff --git a/src/application.rs b/src/application.rs index d68e4fd01a..5169bc25a1 100644 --- a/src/application.rs +++ b/src/application.rs @@ -5,37 +5,24 @@ use winit::{ }; use zerocopy::AsBytes; -use nalgebra_glm as glm; use std::rc::Rc; use std::mem; -use crate::temp::*; -use crate::vertex::*; +use crate::{temp::*, vertex::*, render::*, math}; pub struct Application { entities: Vec, lights: Vec, lights_are_dirty: bool, - shadow_pass: Pass, - forward_pass: Pass, - forward_depth: wgpu::TextureView, - light_uniform_buf: wgpu::Buffer, - camera_position: glm::Vec3, + shadow_pass: ShadowPass, + forward_pass: ForwardPass, + camera_position: math::Vec3, camera_fov: f32, } impl Application { - const MAX_LIGHTS: usize = 10; - const SHADOW_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; - const SHADOW_SIZE: wgpu::Extent3d = wgpu::Extent3d { - width: 512, - height: 512, - depth: 1, - }; - const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; - fn init( sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device, @@ -85,7 +72,7 @@ impl Application { }], }); Entity { - mx_world: glm::identity(), + mx_world: math::identity(), rotation_speed: 0.0, color: wgpu::Color::WHITE, vertex_buf: Rc::new(plane_vertex_buf), @@ -96,28 +83,28 @@ impl Application { } }]; - let camera_position = glm::vec3(3.0f32, -10.0, 6.0); - let camera_fov = glm::quarter_pi(); + let camera_position = math::vec3(3.0f32, -10.0, 6.0); + let camera_fov = math::quarter_pi(); struct CubeDesc { - offset: glm::Vec3, + offset: math::Vec3, rotation: f32, } let cube_descs = [ CubeDesc { - offset: glm::vec3(-2.0, -2.0, 2.0), + offset: math::vec3(-2.0, -2.0, 2.0), rotation: 0.1, }, CubeDesc { - offset: glm::vec3(2.0, -2.0, 2.0), + offset: math::vec3(2.0, -2.0, 2.0), rotation: 0.2, }, CubeDesc { - offset: glm::vec3(-2.0, 2.0, 2.0), + offset: math::vec3(-2.0, 2.0, 2.0), rotation: 0.3, }, CubeDesc { - offset: glm::vec3(2.0, 2.0, 2.0), + offset: math::vec3(2.0, 2.0, 2.0), rotation: 0.4, }, ]; @@ -128,7 +115,7 @@ impl Application { usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, }); entities.push(Entity { - mx_world: glm::translation(&cube.offset), + mx_world: math::translation(&cube.offset), rotation_speed: cube.rotation, color: wgpu::Color::GREEN, vertex_buf: Rc::clone(&cube_vertex_buf), @@ -148,78 +135,6 @@ impl Application { }); } - // Create other resources - let shadow_sampler = device.create_sampler(&wgpu::SamplerDescriptor { - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::FilterMode::Nearest, - lod_min_clamp: -100.0, - lod_max_clamp: 100.0, - compare_function: wgpu::CompareFunction::LessEqual, - }); - - let shadow_texture = device.create_texture(&wgpu::TextureDescriptor { - size: Self::SHADOW_SIZE, - array_layer_count: Self::MAX_LIGHTS as u32, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: Self::SHADOW_FORMAT, - usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::SAMPLED, - }); - let shadow_view = shadow_texture.create_default_view(); - - let mut shadow_target_views = (0 .. 2) - .map(|i| { - Some(shadow_texture.create_view(&wgpu::TextureViewDescriptor { - format: Self::SHADOW_FORMAT, - dimension: wgpu::TextureViewDimension::D2, - aspect: wgpu::TextureAspect::All, - base_mip_level: 0, - level_count: 1, - base_array_layer: i as u32, - array_layer_count: 1, - })) - }) - .collect::>(); - let lights = vec![ - Light { - pos: glm::vec3(7.0, -5.0, 10.0), - color: wgpu::Color { - r: 0.5, - g: 1.0, - b: 0.5, - a: 1.0, - }, - fov: f32::to_radians(60.0), - depth: 1.0 .. 20.0, - target_view: shadow_target_views[0].take().unwrap(), - }, - Light { - pos: glm::vec3(-5.0, 7.0, 10.0), - color: wgpu::Color { - r: 1.0, - g: 0.5, - b: 0.5, - a: 1.0, - }, - fov: f32::to_radians(45.0), - depth: 1.0 .. 20.0, - target_view: shadow_target_views[1].take().unwrap(), - }, - ]; - let light_uniform_size = - (Self::MAX_LIGHTS * mem::size_of::()) as wgpu::BufferAddress; - let light_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { - size: light_uniform_size, - usage: wgpu::BufferUsage::UNIFORM - | wgpu::BufferUsage::COPY_SRC - | wgpu::BufferUsage::COPY_DST, - }); - let vb_desc = wgpu::VertexBufferDescriptor { stride: vertex_size as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, @@ -237,231 +152,55 @@ impl Application { ], }; - let shadow_pass = { - // Create pipeline layout - let bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: &[wgpu::BindGroupLayoutBinding { - binding: 0, // global - visibility: wgpu::ShaderStage::VERTEX, - ty: wgpu::BindingType::UniformBuffer { dynamic: false }, - }], - }); - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout], - }); - - let uniform_size = mem::size_of::() as wgpu::BufferAddress; - let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { - size: uniform_size, - usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - }); - - // Create bind group - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &bind_group_layout, - bindings: &[wgpu::Binding { - binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &uniform_buf, - range: 0 .. uniform_size, - }, - }], - }); - - // Create the render pipeline - let vs_bytes = - load_glsl(include_str!("render/bake/bake.vert"), ShaderStage::Vertex); - let fs_bytes = - load_glsl(include_str!("render/bake/bake.frag"), ShaderStage::Fragment); - let vs_module = device.create_shader_module(&vs_bytes); - let fs_module = device.create_shader_module(&fs_bytes); - - let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - layout: &pipeline_layout, - vertex_stage: wgpu::ProgrammableStageDescriptor { - module: &vs_module, - entry_point: "main", + let shadow_pass = ShadowPass::new(device, vb_desc.clone(), &local_bind_group_layout); + + let mut shadow_target_views = (0 .. 2) + .map(|i| { + Some(shadow_pass.shadow_texture.create_view(&wgpu::TextureViewDescriptor { + format: ShadowPass::SHADOW_FORMAT, + dimension: wgpu::TextureViewDimension::D2, + aspect: wgpu::TextureAspect::All, + base_mip_level: 0, + level_count: 1, + base_array_layer: i as u32, + array_layer_count: 1, + })) + }) + .collect::>(); + let lights = vec![ + Light { + pos: math::vec3(7.0, -5.0, 10.0), + color: wgpu::Color { + r: 0.5, + g: 1.0, + b: 0.5, + a: 1.0, }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: &fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { - front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, - depth_bias: 2, // corresponds to bilinear filtering - depth_bias_slope_scale: 2.0, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: Self::SHADOW_FORMAT, - depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::LessEqual, - stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE, - stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE, - stencil_read_mask: 0, - stencil_write_mask: 0, - }), - index_format: wgpu::IndexFormat::Uint16, - vertex_buffers: &[vb_desc.clone()], - sample_count: 1, - sample_mask: !0, - alpha_to_coverage_enabled: false, - }); - - Pass { - pipeline, - bind_group, - uniform_buf, - } - }; - - let forward_pass = { - // Create pipeline layout - let bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: &[ - wgpu::BindGroupLayoutBinding { - binding: 0, // global - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { dynamic: false }, - }, - wgpu::BindGroupLayoutBinding { - binding: 1, // lights - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { dynamic: false }, - }, - wgpu::BindGroupLayoutBinding { - binding: 2, - visibility: wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::SampledTexture { - multisampled: false, - dimension: wgpu::TextureViewDimension::D2Array, - }, - }, - wgpu::BindGroupLayoutBinding { - binding: 3, - visibility: wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler, - }, - ], - }); - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout], - }); - - let mx_total = generate_matrix(&camera_position, camera_fov, sc_desc.width as f32 / sc_desc.height as f32, 1.0, 20.0); - let forward_uniforms = ForwardUniforms { - proj: *mx_total.as_ref(), - num_lights: [lights.len() as u32, 0, 0, 0], - }; - let uniform_size = mem::size_of::() as wgpu::BufferAddress; - let uniform_buf = device.create_buffer_with_data( - forward_uniforms.as_bytes(), - wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - ); - - // Create bind group - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &bind_group_layout, - bindings: &[ - wgpu::Binding { - binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &uniform_buf, - range: 0 .. uniform_size, - }, - }, - wgpu::Binding { - binding: 1, - resource: wgpu::BindingResource::Buffer { - buffer: &light_uniform_buf, - range: 0 .. light_uniform_size, - }, - }, - wgpu::Binding { - binding: 2, - resource: wgpu::BindingResource::TextureView(&shadow_view), - }, - wgpu::Binding { - binding: 3, - resource: wgpu::BindingResource::Sampler(&shadow_sampler), - }, - ], - }); - - // Create the render pipeline - let vs_bytes = - load_glsl(include_str!("render/forward/forward.vert"), ShaderStage::Vertex); - let fs_bytes = - load_glsl(include_str!("render/forward/forward.frag"), ShaderStage::Fragment); - - let vs_module = device.create_shader_module(&vs_bytes); - let fs_module = device.create_shader_module(&fs_bytes); - - let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - layout: &pipeline_layout, - vertex_stage: wgpu::ProgrammableStageDescriptor { - module: &vs_module, - entry_point: "main", - }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: &fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { - front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, - depth_bias: 0, - depth_bias_slope_scale: 0.0, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[wgpu::ColorStateDescriptor { - format: sc_desc.format, - color_blend: wgpu::BlendDescriptor::REPLACE, - alpha_blend: wgpu::BlendDescriptor::REPLACE, - write_mask: wgpu::ColorWrite::ALL, - }], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: Self::DEPTH_FORMAT, - depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::Less, - stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE, - stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE, - stencil_read_mask: 0, - stencil_write_mask: 0, - }), - index_format: wgpu::IndexFormat::Uint16, - vertex_buffers: &[vb_desc], - sample_count: 1, - sample_mask: !0, - alpha_to_coverage_enabled: false, - }); - - Pass { - pipeline, - bind_group, - uniform_buf, - } - }; - - let depth_texture = device.create_texture(&wgpu::TextureDescriptor { - size: wgpu::Extent3d { - width: sc_desc.width, - height: sc_desc.height, - depth: 1, + fov: f32::to_radians(60.0), + depth: 1.0 .. 20.0, + target_view: shadow_target_views[0].take().unwrap(), }, - array_layer_count: 1, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: Self::DEPTH_FORMAT, - usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, - }); + Light { + pos: math::vec3(-5.0, 7.0, 10.0), + color: wgpu::Color { + r: 1.0, + g: 0.5, + b: 0.5, + a: 1.0, + }, + fov: f32::to_radians(45.0), + depth: 1.0 .. 20.0, + target_view: shadow_target_views[1].take().unwrap(), + }, + ]; + + let matrix = generate_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], + }; + + let forward_pass = ForwardPass::new(device, forward_uniforms, &shadow_pass, vb_desc, &local_bind_group_layout, sc_desc); let this = Application { entities, @@ -469,8 +208,6 @@ impl Application { lights_are_dirty: true, shadow_pass, forward_pass, - forward_depth: depth_texture.create_default_view(), - light_uniform_buf, camera_position, camera_fov }; @@ -491,24 +228,11 @@ impl Application { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); - encoder.copy_buffer_to_buffer(&temp_buf, 0, &self.forward_pass.uniform_buf, 0, 64); + encoder.copy_buffer_to_buffer(&temp_buf, 0, &self.forward_pass.forward_uniform_buffer, 0, 64); encoder.finish() }; - let depth_texture = device.create_texture(&wgpu::TextureDescriptor { - size: wgpu::Extent3d { - width: sc_desc.width, - height: sc_desc.height, - depth: 1, - }, - array_layer_count: 1, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: Self::DEPTH_FORMAT, - usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, - }); - self.forward_depth = depth_texture.create_default_view(); + self.forward_pass.update_swap_chain_descriptor(device, sc_desc); Some(command_buf) } @@ -538,7 +262,7 @@ impl Application { { if entity.rotation_speed != 0.0 { let rotation = - glm::rotation(entity.rotation_speed, &glm::vec3(0.0, 1.0, 0.0)); + math::rotation(entity.rotation_speed, &math::vec3(0.0, 1.0, 0.0)); entity.mx_world = entity.mx_world * rotation; } slot.copy_from_slice( @@ -584,7 +308,7 @@ impl Application { encoder.copy_buffer_to_buffer( &temp_buf_data.finish(), 0, - &self.light_uniform_buf, + &self.forward_pass.light_uniform_buffer, 0, total_size as wgpu::BufferAddress, ); @@ -594,7 +318,7 @@ impl Application { // 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_buf, + &self.forward_pass.light_uniform_buffer, (i * mem::size_of::()) as wgpu::BufferAddress, &self.shadow_pass.uniform_buf, 0, @@ -640,7 +364,7 @@ impl Application { }, }], depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &self.forward_depth, + attachment: &self.forward_pass.depth_texture, depth_load_op: wgpu::LoadOp::Clear, depth_store_op: wgpu::StoreOp::Store, stencil_load_op: wgpu::LoadOp::Clear, diff --git a/src/lib.rs b/src/lib.rs index 7b424913ad..8fe3809b08 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,10 @@ mod transform; mod application; mod vertex; mod temp; +mod render; pub use transform::Transform; pub use application::Application; -pub use legion; \ No newline at end of file + +pub use legion; +pub use nalgebra_glm as math; \ No newline at end of file diff --git a/src/render/forward/mod.rs b/src/render/forward/mod.rs new file mode 100644 index 0000000000..01d68df750 --- /dev/null +++ b/src/render/forward/mod.rs @@ -0,0 +1,193 @@ +use crate::{temp::*, render::shadow::ShadowPass}; + +use std::mem; +use zerocopy::{AsBytes, FromBytes}; +use wgpu::{Device, BindGroupLayout, VertexBufferDescriptor, SwapChainDescriptor}; + +#[repr(C)] +#[derive(Clone, Copy, AsBytes, FromBytes)] +pub struct ForwardUniforms { + pub proj: [[f32; 4]; 4], + pub num_lights: [u32; 4], +} + +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 depth_texture: wgpu::TextureView, +} + +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( + include_str!("forward.vert"), + ShaderStage::Vertex, + ); + let fs_bytes = load_glsl( + include_str!("forward.frag"), + ShaderStage::Fragment, + ); + + let bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + bindings: &[ + wgpu::BindGroupLayoutBinding { + binding: 0, // global + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, + }, + wgpu::BindGroupLayoutBinding { + binding: 1, // lights + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, + }, + wgpu::BindGroupLayoutBinding { + binding: 2, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::SampledTexture { + multisampled: false, + dimension: wgpu::TextureViewDimension::D2Array, + }, + }, + wgpu::BindGroupLayoutBinding { + binding: 3, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler, + }, + ], + }); + + let uniform_size = mem::size_of::() as wgpu::BufferAddress; + let forward_uniform_buffer = device.create_buffer_with_data( + forward_uniforms.as_bytes(), + 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, + bindings: &[ + wgpu::Binding { + binding: 0, + resource: wgpu::BindingResource::Buffer { + buffer: &forward_uniform_buffer, + range: 0 .. uniform_size, + }, + }, + wgpu::Binding { + binding: 1, + resource: wgpu::BindingResource::Buffer { + buffer: &light_uniform_buffer, + range: 0 .. light_uniform_size, + }, + }, + wgpu::Binding { + binding: 2, + resource: wgpu::BindingResource::TextureView(&shadow_pass.shadow_view), + }, + wgpu::Binding { + binding: 3, + resource: wgpu::BindingResource::Sampler(&shadow_pass.shadow_sampler), + }, + ], + }); + + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + bind_group_layouts: &[&bind_group_layout, local_bind_group_layout], + }); + + let vs_module = device.create_shader_module(&vs_bytes); + let fs_module = device.create_shader_module(&fs_bytes); + + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + layout: &pipeline_layout, + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: &vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: &fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[ + wgpu::ColorStateDescriptor { + format: swap_chain_descriptor.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }, + ], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: Self::DEPTH_FORMAT, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil_read_mask: 0, + stencil_write_mask: 0, + }), + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[vertex_buffer_descriptor], + sample_count: 1, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + + ForwardPass { + pipeline, + bind_group, + forward_uniform_buffer, + light_uniform_buffer, + depth_texture: Self::get_depth_texture(device, swap_chain_descriptor) + } + } + + + pub fn update_swap_chain_descriptor(&mut self, device: &Device, swap_chain_descriptor: &SwapChainDescriptor) { + self.depth_texture = Self::get_depth_texture(device, swap_chain_descriptor); + } + + fn get_depth_texture(device: &Device, swap_chain_descriptor: &SwapChainDescriptor) -> wgpu::TextureView { + let texture = device.create_texture(&wgpu::TextureDescriptor { + size: wgpu::Extent3d { + width: swap_chain_descriptor.width, + height: swap_chain_descriptor.height, + depth: 1, + }, + array_layer_count: 1, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: Self::DEPTH_FORMAT, + usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, + }); + + texture.create_default_view() + } +} + diff --git a/src/render/lib.rs b/src/render/lib.rs deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/render/mod.rs b/src/render/mod.rs new file mode 100644 index 0000000000..1d416a5bef --- /dev/null +++ b/src/render/mod.rs @@ -0,0 +1,5 @@ +mod forward; +mod shadow; + +pub use forward::{ForwardPass, ForwardUniforms}; +pub use shadow::ShadowPass; \ No newline at end of file diff --git a/src/render/shadow/mod.rs b/src/render/shadow/mod.rs new file mode 100644 index 0000000000..d6f57eb01c --- /dev/null +++ b/src/render/shadow/mod.rs @@ -0,0 +1,131 @@ +use crate::{temp::*, render::forward}; +use wgpu::{Device, BindGroupLayout, VertexBufferDescriptor}; +use std::mem; + +pub struct ShadowPass { + pub pipeline: wgpu::RenderPipeline, + pub bind_group: wgpu::BindGroup, + pub uniform_buf: wgpu::Buffer, + pub shadow_texture: wgpu::Texture, + pub shadow_view: wgpu::TextureView, + pub shadow_sampler: wgpu::Sampler, +} + +impl ShadowPass { + pub const SHADOW_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; + pub const SHADOW_SIZE: wgpu::Extent3d = wgpu::Extent3d { + width: 512, + height: 512, + depth: 1, + }; + + pub fn new(device: &Device, vertex_buffer_descriptor: VertexBufferDescriptor, local_bind_group_layout: &BindGroupLayout) -> ShadowPass { + // Create pipeline layout + let bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + bindings: &[wgpu::BindGroupLayoutBinding { + binding: 0, // global + visibility: wgpu::ShaderStage::VERTEX, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, + }], + }); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout], + }); + + let uniform_size = mem::size_of::() as wgpu::BufferAddress; + let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { + size: uniform_size, + usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + }); + + // Create bind group + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &bind_group_layout, + bindings: &[wgpu::Binding { + binding: 0, + resource: wgpu::BindingResource::Buffer { + buffer: &uniform_buf, + range: 0 .. uniform_size, + }, + }], + }); + + let shadow_texture = device.create_texture(&wgpu::TextureDescriptor { + size: Self::SHADOW_SIZE, + array_layer_count: forward::ForwardPass::MAX_LIGHTS as u32, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: Self::SHADOW_FORMAT, + usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::SAMPLED, + }); + + let shadow_view = shadow_texture.create_default_view(); + + // Create other resources + let shadow_sampler = device.create_sampler(&wgpu::SamplerDescriptor { + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + lod_min_clamp: -100.0, + lod_max_clamp: 100.0, + compare_function: wgpu::CompareFunction::LessEqual, + }); + + // Create the render pipeline + let vs_bytes = + load_glsl(include_str!("shadow.vert"), ShaderStage::Vertex); + let fs_bytes = + load_glsl(include_str!("shadow.frag"), ShaderStage::Fragment); + let vs_module = device.create_shader_module(&vs_bytes); + let fs_module = device.create_shader_module(&fs_bytes); + + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + layout: &pipeline_layout, + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: &vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: &fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + depth_bias: 2, // corresponds to bilinear filtering + depth_bias_slope_scale: 2.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: Self::SHADOW_FORMAT, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil_read_mask: 0, + stencil_write_mask: 0, + }), + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[vertex_buffer_descriptor], + sample_count: 1, + sample_mask: !0, + alpha_to_coverage_enabled: false, + }); + + ShadowPass { + pipeline, + bind_group, + uniform_buf, + shadow_texture, + shadow_view, + shadow_sampler + } + } +} diff --git a/src/render/bake/bake.frag b/src/render/shadow/shadow.frag similarity index 100% rename from src/render/bake/bake.frag rename to src/render/shadow/shadow.frag diff --git a/src/render/bake/bake.vert b/src/render/shadow/shadow.vert similarity index 100% rename from src/render/bake/bake.vert rename to src/render/shadow/shadow.vert diff --git a/src/temp.rs b/src/temp.rs index 00766e3c3e..b6a18e15f5 100644 --- a/src/temp.rs +++ b/src/temp.rs @@ -1,10 +1,10 @@ -pub use std::rc::Rc; -pub use std::ops::Range; +use std::{rc::Rc, ops::Range}; use zerocopy::{AsBytes, FromBytes}; -use nalgebra_glm as glm; +use crate::math; -pub fn opengl_to_wgpu_matrix() -> glm::Mat4 { - glm::mat4( + +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, @@ -12,7 +12,7 @@ pub fn opengl_to_wgpu_matrix() -> glm::Mat4 { ) } pub struct Entity { - pub mx_world: glm::Mat4, + pub mx_world: math::Mat4, pub rotation_speed: f32, pub color: wgpu::Color, pub vertex_buf: Rc, @@ -23,7 +23,7 @@ pub struct Entity { } pub struct Light { - pub pos: glm::Vec3, + pub pos: math::Vec3, pub color: wgpu::Color, pub fov: f32, pub depth: Range, @@ -53,13 +53,6 @@ impl Light { } } -#[repr(C)] -#[derive(Clone, Copy, AsBytes, FromBytes)] -pub struct ForwardUniforms { - pub proj: [[f32; 4]; 4], - pub num_lights: [u32; 4], -} - #[repr(C)] #[derive(Clone, Copy, AsBytes, FromBytes)] pub struct EntityUniforms { @@ -72,11 +65,11 @@ 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, -} +// pub struct Pass { +// pub pipeline: wgpu::RenderPipeline, +// pub bind_group: wgpu::BindGroup, +// pub uniform_buf: wgpu::Buffer, +// } #[allow(dead_code)] pub enum ShaderStage { @@ -95,13 +88,13 @@ pub fn load_glsl(code: &str, stage: ShaderStage) -> Vec { wgpu::read_spirv(glsl_to_spirv::compile(&code, ty).unwrap()).unwrap() } -pub fn generate_matrix(eye: &glm::Vec3, fov: f32, aspect_ratio: f32, near: f32, far: f32) -> glm::Mat4 { - let projection = glm::perspective(aspect_ratio, fov, near, far); +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 = glm::look_at_rh::( + let view = math::look_at_rh::( &eye, - &glm::vec3(0.0, 0.0, 0.0), - &glm::vec3(0.0, 0.0, 1.0), + &math::vec3(0.0, 0.0, 0.0), + &math::vec3(0.0, 0.0, 1.0), ); opengl_to_wgpu_matrix() * projection * view diff --git a/src/transform.rs b/src/transform.rs index 4d1abcee27..4cbd7bac65 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -1,16 +1,16 @@ -use nalgebra_glm as glm; +use crate::math; #[derive(Clone, Copy, Debug, PartialEq)] pub struct Transform { - pub local: glm::Mat4, - pub global: glm::Mat4, + pub local: math::Mat4, + pub global: math::Mat4, } impl Transform { pub fn new() -> Transform { Transform { - local: glm::identity(), - global: glm::identity(), + local: math::identity(), + global: math::identity(), } } } \ No newline at end of file