[oden] lol sprite API

This commit is contained in:
John Doty 2023-06-23 06:25:45 -07:00
parent c7903382a0
commit aa90cea4a3
3 changed files with 168 additions and 75 deletions

View file

@ -1,5 +1,4 @@
use bytemuck;
use wgpu::util::DeviceExt;
use winit::{
event::*,
event_loop::{ControlFlow, EventLoop},
@ -8,13 +7,13 @@ use winit::{
};
mod script;
use script::graphics::{ClearCommand, GraphicsCommand, PrintCommand};
use script::graphics::GraphicsCommand;
mod texture;
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
struct Vertex {
position: [f32; 3],
position: [f32; 3], // TODO: Why do I pass in a Z here?
tex_coords: [f32; 2],
}
@ -74,8 +73,7 @@ struct State {
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
num_indices: u32, // Indices in index_buffer
max_vertices: usize,
diffuse_bind_group: wgpu::BindGroup,
@ -248,17 +246,15 @@ impl State {
multiview: None,
});
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
let max_vertices: usize = 4096;
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsages::VERTEX,
size: (max_vertices * std::mem::size_of::<Vertex>())
.try_into()
.unwrap(),
mapped_at_creation: false,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
Self {
window,
@ -269,8 +265,7 @@ impl State {
size,
render_pipeline,
vertex_buffer,
index_buffer,
num_indices,
max_vertices,
diffuse_bind_group,
mouse_x: 0.0,
@ -302,11 +297,6 @@ impl State {
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
// Group the commands into passes.
struct Pass {
@ -316,8 +306,8 @@ impl State {
let mut passes = Vec::new();
for command in commands {
match command {
GraphicsCommand::Clear(ClearCommand { color }) => passes.push(Pass {
color: Some(color),
GraphicsCommand::Clear(cc) => passes.push(Pass {
color: Some(cc.color),
commands: Vec::new(),
}),
GraphicsCommand::EndFrame => (),
@ -331,39 +321,91 @@ impl State {
}
}
let mut vertices = Vec::new();
for pass in passes {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: if let Some([r, g, b, a]) = pass.color {
wgpu::LoadOp::Clear(wgpu::Color {
r, //0.1,
g, //0.2,
b,
a,
})
} else {
wgpu::LoadOp::Load
// TODO: It would be great if we could use multiple passes in a
// single encoder but right now because of the dyanmic
// nature of vertices we can't, I think? Because
// queue.write_buffer doesn't actually happen until we call
// submit...
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
{
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: if let Some([r, g, b, a]) = pass.color {
wgpu::LoadOp::Clear(wgpu::Color {
r, //0.1,
g, //0.2,
b,
a,
})
} else {
wgpu::LoadOp::Load
},
store: true,
},
store: true,
},
})],
depth_stencil_attachment: None,
});
})],
depth_stencil_attachment: None,
});
for command in pass.commands {
match command {
GraphicsCommand::Print(PrintCommand { text }) => {
println!("{}", text);
vertices.clear();
for command in pass.commands {
match command {
GraphicsCommand::Print(pc) => {
println!("{}", pc.text);
}
GraphicsCommand::Sprite(sc) => {
vertices.push(Vertex {
position: [sc.x, sc.y, 0.0],
tex_coords: [sc.u, sc.v],
});
vertices.push(Vertex {
position: [sc.x + sc.w, sc.y, 0.0],
tex_coords: [sc.u + sc.sw, sc.v],
});
vertices.push(Vertex {
position: [sc.x, sc.y + sc.h, 0.0],
tex_coords: [sc.u, sc.v],
});
vertices.push(Vertex {
position: [sc.x, sc.y + sc.h, 0.0],
tex_coords: [sc.u, sc.v],
});
vertices.push(Vertex {
position: [sc.x + sc.w, sc.y, 0.0],
tex_coords: [sc.u, sc.v],
});
vertices.push(Vertex {
position: [sc.x + sc.w, sc.y + sc.h, 0.0],
tex_coords: [sc.u, sc.v],
});
}
GraphicsCommand::Clear(_) => (), // Already handled
GraphicsCommand::EndFrame => (), // Should never appear
}
GraphicsCommand::Clear(_) => (), // Already handled
GraphicsCommand::EndFrame => (), // Should never appear
}
assert!(vertices.len() < self.max_vertices); // !
self.queue
.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&vertices));
render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]);
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
render_pass.draw(0..(vertices.len() as u32), 0..1);
}
// Submit will accept anything that implements IntoIter
self.queue.submit(std::iter::once(encoder.finish()));
}
// {
@ -397,8 +439,6 @@ impl State {
// render_pass.draw_indexed(0..self.num_indices, 0, 0..1);
// }
// Submit will accept anything that implements IntoIter
self.queue.submit(std::iter::once(encoder.finish()));
output.present();
Ok(())