diff --git a/crates/comet_renderer/src/render_pass.rs b/crates/comet_renderer/src/render_pass.rs index 50c5b35..5415b66 100644 --- a/crates/comet_renderer/src/render_pass.rs +++ b/crates/comet_renderer/src/render_pass.rs @@ -2,20 +2,36 @@ use wgpu::{ShaderModule, BindGroup, BindGroupLayout, BufferUsages, Device, Queue use wgpu::util::DeviceExt; use comet_resources::{Vertex, Texture}; +#[derive(Debug, Clone)] +pub enum RenderPassType { + Engine, + User +} + pub struct RenderPassInfo { pass_name: String, + pass_type: RenderPassType, texture_bind_group: BindGroup, - shader: ShaderModule, vertex_buffer: wgpu::Buffer, index_buffer: wgpu::Buffer, vertex_data: Vec, index_data: Vec, num_indices: u32, - pipeline: RenderPipeline + pipeline: Option } impl RenderPassInfo { - pub fn new(device: &Device, pass_name: String, texture_group_layout: &BindGroupLayout, texture: &Texture, shader: ShaderModule, vertex_data: Vec, index_data: Vec, pipeline_layout: &PipelineLayout, config: &SurfaceConfiguration) -> Self { + pub fn new_user_pass( + device: &Device, + pass_name: String, + texture_group_layout: &BindGroupLayout, + texture: &Texture, + shader: ShaderModule, + vertex_data: Vec, + index_data: Vec, + pipeline_layout: &PipelineLayout, + config: &SurfaceConfiguration + ) -> Self { let num_indices = index_data.len() as u32; let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some(format!("{} Vertex Buffer", pass_name).as_str()), @@ -95,14 +111,62 @@ impl RenderPassInfo { Self { pass_name, + pass_type: RenderPassType::User, texture_bind_group, - shader, vertex_buffer, index_buffer, vertex_data, index_data, num_indices, - pipeline + pipeline: Some(pipeline) + } + } + + pub fn new_engine_pass( + device: &Device, + pass_name: String, + texture_group_layout: &BindGroupLayout, + texture: &Texture, + vertex_data: Vec, + index_data: Vec, + ) -> Self { + let num_indices = index_data.len() as u32; + let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some(format!("{} Vertex Buffer", pass_name).as_str()), + contents: bytemuck::cast_slice(&vertex_data), + usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, + }); + + let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some(format!("{} Index Buffer", pass_name).as_str()), + contents: bytemuck::cast_slice(&index_data), + usage: BufferUsages::INDEX | BufferUsages::COPY_DST, + }); + + let texture_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &texture_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&texture.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&texture.sampler), + }, + ], + label: Some(format!("{} Texture Bind Group", pass_name).as_str()), + }); + Self { + pass_name, + pass_type: RenderPassType::Engine, + texture_bind_group, + vertex_buffer, + index_buffer, + vertex_data, + index_data, + num_indices, + pipeline: None } } @@ -110,8 +174,59 @@ impl RenderPassInfo { &self.pass_name } - pub fn shader(&self) -> &ShaderModule { - &self.shader + pub fn pass_type(&self) -> RenderPassType { + self.pass_type.clone() + } + + pub fn set_shader(&mut self, device: &Device, config: &SurfaceConfiguration, pipeline_layout: &PipelineLayout, shader: &ShaderModule) { + self.pipeline = Some(device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Render Pipeline"), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + buffers: &[Vertex::desc()], + compilation_options: Default::default(), + }, + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format: config.format, + blend: Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add, + }, + }), + write_mask: wgpu::ColorWrites::ALL, + })], + compilation_options: Default::default(), + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: Some(wgpu::Face::Back), + polygon_mode: wgpu::PolygonMode::Fill, + unclipped_depth: false, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + multiview: None, + cache: None, + })); } pub fn texture_bind_group(&self) -> &BindGroup { @@ -216,7 +331,7 @@ impl RenderPassInfo { self.num_indices = self.index_data.len() as u32; } - pub fn pipeline(&self) -> &RenderPipeline { - &self.pipeline + pub fn pipeline(&self) -> Option<&RenderPipeline> { + self.pipeline.as_ref() } } \ No newline at end of file diff --git a/crates/comet_renderer/src/renderer2d.rs b/crates/comet_renderer/src/renderer2d.rs index b80e4cf..d0bbee2 100644 --- a/crates/comet_renderer/src/renderer2d.rs +++ b/crates/comet_renderer/src/renderer2d.rs @@ -9,13 +9,13 @@ use winit::dpi::PhysicalSize; use winit::window::Window; use comet_colors::{ Color, LinearRgba }; use comet_ecs::{Camera, Camera2D, Component, Position2D, Render, Render2D, Transform2D, Scene}; -use comet_log::{debug, info}; +use comet_log::{debug, error, info}; use comet_math::{Point2, Point3, Vec2, Vec3}; use comet_resources::{texture, graphic_resource_manager::GraphicResourceManager, Texture, Vertex}; use comet_resources::texture_atlas::TextureRegion; use comet_structs::ComponentSet; use crate::camera::{RenderCamera, CameraUniform}; -use crate::render_pass::RenderPassInfo; +use crate::render_pass::{RenderPassInfo, RenderPassType}; use crate::renderer::Renderer; pub struct Renderer2D<'a> { @@ -25,7 +25,8 @@ pub struct Renderer2D<'a> { config: wgpu::SurfaceConfiguration, size: PhysicalSize, render_pipeline_layout: wgpu::PipelineLayout, - diffuse_bind_group_layout: wgpu::BindGroupLayout, + universal_render_pipeline: wgpu::RenderPipeline, + texture_bind_group_layout: wgpu::BindGroupLayout, camera: RenderCamera, camera_uniform: CameraUniform, camera_buffer: wgpu::Buffer, @@ -96,20 +97,6 @@ impl<'a> Renderer2D<'a> { source: wgpu::ShaderSource::Wgsl(include_str!("base2d.wgsl").into()), }); - let geometry_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(&geometry_data), - usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, - }); - - let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Index Buffer"), - contents: bytemuck::cast_slice(&index_data), - usage: BufferUsages::INDEX | BufferUsages::COPY_DST - }); - - let num_indices = index_data.len() as u32; - let graphic_resource_manager = GraphicResourceManager::new(); let diffuse_bytes = include_bytes!(r"../../../resources/textures/comet_icon.png"); @@ -139,21 +126,6 @@ impl<'a> Renderer2D<'a> { label: Some("texture_bind_group_layout"), }); - let diffuse_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &texture_bind_group_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&diffuse_texture.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler), - }, - ], - label: Some("diffuse_bind_group"), - }); - let camera = RenderCamera::new(1.0, Vec2::new(2.0, 2.0), Vec3::new(0.0, 0.0, 0.0)); let mut camera_uniform = CameraUniform::new(); @@ -199,7 +171,7 @@ impl<'a> Renderer2D<'a> { push_constant_ranges: &[], }); - let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + let universal_render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Render Pipeline"), layout: Some(&render_pipeline_layout), vertex: wgpu::VertexState { @@ -248,20 +220,14 @@ impl<'a> Renderer2D<'a> { cache: None, }); - let mut pipelines = Vec::new(); - pipelines.push(render_pipeline); - let mut render_pass = Vec::new(); - render_pass.push(RenderPassInfo::new( + render_pass.push(RenderPassInfo::new_engine_pass( &device, - "Render Pass".to_string(), + "Standard Render Pass".to_string(), &texture_bind_group_layout, &diffuse_texture, - shader, geometry_data.clone(), index_data.clone(), - &render_pipeline_layout, - &config )); let clear_color = match clear_color { @@ -281,9 +247,10 @@ impl<'a> Renderer2D<'a> { config, size, render_pipeline_layout, - diffuse_bind_group_layout: texture_bind_group_layout, - camera: camera, - camera_uniform: camera_uniform, + universal_render_pipeline, + texture_bind_group_layout, + camera, + camera_uniform, camera_buffer, camera_bind_group, render_pass, @@ -335,7 +302,15 @@ impl<'a> Renderer2D<'a> { /// A function that applies a shader to the entire surface of the `Renderer2D` if the shader is loaded. pub fn apply_shader(&mut self, shader: &str) { - todo!() + let module = match self.graphic_resource_manager.get_shader(shader) { + Some(module) => module, + None => { + error!("Shader not found"); + return; + } + }; + + self.render_pass[0].set_shader(&self.device, &self.config, &self.render_pipeline_layout, module); } /// A function to revert back to the base shader of the `Renderer2D` @@ -374,7 +349,7 @@ impl<'a> Renderer2D<'a> { /// The old texture atlas will be replaced with the new one. pub fn set_texture_atlas_by_paths(&mut self, paths: Vec) { self.graphic_resource_manager.create_texture_atlas(paths); - self.render_pass[0].set_texture(&self.device, &self.diffuse_bind_group_layout, &Texture::from_image(&self.device, &self.queue, self.graphic_resource_manager.texture_atlas().atlas(), None, false).unwrap()); + self.render_pass[0].set_texture(&self.device, &self.texture_bind_group_layout, &Texture::from_image(&self.device, &self.queue, self.graphic_resource_manager.texture_atlas().atlas(), None, false).unwrap()); } fn switch_texture(&mut self, to: Texture) { @@ -764,7 +739,11 @@ impl<'a> Renderer2D<'a> { timestamp_writes: None, }); - render_pass.set_pipeline(pass.pipeline()); + match pass.pass_type() { + RenderPassType::Engine => render_pass.set_pipeline(&self.universal_render_pipeline), + RenderPassType::User => render_pass.set_pipeline(pass.pipeline().unwrap()), + } + render_pass.set_bind_group(0, pass.texture_bind_group(), &[]); render_pass.set_bind_group(1, &self.camera_bind_group, &[]); render_pass.set_vertex_buffer(0, pass.vertex_buffer().slice(..));