From f8dabf955e9cd38a7e2d92158b634e1d7a5cd3e6 Mon Sep 17 00:00:00 2001 From: lisk77 Date: Sun, 3 Aug 2025 02:11:45 +0200 Subject: [PATCH] feat(renderer): rewrote the core of the Renderer2D as a temporary module --- crates/comet_renderer/src/lib.rs | 7 +- .../comet_renderer/src/renderer2d_/base.wgsl | 25 +++ crates/comet_renderer/src/renderer2d_/mod.rs | 188 ++++++++++++++++++ .../src/renderer2d_/render_context.rs | 96 +++++++++ 4 files changed, 313 insertions(+), 3 deletions(-) create mode 100644 crates/comet_renderer/src/renderer2d_/base.wgsl create mode 100644 crates/comet_renderer/src/renderer2d_/mod.rs create mode 100644 crates/comet_renderer/src/renderer2d_/render_context.rs diff --git a/crates/comet_renderer/src/lib.rs b/crates/comet_renderer/src/lib.rs index 6b26511..f9667c2 100644 --- a/crates/comet_renderer/src/lib.rs +++ b/crates/comet_renderer/src/lib.rs @@ -1,6 +1,7 @@ mod camera; +mod draw_info; +mod render_group; +mod render_pass; pub mod renderer; pub mod renderer2d; -mod render_pass; -mod render_group; -mod draw_info; \ No newline at end of file +pub mod renderer2d_; diff --git a/crates/comet_renderer/src/renderer2d_/base.wgsl b/crates/comet_renderer/src/renderer2d_/base.wgsl new file mode 100644 index 0000000..07f27b8 --- /dev/null +++ b/crates/comet_renderer/src/renderer2d_/base.wgsl @@ -0,0 +1,25 @@ +struct VertexInput { + @location(0) position: vec3, + @location(1) tex_coords: vec2, + @location(2) color: vec4, +} + +struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) tex_coords: vec2, + @location(1) color: vec4, +} + +@vertex +fn vs_main(input: VertexInput) -> VertexOutput { + var out: VertexOutput; + out.clip_position = vec4(input.position, 1.0); + out.tex_coords = input.tex_coords; + out.color = input.color; + return out; +} + +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4 { + return in.color; +} diff --git a/crates/comet_renderer/src/renderer2d_/mod.rs b/crates/comet_renderer/src/renderer2d_/mod.rs new file mode 100644 index 0000000..8531d4c --- /dev/null +++ b/crates/comet_renderer/src/renderer2d_/mod.rs @@ -0,0 +1,188 @@ +mod render_context; + +use render_context::*; + +use crate::renderer::Renderer; +use comet_colors::Color; +use comet_resources::{graphic_resource_manager::GraphicResourceManager, Vertex}; +use std::iter; +use std::sync::Arc; +use wgpu::util::DeviceExt; +use winit::dpi::PhysicalSize; +use winit::window::Window; + +pub struct Renderer2D_<'a> { + render_context: RenderContext<'a>, + universal_render_pipeline: wgpu::RenderPipeline, + graphic_resource_manager: GraphicResourceManager, + vertex_vec: Vec, + vertex_buffer: wgpu::Buffer, + index_vec: Vec, + index_buffer: wgpu::Buffer, + num_indices: u32, + clear_color: wgpu::Color, +} + +impl<'a> Renderer2D_<'a> { + pub fn new(window: Arc, clear_color: Option) -> Renderer2D_<'a> { + let render_context = RenderContext::new(window.clone(), clear_color); + let graphic_resource_manager = GraphicResourceManager::new(); + let clear_color = match clear_color { + Some(color) => color.to_wgpu(), + None => wgpu::Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 1.0, + }, + }; + + let universal_renderpipeline_module = + render_context + .device + .create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("Universal Render Pipeline Shader Module"), + source: wgpu::ShaderSource::Wgsl(include_str!("base.wgsl").into()), + }); + + let universal_renderpipeline_layout = + render_context + .device + .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Universal Render Pipeline Layout"), + bind_group_layouts: &[], + push_constant_ranges: &[], + }); + + let universal_render_pipeline = + render_context + .device + .create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Universal Render Pipeline"), + layout: Some(&universal_renderpipeline_layout), + vertex: wgpu::VertexState { + module: &universal_renderpipeline_module, + entry_point: "vs_main", + buffers: &[Vertex::desc()], + compilation_options: Default::default(), + }, + fragment: Some(wgpu::FragmentState { + module: &universal_renderpipeline_module, + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format: render_context.config.format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + 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, + }); + + let vertex_buffer = + render_context + .device + .create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Vertex Buffer"), + contents: &[], + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, + }); + + let index_buffer = + render_context + .device + .create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Index Buffer"), + contents: &[], + usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST, + }); + + Self { + render_context, + universal_render_pipeline, + graphic_resource_manager, + vertex_buffer, + vertex_vec: vec![], + index_buffer, + index_vec: vec![], + num_indices: 0, + clear_color, + } + } +} + +impl<'a> Renderer for Renderer2D_<'a> { + fn new(window: Arc, clear_color: Option) -> Renderer2D_<'a> { + Self::new(window, clear_color) + } + + fn size(&self) -> PhysicalSize { + self.render_context.size() + } + + fn resize(&mut self, new_size: PhysicalSize) { + self.render_context.resize(new_size) + } + + fn update(&mut self) -> f32 { + self.render_context.update() + } + + fn render(&mut self) -> Result<(), wgpu::SurfaceError> { + let output = self.render_context.surface.get_current_texture()?; + let output_view = output + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + + let mut encoder = + self.render_context + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Render Encoder"), + }); + + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("Universal Render Pass"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &output_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(self.clear_color), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + occlusion_query_set: None, + timestamp_writes: None, + }); + + render_pass.set_pipeline(&self.universal_render_pipeline); + render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); + render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint32); + render_pass.draw_indexed(0..self.num_indices, 0, 0..1); + } + + self.render_context + .queue + .submit(iter::once(encoder.finish())); + output.present(); + Ok(()) + } +} diff --git a/crates/comet_renderer/src/renderer2d_/render_context.rs b/crates/comet_renderer/src/renderer2d_/render_context.rs new file mode 100644 index 0000000..de56812 --- /dev/null +++ b/crates/comet_renderer/src/renderer2d_/render_context.rs @@ -0,0 +1,96 @@ +use comet_colors::Color; +use std::sync::Arc; +use std::time::Instant; +use winit::dpi::PhysicalSize; +use winit::window::Window; + +pub struct RenderContext<'a> { + pub surface: wgpu::Surface<'a>, + pub device: wgpu::Device, + pub queue: wgpu::Queue, + pub config: wgpu::SurfaceConfiguration, + pub size: PhysicalSize, + pub last_frame_time: Instant, + pub delta_time: f32, +} + +impl<'a> RenderContext<'a> { + pub fn new(window: Arc, clear_color: Option) -> RenderContext<'a> { + let size = window.inner_size(); + + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: wgpu::Backends::PRIMARY, + ..Default::default() + }); + + let surface = instance.create_surface(window).unwrap(); + + let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::default(), + compatible_surface: Some(&surface), + force_fallback_adapter: false, + })) + .unwrap(); + + let (device, queue) = pollster::block_on(adapter.request_device( + &wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::default(), + memory_hints: Default::default(), + }, + None, + )) + .unwrap(); + + let surface_caps = surface.get_capabilities(&adapter); + let surface_format = surface_caps + .formats + .iter() + .copied() + .find(|f| f.is_srgb()) + .unwrap_or(surface_caps.formats[0]); + + let config = wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format: surface_format, + width: size.width, + height: size.height, + present_mode: surface_caps.present_modes[0], + alpha_mode: surface_caps.alpha_modes[0], + view_formats: vec![], + desired_maximum_frame_latency: 2, + }; + + Self { + surface, + device, + queue, + config, + size, + last_frame_time: Instant::now(), + delta_time: 0.0, + } + } + + pub fn size(&self) -> PhysicalSize { + self.size + } + + pub fn resize(&mut self, new_size: PhysicalSize) { + if new_size.width > 0 && new_size.height > 0 { + self.size = new_size; + self.config.width = new_size.width; + self.config.height = new_size.height; + self.surface.configure(&self.device, &self.config); + } + } + + pub fn update(&mut self) -> f32 { + let now = Instant::now(); + let delta_time = now.duration_since(self.last_frame_time).as_millis() as f32 / 1000.0; + self.last_frame_time = now; + self.delta_time = delta_time; + delta_time + } +}