mirror of
https://github.com/lisk77/comet.git
synced 2025-10-24 05:48:50 +00:00
feat: added a RenderPassInfo struct that allows for easily managed multiple render passes in the Renderer2D
This commit is contained in:
parent
490db93137
commit
661e3aa67a
3 changed files with 263 additions and 369 deletions
|
|
@ -1,29 +1,222 @@
|
||||||
use comet_resources::Vertex;
|
use wgpu::{ShaderModule, BindGroup, BindGroupLayout, BufferUsages, Device, Queue, RenderPipeline, PipelineLayout, SurfaceConfiguration, TextureFormat};
|
||||||
|
use wgpu::util::DeviceExt;
|
||||||
|
use comet_resources::{Vertex, Texture};
|
||||||
|
|
||||||
pub struct RenderPassInfo {
|
pub struct RenderPassInfo {
|
||||||
shader: &'static str,
|
pass_name: String,
|
||||||
vertex_buffer: Vec<Vertex>,
|
texture_bind_group: BindGroup,
|
||||||
index_buffer: Vec<u16>,
|
shader: ShaderModule,
|
||||||
|
vertex_buffer: wgpu::Buffer,
|
||||||
|
index_buffer: wgpu::Buffer,
|
||||||
|
vertex_data: Vec<Vertex>,
|
||||||
|
index_data: Vec<u16>,
|
||||||
|
num_indices: u32,
|
||||||
|
pipeline: RenderPipeline
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderPassInfo {
|
impl RenderPassInfo {
|
||||||
pub fn new(shader: &'static str, vertex_buffer: Vec<Vertex>, index_buffer: Vec<u16>) -> Self {
|
pub fn new(device: &Device, pass_name: String, texture_group_layout: &BindGroupLayout, texture: &Texture, shader: ShaderModule, vertex_data: Vec<Vertex>, index_data: Vec<u16>, 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()),
|
||||||
|
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()),
|
||||||
|
});
|
||||||
|
|
||||||
|
let pipeline = 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,
|
||||||
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
pass_name,
|
||||||
|
texture_bind_group,
|
||||||
shader,
|
shader,
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
index_buffer
|
index_buffer,
|
||||||
|
vertex_data,
|
||||||
|
index_data,
|
||||||
|
num_indices,
|
||||||
|
pipeline
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shader(&self) -> &'static str {
|
pub fn pass_name(&self) -> &str {
|
||||||
self.shader
|
&self.pass_name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vertex_buffer(&self) -> &Vec<Vertex> {
|
pub fn shader(&self) -> &ShaderModule {
|
||||||
|
&self.shader
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn texture_bind_group(&self) -> &BindGroup {
|
||||||
|
&self.texture_bind_group
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_texture(&mut self, device: &Device, layout: &BindGroupLayout, texture: &Texture) {
|
||||||
|
self.texture_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
layout: &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", self.pass_name).as_str()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vertex_buffer(&self) -> &wgpu::Buffer {
|
||||||
&self.vertex_buffer
|
&self.vertex_buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index_buffer(&self) -> &Vec<u16> {
|
pub fn vertex_data(&self) -> &Vec<Vertex> {
|
||||||
|
&self.vertex_data
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_vertex_buffer(&mut self, device: &Device, queue: &Queue, vertex_data: Vec<Vertex>) {
|
||||||
|
let new_vertex_size = vertex_data.len() as u64 * size_of::<Vertex>() as u64;
|
||||||
|
match vertex_data == self.vertex_data {
|
||||||
|
true => {},
|
||||||
|
false => {
|
||||||
|
match new_vertex_size > self.vertex_buffer.size() {
|
||||||
|
false => queue.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&vertex_data)),
|
||||||
|
true => {
|
||||||
|
self.vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some(format!("{} Vertex Buffer", self.pass_name).as_str()),
|
||||||
|
contents: bytemuck::cast_slice(&vertex_data),
|
||||||
|
usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.vertex_data = vertex_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_to_vertex_buffer(&mut self, device: &Device, vertex_data: &mut Vec<Vertex>) {
|
||||||
|
self.vertex_data.append(vertex_data);
|
||||||
|
self.vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some(format!("{} Vertex Buffer", self.pass_name).as_str()),
|
||||||
|
contents: bytemuck::cast_slice(&vertex_data),
|
||||||
|
usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn index_buffer(&self) -> &wgpu::Buffer {
|
||||||
&self.index_buffer
|
&self.index_buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn index_data(&self) -> &Vec<u16> {
|
||||||
|
&self.index_data
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_indices(&self) -> u32 {
|
||||||
|
self.num_indices
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_index_buffer(&mut self, device: &Device, queue: &Queue, index_data: Vec<u16>) {
|
||||||
|
let new_index_size = index_data.len() as u64 * size_of::<u16>() as u64;
|
||||||
|
match index_data == self.index_data {
|
||||||
|
true => {},
|
||||||
|
false => {
|
||||||
|
match new_index_size > self.index_buffer.size() {
|
||||||
|
false => queue.write_buffer(&self.index_buffer, 0, bytemuck::cast_slice(&index_data)),
|
||||||
|
true => {
|
||||||
|
self.index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some(format!("{} Index Buffer", self.pass_name).as_str()),
|
||||||
|
contents: bytemuck::cast_slice(&index_data),
|
||||||
|
usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.num_indices = index_data.len() as u32;
|
||||||
|
self.index_data = index_data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_to_index_buffer(&mut self, device: &Device, index_data: &mut Vec<u16>) {
|
||||||
|
self.index_data.append(index_data);
|
||||||
|
self.index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some(format!("{} Index Buffer", self.pass_name).as_str()),
|
||||||
|
contents: bytemuck::cast_slice(&index_data),
|
||||||
|
usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.num_indices = self.index_data.len() as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pipeline(&self) -> &RenderPipeline {
|
||||||
|
&self.pipeline
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -25,29 +25,21 @@ pub struct Renderer2D<'a> {
|
||||||
config: wgpu::SurfaceConfiguration,
|
config: wgpu::SurfaceConfiguration,
|
||||||
size: PhysicalSize<u32>,
|
size: PhysicalSize<u32>,
|
||||||
render_pipeline_layout: wgpu::PipelineLayout,
|
render_pipeline_layout: wgpu::PipelineLayout,
|
||||||
pipelines: Vec<wgpu::RenderPipeline>,
|
|
||||||
render_pass: Vec<RenderPassInfo>,
|
|
||||||
last_frame_time: Instant,
|
|
||||||
delta_time: f32,
|
|
||||||
vertex_buffer: wgpu::Buffer,
|
|
||||||
vertex_data: Vec<Vertex>,
|
|
||||||
index_buffer: wgpu::Buffer,
|
|
||||||
index_data: Vec<u16>,
|
|
||||||
num_indices: u32,
|
|
||||||
clear_color: wgpu::Color,
|
|
||||||
diffuse_texture: Texture,
|
|
||||||
diffuse_bind_group_layout: wgpu::BindGroupLayout,
|
diffuse_bind_group_layout: wgpu::BindGroupLayout,
|
||||||
diffuse_bind_group: wgpu::BindGroup,
|
|
||||||
graphic_resource_manager: GraphicResourceManager,
|
|
||||||
camera: RenderCamera,
|
camera: RenderCamera,
|
||||||
camera_uniform: CameraUniform,
|
camera_uniform: CameraUniform,
|
||||||
camera_buffer: wgpu::Buffer,
|
camera_buffer: wgpu::Buffer,
|
||||||
camera_bind_group: wgpu::BindGroup,
|
camera_bind_group: wgpu::BindGroup,
|
||||||
|
render_pass: Vec<RenderPassInfo>,
|
||||||
|
graphic_resource_manager: GraphicResourceManager,
|
||||||
|
delta_time: f32,
|
||||||
|
last_frame_time: Instant,
|
||||||
|
clear_color: wgpu::Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Renderer2D<'a> {
|
impl<'a> Renderer2D<'a> {
|
||||||
pub async fn new(window: Arc<Window>, clear_color: Option<impl Color>) -> Renderer2D<'a> {
|
pub async fn new(window: Arc<Window>, clear_color: Option<impl Color>) -> Renderer2D<'a> {
|
||||||
let vertex_data: Vec<Vertex> = vec![];
|
let geometry_data: Vec<Vertex> = vec![];
|
||||||
let index_data: Vec<u16> = vec![];
|
let index_data: Vec<u16> = vec![];
|
||||||
|
|
||||||
let size = PhysicalSize::<u32>::new(1920, 1080);
|
let size = PhysicalSize::<u32>::new(1920, 1080);
|
||||||
|
|
@ -104,9 +96,9 @@ impl<'a> Renderer2D<'a> {
|
||||||
source: wgpu::ShaderSource::Wgsl(include_str!("base2d.wgsl").into()),
|
source: wgpu::ShaderSource::Wgsl(include_str!("base2d.wgsl").into()),
|
||||||
});
|
});
|
||||||
|
|
||||||
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let geometry_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some("Vertex Buffer"),
|
label: Some("Vertex Buffer"),
|
||||||
contents: bytemuck::cast_slice(&vertex_data),
|
contents: bytemuck::cast_slice(&geometry_data),
|
||||||
usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
|
usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -259,6 +251,19 @@ impl<'a> Renderer2D<'a> {
|
||||||
let mut pipelines = Vec::new();
|
let mut pipelines = Vec::new();
|
||||||
pipelines.push(render_pipeline);
|
pipelines.push(render_pipeline);
|
||||||
|
|
||||||
|
let mut render_pass = Vec::new();
|
||||||
|
render_pass.push(RenderPassInfo::new(
|
||||||
|
&device,
|
||||||
|
"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 {
|
let clear_color = match clear_color {
|
||||||
Some(color) => color.to_wgpu(),
|
Some(color) => color.to_wgpu(),
|
||||||
None => wgpu::Color {
|
None => wgpu::Color {
|
||||||
|
|
@ -276,24 +281,16 @@ impl<'a> Renderer2D<'a> {
|
||||||
config,
|
config,
|
||||||
size,
|
size,
|
||||||
render_pipeline_layout,
|
render_pipeline_layout,
|
||||||
pipelines,
|
|
||||||
render_pass: vec![],
|
|
||||||
last_frame_time: Instant::now(),
|
|
||||||
delta_time: 0.0,
|
|
||||||
vertex_buffer,
|
|
||||||
vertex_data,
|
|
||||||
index_buffer,
|
|
||||||
index_data,
|
|
||||||
num_indices,
|
|
||||||
clear_color,
|
|
||||||
diffuse_texture,
|
|
||||||
diffuse_bind_group_layout: texture_bind_group_layout,
|
diffuse_bind_group_layout: texture_bind_group_layout,
|
||||||
diffuse_bind_group,
|
camera: camera,
|
||||||
graphic_resource_manager,
|
camera_uniform: camera_uniform,
|
||||||
camera,
|
|
||||||
camera_buffer,
|
camera_buffer,
|
||||||
camera_uniform,
|
camera_bind_group,
|
||||||
camera_bind_group
|
render_pass,
|
||||||
|
graphic_resource_manager,
|
||||||
|
delta_time: 0.0,
|
||||||
|
last_frame_time: Instant::now(),
|
||||||
|
clear_color,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,186 +335,12 @@ impl<'a> Renderer2D<'a> {
|
||||||
|
|
||||||
/// A function that applies a shader to the entire surface of the `Renderer2D` if the shader is loaded.
|
/// 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) {
|
pub fn apply_shader(&mut self, shader: &str) {
|
||||||
let shader_module = self.graphic_resource_manager.get_shader(
|
todo!()
|
||||||
((Self::get_project_root().unwrap().as_os_str().to_str().unwrap().to_string() + "\\resources\\shaders\\").as_str().to_string() + shader).as_str()).unwrap();
|
|
||||||
let camera_bind_group_layout = self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
||||||
entries: &[wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 0,
|
|
||||||
visibility: wgpu::ShaderStages::VERTEX,
|
|
||||||
ty: wgpu::BindingType::Buffer {
|
|
||||||
ty: wgpu::BufferBindingType::Uniform,
|
|
||||||
has_dynamic_offset: false,
|
|
||||||
min_binding_size: None,
|
|
||||||
},
|
|
||||||
count: None,
|
|
||||||
}],
|
|
||||||
label: Some("camera_bind_group_layout"),
|
|
||||||
});
|
|
||||||
|
|
||||||
let render_pipeline_layout =
|
|
||||||
self.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
|
||||||
label: Some("Render Pipeline Layout"),
|
|
||||||
bind_group_layouts: &[
|
|
||||||
&self.diffuse_bind_group_layout,
|
|
||||||
&camera_bind_group_layout,
|
|
||||||
],
|
|
||||||
push_constant_ranges: &[],
|
|
||||||
});
|
|
||||||
|
|
||||||
self.pipelines[0] = self.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
|
||||||
label: Some("Render Pipeline"),
|
|
||||||
layout: Some(&render_pipeline_layout),
|
|
||||||
vertex: wgpu::VertexState {
|
|
||||||
module: &shader_module,
|
|
||||||
entry_point: "vs_main",
|
|
||||||
buffers: &[Vertex::desc()],
|
|
||||||
compilation_options: Default::default(),
|
|
||||||
},
|
|
||||||
fragment: Some(wgpu::FragmentState {
|
|
||||||
module: &shader_module,
|
|
||||||
entry_point: "fs_main",
|
|
||||||
targets: &[Some(wgpu::ColorTargetState {
|
|
||||||
format: self.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,
|
|
||||||
});
|
|
||||||
|
|
||||||
info!("Applied shader ({})!", shader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A function to revert back to the base shader of the `Renderer2D`
|
/// A function to revert back to the base shader of the `Renderer2D`
|
||||||
pub fn apply_base_shader(&mut self) {
|
pub fn apply_base_shader(&mut self) {
|
||||||
let shader = self.device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
todo!()
|
||||||
label: Some("Shader"),
|
|
||||||
source: wgpu::ShaderSource::Wgsl(include_str!("base2d.wgsl").into()),
|
|
||||||
});
|
|
||||||
|
|
||||||
let texture_bind_group_layout = self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 0,
|
|
||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
|
||||||
ty: wgpu::BindingType::Texture {
|
|
||||||
multisampled: false,
|
|
||||||
view_dimension: wgpu::TextureViewDimension::D2,
|
|
||||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
|
||||||
},
|
|
||||||
count: None,
|
|
||||||
},
|
|
||||||
wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 1,
|
|
||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
|
||||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
|
||||||
count: None,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
label: Some("texture_bind_group_layout"),
|
|
||||||
});
|
|
||||||
|
|
||||||
let camera_bind_group_layout = self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
||||||
entries: &[wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 0,
|
|
||||||
visibility: wgpu::ShaderStages::VERTEX,
|
|
||||||
ty: wgpu::BindingType::Buffer {
|
|
||||||
ty: wgpu::BufferBindingType::Uniform,
|
|
||||||
has_dynamic_offset: false,
|
|
||||||
min_binding_size: None,
|
|
||||||
},
|
|
||||||
count: None,
|
|
||||||
}],
|
|
||||||
label: Some("camera_bind_group_layout"),
|
|
||||||
});
|
|
||||||
|
|
||||||
let render_pipeline_layout =
|
|
||||||
self.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
|
||||||
label: Some("Render Pipeline Layout"),
|
|
||||||
bind_group_layouts: &[
|
|
||||||
&texture_bind_group_layout,
|
|
||||||
&camera_bind_group_layout,
|
|
||||||
],
|
|
||||||
push_constant_ranges: &[],
|
|
||||||
});
|
|
||||||
|
|
||||||
self.pipelines[0] = self.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
|
||||||
label: Some("Render Pipeline"),
|
|
||||||
layout: Some(&render_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: self.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,
|
|
||||||
});
|
|
||||||
info!("Applied base shader!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_font(&mut self, path: &str, size: f32) {
|
pub fn load_font(&mut self, path: &str, size: f32) {
|
||||||
|
|
@ -551,67 +374,11 @@ impl<'a> Renderer2D<'a> {
|
||||||
/// The old texture atlas will be replaced with the new one.
|
/// The old texture atlas will be replaced with the new one.
|
||||||
pub fn set_texture_atlas_by_paths(&mut self, paths: Vec<String>) {
|
pub fn set_texture_atlas_by_paths(&mut self, paths: Vec<String>) {
|
||||||
self.graphic_resource_manager.create_texture_atlas(paths);
|
self.graphic_resource_manager.create_texture_atlas(paths);
|
||||||
self.diffuse_texture = 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.diffuse_bind_group_layout, &Texture::from_image(&self.device, &self.queue, self.graphic_resource_manager.texture_atlas().atlas(), None, false).unwrap());
|
||||||
|
|
||||||
let texture_bind_group_layout =
|
|
||||||
self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 0,
|
|
||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
|
||||||
ty: wgpu::BindingType::Texture {
|
|
||||||
multisampled: false,
|
|
||||||
view_dimension: wgpu::TextureViewDimension::D2,
|
|
||||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
|
||||||
},
|
|
||||||
count: None,
|
|
||||||
},
|
|
||||||
wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 1,
|
|
||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
|
||||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
|
||||||
count: None,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
label: Some("texture_bind_group_layout"),
|
|
||||||
});
|
|
||||||
|
|
||||||
let diffuse_bind_group = self.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
||||||
layout: &texture_bind_group_layout,
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 0,
|
|
||||||
resource: wgpu::BindingResource::TextureView(&self.diffuse_texture.view),
|
|
||||||
},
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 1,
|
|
||||||
resource: wgpu::BindingResource::Sampler(&self.diffuse_texture.sampler),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
label: Some("diffuse_bind_group"),
|
|
||||||
});
|
|
||||||
|
|
||||||
self.diffuse_bind_group = diffuse_bind_group;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch_texture(&mut self, to: Texture) {
|
fn switch_texture(&mut self, to: Texture) {
|
||||||
self.diffuse_texture = to;
|
todo!()
|
||||||
let diffuse_bind_group = self.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
||||||
layout: &self.diffuse_bind_group_layout,
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 0,
|
|
||||||
resource: wgpu::BindingResource::TextureView(&self.diffuse_texture.view),
|
|
||||||
},
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 1,
|
|
||||||
resource: wgpu::BindingResource::Sampler(&self.diffuse_texture.sampler),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
label: Some("diffuse_bind_group"),
|
|
||||||
});
|
|
||||||
|
|
||||||
self.diffuse_bind_group = diffuse_bind_group;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_texture_atlas(&mut self) {
|
fn set_texture_atlas(&mut self) {
|
||||||
|
|
@ -651,85 +418,21 @@ impl<'a> Renderer2D<'a> {
|
||||||
self.set_texture_atlas_by_paths(paths);
|
self.set_texture_atlas_by_paths(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A function that clears the buffers and sets the vertex and index buffer of the `Renderer2D` with the given data.
|
/// A function that writes on the buffers and sets the geometry and index buffer of the `Renderer2D` with the given data.
|
||||||
fn set_buffers(&mut self, new_vertex_buffer: Vec<Vertex>, new_index_buffer: Vec<u16>) {
|
fn set_buffers(&mut self, new_geometry_buffer: Vec<Vertex>, new_index_buffer: Vec<u16>) {
|
||||||
let new_vertex_size = new_vertex_buffer.len() as u64 * size_of::<Vertex>() as u64;
|
self.render_pass[0].set_vertex_buffer(&self.device, &self.queue, new_geometry_buffer);
|
||||||
let new_index_size = new_index_buffer.len() as u64 * size_of::<u16>() as u64;
|
self.render_pass[0].set_index_buffer(&self.device, &self.queue, new_index_buffer);
|
||||||
|
|
||||||
match new_vertex_buffer == self.vertex_data {
|
|
||||||
true => {},
|
|
||||||
false => {
|
|
||||||
match new_vertex_size > self.vertex_buffer.size() {
|
|
||||||
false => self.queue.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&new_vertex_buffer)),
|
|
||||||
true => {
|
|
||||||
self.vertex_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Updated Vertex Buffer"),
|
|
||||||
contents: bytemuck::cast_slice(&new_vertex_buffer),
|
|
||||||
usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.vertex_data = new_vertex_buffer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match new_index_buffer == self.index_data {
|
/// A function that adds data to the already existing geometry and index buffers of the `Renderer2D`.
|
||||||
true => {},
|
fn push_to_buffers(&mut self, new_geometry_data: &mut Vec<Vertex>, new_index_buffer: &mut Vec<u16>) {
|
||||||
false => {
|
self.render_pass[0].push_to_vertex_buffer(&self.device, new_geometry_data);
|
||||||
match new_index_size > self.index_buffer.size() {
|
self.render_pass[0].push_to_index_buffer(&self.device, new_index_buffer);
|
||||||
false => self.queue.write_buffer(&self.index_buffer, 0, bytemuck::cast_slice(&new_index_buffer)),
|
|
||||||
true => {
|
|
||||||
self.index_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Updated Index Buffer"),
|
|
||||||
contents: bytemuck::cast_slice(&new_index_buffer),
|
|
||||||
usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.num_indices = new_index_buffer.len() as u32;
|
|
||||||
self.index_data = new_index_buffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A function that adds data to the already existing vertex and index buffers of the `Renderer2D`.
|
/// A function that clears the geometry and index buffers of the `Renderer2D`.
|
||||||
fn push_to_buffers(&mut self, new_vertex_buffer: &mut Vec<Vertex>, new_index_buffer: &mut Vec<u16>) {
|
|
||||||
self.vertex_data.append(new_vertex_buffer);
|
|
||||||
self.index_data.append(new_index_buffer);
|
|
||||||
|
|
||||||
self.vertex_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Updated Vertex Buffer"),
|
|
||||||
contents: bytemuck::cast_slice(&self.vertex_data),
|
|
||||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.index_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Updated Index Buffer"),
|
|
||||||
contents: bytemuck::cast_slice(&self.index_data),
|
|
||||||
usage: wgpu::BufferUsages::INDEX | BufferUsages::COPY_DST,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.num_indices = self.index_data.len() as u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A function that clears the vertex and index buffers of the `Renderer2D`.
|
|
||||||
fn clear_buffers(&mut self) {
|
fn clear_buffers(&mut self) {
|
||||||
self.vertex_data = vec![];
|
todo!()
|
||||||
self.index_data = vec![];
|
|
||||||
|
|
||||||
self.vertex_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Updated Vertex Buffer"),
|
|
||||||
contents: bytemuck::cast_slice(&self.vertex_data),
|
|
||||||
usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.index_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some("Updated Index Buffer"),
|
|
||||||
contents: bytemuck::cast_slice(&self.index_data),
|
|
||||||
usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.num_indices = self.index_data.len() as u32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A function to just draw a textured quad at a given position.
|
/// A function to just draw a textured quad at a given position.
|
||||||
|
|
@ -747,7 +450,7 @@ impl<'a> Renderer2D<'a> {
|
||||||
Vertex :: new ( [ bound_x + position.x(), bound_y + position.y(), 0.0 + position.z()], [region.u1(), region.v0()], [0.0, 0.0, 0.0, 0.0] )
|
Vertex :: new ( [ bound_x + position.x(), bound_y + position.y(), 0.0 + position.z()], [region.u1(), region.v0()], [0.0, 0.0, 0.0, 0.0] )
|
||||||
];
|
];
|
||||||
|
|
||||||
let buffer_size = self.vertex_data.len() as u16;
|
let buffer_size = self.render_pass[0].vertex_data().len() as u16;
|
||||||
|
|
||||||
let indices: &mut Vec<u16> = &mut vec![
|
let indices: &mut Vec<u16> = &mut vec![
|
||||||
0 + buffer_size, 1 + buffer_size, 3 + buffer_size,
|
0 + buffer_size, 1 + buffer_size, 3 + buffer_size,
|
||||||
|
|
@ -796,7 +499,7 @@ impl<'a> Renderer2D<'a> {
|
||||||
Vertex::new([ glyph_right, glyph_top, 0.0 ], [region.u1(), region.v0()], vert_color),
|
Vertex::new([ glyph_right, glyph_top, 0.0 ], [region.u1(), region.v0()], vert_color),
|
||||||
];
|
];
|
||||||
|
|
||||||
let buffer_size = self.vertex_data.len() as u16;
|
let buffer_size = self.render_pass[1].vertex_data().len() as u16;
|
||||||
let indices: &mut Vec<u16> = &mut vec![
|
let indices: &mut Vec<u16> = &mut vec![
|
||||||
buffer_size, buffer_size + 1, buffer_size + 3,
|
buffer_size, buffer_size + 1, buffer_size + 3,
|
||||||
buffer_size + 1, buffer_size + 2, buffer_size + 3,
|
buffer_size + 1, buffer_size + 2, buffer_size + 3,
|
||||||
|
|
@ -810,7 +513,6 @@ impl<'a> Renderer2D<'a> {
|
||||||
y_offset += line_height;
|
y_offset += line_height;
|
||||||
x_offset = 0.0;
|
x_offset = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_priority_camera(&self, cameras: Vec<Camera2D>) -> usize {
|
fn find_priority_camera(&self, cameras: Vec<Camera2D>) -> usize {
|
||||||
|
|
@ -914,10 +616,10 @@ impl<'a> Renderer2D<'a> {
|
||||||
let buffer_size = vertex_buffer.len() as u16;
|
let buffer_size = vertex_buffer.len() as u16;
|
||||||
|
|
||||||
vertex_buffer.append(&mut vec![
|
vertex_buffer.append(&mut vec![
|
||||||
Vertex :: new ( [-bound_x + position.x(), bound_y + position.y(), 0.0], [region.u0(), region.v0()], [0.0, 0.0, 0.0, 0.0] ),
|
Vertex :: new ( [-bound_x + position.x(), bound_y + position.y(), 0.0], [region.u0(), region.v0()], [1.0, 1.0, 1.0, 1.0] ),
|
||||||
Vertex :: new ( [-bound_x + position.x(), -bound_y + position.y(), 0.0], [region.u0(), region.v1()], [0.0, 0.0, 0.0, 0.0] ),
|
Vertex :: new ( [-bound_x + position.x(), -bound_y + position.y(), 0.0], [region.u0(), region.v1()], [1.0, 1.0, 1.0, 1.0] ),
|
||||||
Vertex :: new ( [ bound_x + position.x(), -bound_y + position.y(), 0.0], [region.u1(), region.v1()], [0.0, 0.0, 0.0, 0.0] ) ,
|
Vertex :: new ( [ bound_x + position.x(), -bound_y + position.y(), 0.0], [region.u1(), region.v1()], [1.0, 1.0, 1.0, 1.0] ) ,
|
||||||
Vertex :: new ( [ bound_x + position.x(), bound_y + position.y(), 0.0], [region.u1(), region.v0()], [0.0, 0.0, 0.0, 0.0] )
|
Vertex :: new ( [ bound_x + position.x(), bound_y + position.y(), 0.0], [region.u1(), region.v0()], [1.0, 1.0, 1.0, 1.0] )
|
||||||
]);
|
]);
|
||||||
|
|
||||||
index_buffer.append(&mut vec![
|
index_buffer.append(&mut vec![
|
||||||
|
|
@ -981,7 +683,7 @@ impl<'a> Renderer2D<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut entity_data = {
|
let entity_data = {
|
||||||
let mut data: Vec<(usize, Position2D)> = vec![];
|
let mut data: Vec<(usize, Position2D)> = vec![];
|
||||||
for entity in visible_entities {
|
for entity in visible_entities {
|
||||||
data.push((entity, *world.get_component::<Transform2D>(entity).unwrap().position()));
|
data.push((entity, *world.get_component::<Transform2D>(entity).unwrap().position()));
|
||||||
|
|
@ -1046,9 +748,9 @@ impl<'a> Renderer2D<'a> {
|
||||||
label: Some("Render Encoder"),
|
label: Some("Render Encoder"),
|
||||||
});
|
});
|
||||||
|
|
||||||
for (i, pipeline) in self.pipelines.iter().enumerate() {
|
for pass in self.render_pass.iter() {
|
||||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
label: Some(format!("Render Pass {}", i).as_str()),
|
label: Some(pass.pass_name()),
|
||||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
view: &view,
|
view: &view,
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
|
|
@ -1062,12 +764,12 @@ impl<'a> Renderer2D<'a> {
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
render_pass.set_pipeline(pipeline);
|
render_pass.set_pipeline(pass.pipeline());
|
||||||
render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]);
|
render_pass.set_bind_group(0, pass.texture_bind_group(), &[]);
|
||||||
render_pass.set_bind_group(1, &self.camera_bind_group, &[]);
|
render_pass.set_bind_group(1, &self.camera_bind_group, &[]);
|
||||||
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
render_pass.set_vertex_buffer(0, pass.vertex_buffer().slice(..));
|
||||||
render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
|
render_pass.set_index_buffer(pass.index_buffer().slice(..), wgpu::IndexFormat::Uint16);
|
||||||
render_pass.draw_indexed(0..self.num_indices, 0, 0..1);
|
render_pass.draw_indexed(0..pass.num_indices(), 0, 0..1);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.queue.submit(iter::once(encoder.finish()));
|
self.queue.submit(iter::once(encoder.finish()));
|
||||||
|
|
@ -1078,7 +780,6 @@ impl<'a> Renderer2D<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Renderer for Renderer2D<'a> {
|
impl<'a> Renderer for Renderer2D<'a> {
|
||||||
|
|
||||||
async fn new(window: Arc<Window>, clear_color: Option<impl Color>) -> Renderer2D<'a> {
|
async fn new(window: Arc<Window>, clear_color: Option<impl Color>) -> Renderer2D<'a> {
|
||||||
Self::new(window, clear_color).await
|
Self::new(window, clear_color).await
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ pub struct TextureRegion {
|
||||||
v0: f32,
|
v0: f32,
|
||||||
u1: f32,
|
u1: f32,
|
||||||
v1: f32,
|
v1: f32,
|
||||||
dimensions: (u32, u32),
|
|
||||||
advance: f32,
|
advance: f32,
|
||||||
offset_x: f32,
|
offset_x: f32,
|
||||||
offset_y: f32,
|
offset_y: f32,
|
||||||
|
dimensions: (u32, u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextureRegion {
|
impl TextureRegion {
|
||||||
|
|
@ -26,10 +26,10 @@ impl TextureRegion {
|
||||||
v0,
|
v0,
|
||||||
u1,
|
u1,
|
||||||
v1,
|
v1,
|
||||||
dimensions,
|
|
||||||
advance,
|
advance,
|
||||||
offset_x,
|
offset_x,
|
||||||
offset_y,
|
offset_y,
|
||||||
|
dimensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue