Add GeometryBuffers struct containing vertex and index buffers

This commit is contained in:
Sijmen 2021-06-02 03:20:33 +02:00
parent 8bc41825d2
commit 14a2e91b26
Signed by: vijfhoek
GPG key ID: 82D05C89B28B0DAE
4 changed files with 104 additions and 129 deletions

View file

@ -1,4 +1,9 @@
use crate::vertex::Vertex;
use wgpu::{
util::{BufferInitDescriptor, DeviceExt},
RenderPass,
};
use crate::{render_context::RenderContext, vertex::Vertex};
/// Represents a set of triangles by its vertices and indices.
#[derive(Default)]
@ -23,3 +28,48 @@ impl<T: Vertex> Geometry<T> {
self.indices.len()
}
}
pub struct GeometryBuffers {
pub vertices: wgpu::Buffer,
pub indices: wgpu::Buffer,
pub index_count: usize,
}
impl GeometryBuffers {
pub fn from_geometry<T: Vertex + bytemuck::Pod>(
render_context: &RenderContext,
geometry: &Geometry<T>,
usage: wgpu::BufferUsage,
) -> Self {
let vertices = render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: None,
contents: bytemuck::cast_slice(&geometry.vertices),
usage: wgpu::BufferUsage::VERTEX | usage,
});
let indices = render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: None,
contents: bytemuck::cast_slice(&geometry.indices),
usage: wgpu::BufferUsage::INDEX | usage,
});
Self {
vertices,
indices,
index_count: geometry.index_count(),
}
}
pub fn set_buffers<'a>(&'a self, render_pass: &mut RenderPass<'a>) {
render_pass.set_vertex_buffer(0, self.vertices.slice(..));
render_pass.set_index_buffer(self.indices.slice(..), wgpu::IndexFormat::Uint16);
}
pub fn draw_indexed(&self, render_pass: &mut RenderPass) {
render_pass.draw_indexed(0..self.index_count as u32, 0, 0..1);
}
}

View file

@ -1,12 +1,10 @@
use std::time::{Duration, Instant};
use cgmath::Vector3;
use wgpu::{
util::{BufferInitDescriptor, DeviceExt},
CommandEncoder, SwapChainTexture,
};
use wgpu::{BufferUsage, CommandEncoder, SwapChainTexture};
use crate::{
geometry::{Geometry, GeometryBuffers},
render_context::RenderContext,
text_renderer::{self, TextRenderer},
texture::Texture,
@ -19,21 +17,16 @@ const UI_SCALE_Y: f32 = 0.008;
pub struct HudState {
texture_bind_group: wgpu::BindGroup,
render_pipeline: wgpu::RenderPipeline,
hud_vertex_buffer: wgpu::Buffer,
hud_index_buffer: wgpu::Buffer,
hud_geometry_buffers: GeometryBuffers,
text_renderer: TextRenderer,
fps_vertex_buffer: wgpu::Buffer,
fps_index_buffer: wgpu::Buffer,
fps_index_count: usize,
fps_geometry_buffers: GeometryBuffers,
fps_instant: Instant,
fps_frames: u32,
fps_elapsed: Duration,
coordinates_vertex_buffer: wgpu::Buffer,
coordinates_index_buffer: wgpu::Buffer,
coordinates_index_count: usize,
coordinates_geometry_buffers: GeometryBuffers,
coordinates_last: Vector3<f32>,
pub hotbar_cursor_position: i32,
}
@ -46,45 +39,33 @@ impl HudState {
Self::create_render_pipeline(render_context, &[&texture_bind_group_layout]);
// HUD buffers
let hud_vertex_buffer = render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: Some("HUD crosshair vertex buffer"),
contents: bytemuck::cast_slice(HUD_VERTICES),
usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
});
let hud_index_buffer = render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: Some("HUD crosshair index buffer"),
contents: bytemuck::cast_slice(HUD_INDICES),
usage: wgpu::BufferUsage::INDEX,
});
let hud_geometry = Geometry {
vertices: HUD_VERTICES.to_vec(),
indices: HUD_INDICES.to_vec(),
};
let hud_geometry_buffers =
GeometryBuffers::from_geometry(render_context, &hud_geometry, BufferUsage::COPY_DST);
// Text buffers
let text_renderer = TextRenderer::new(render_context).unwrap();
let (fps_vertex_buffer, fps_index_buffer, fps_index_count) =
let fps_geometry_buffers =
text_renderer.string_to_buffers(&render_context, -0.98, 0.97, "");
let (coordinates_vertex_buffer, coordinates_index_buffer, coordinates_index_count) =
let coordinates_geometry_buffers =
text_renderer.string_to_buffers(&render_context, -0.98, 0.97 - text_renderer::DY, "");
Self {
texture_bind_group,
render_pipeline,
hud_vertex_buffer,
hud_index_buffer,
text_renderer,
fps_vertex_buffer,
fps_index_buffer,
fps_index_count,
hud_geometry_buffers,
fps_geometry_buffers,
fps_instant: Instant::now(),
fps_frames: 0,
fps_elapsed: Duration::from_secs(0),
coordinates_vertex_buffer,
coordinates_index_buffer,
coordinates_index_count,
coordinates_geometry_buffers,
coordinates_last: Vector3::new(0.0, 0.0, 0.0),
hotbar_cursor_position: 0,
@ -102,12 +83,9 @@ impl HudState {
let fps = 1.0 / frametime.as_secs_f32();
let string = format!("{:<5.0} fps", fps);
let (vertices, indices, index_count) =
self.fps_geometry_buffers =
self.text_renderer
.string_to_buffers(render_context, -0.98, 0.97, &string);
self.fps_vertex_buffer = vertices;
self.fps_index_buffer = indices;
self.fps_index_count = index_count;
self.fps_elapsed = Duration::from_secs(0);
self.fps_frames = 0;
@ -115,15 +93,12 @@ impl HudState {
if position != &self.coordinates_last {
let string = format!("({:.1},{:.1},{:.1})", position.x, position.y, position.z,);
let (vertices, indices, index_count) = self.text_renderer.string_to_buffers(
self.coordinates_geometry_buffers = self.text_renderer.string_to_buffers(
render_context,
-0.98,
0.97 - text_renderer::DY * 1.3,
&string,
);
self.coordinates_vertex_buffer = vertices;
self.coordinates_index_buffer = indices;
self.coordinates_index_count = index_count;
}
}
@ -147,26 +122,23 @@ impl HudState {
render_pass.set_pipeline(&self.render_pipeline);
// Render the crosshair and hotbar
render_pass.set_vertex_buffer(0, self.hud_vertex_buffer.slice(..));
render_pass.set_index_buffer(self.hud_index_buffer.slice(..), wgpu::IndexFormat::Uint16);
// Render the crosshair and
self.hud_geometry_buffers.set_buffers(&mut render_pass);
render_pass.set_bind_group(0, &self.texture_bind_group, &[]);
render_pass.draw_indexed(0..HUD_INDICES.len() as u32, 0, 0..1);
self.hud_geometry_buffers.draw_indexed(&mut render_pass);
render_pass.draw_indexed(0..self.hud_geometry_buffers.index_count as u32, 0, 0..1);
// Render the FPS text
render_pass.set_vertex_buffer(0, self.fps_vertex_buffer.slice(..));
render_pass.set_index_buffer(self.fps_index_buffer.slice(..), wgpu::IndexFormat::Uint16);
self.fps_geometry_buffers.set_buffers(&mut render_pass);
render_pass.set_bind_group(0, &self.text_renderer.bind_group, &[]);
render_pass.draw_indexed(0..self.fps_index_count as u32, 0, 0..1);
self.fps_geometry_buffers.draw_indexed(&mut render_pass);
// Render the coordinates text
render_pass.set_vertex_buffer(0, self.coordinates_vertex_buffer.slice(..));
render_pass.set_index_buffer(
self.coordinates_index_buffer.slice(..),
wgpu::IndexFormat::Uint16,
);
self.coordinates_geometry_buffers
.set_buffers(&mut render_pass);
render_pass.set_bind_group(0, &self.text_renderer.bind_group, &[]);
render_pass.draw_indexed(0..self.coordinates_index_count as u32, 0, 0..1);
self.coordinates_geometry_buffers
.draw_indexed(&mut render_pass);
Ok(HUD_INDICES.len() / 3)
}
@ -183,7 +155,7 @@ impl HudState {
];
render_context.queue.write_buffer(
&self.hud_vertex_buffer,
&self.hud_geometry_buffers.vertices,
HudVertex::descriptor().array_stride * 8,
bytemuck::cast_slice(&vertices),
);
@ -323,7 +295,7 @@ impl HudState {
}
#[rustfmt::skip]
pub const HUD_VERTICES: &[HudVertex] = &[
pub const HUD_VERTICES: [HudVertex; 12] = [
// Crosshair
HudVertex { position: [UI_SCALE_X * -8.0, UI_SCALE_Y * 8.0], texture_coordinates: [240.0 / 256.0, 0.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * 8.0, UI_SCALE_Y * 8.0], texture_coordinates: [256.0 / 256.0, 0.0 / 256.0] },
@ -344,7 +316,7 @@ pub const HUD_VERTICES: &[HudVertex] = &[
];
#[rustfmt::skip]
pub const HUD_INDICES: &[u16] = &[
pub const HUD_INDICES: [u16; 18] = [
// Crosshair
1, 0, 3,
1, 3, 2,

View file

@ -4,7 +4,7 @@ use ahash::AHashMap;
use cgmath::{EuclideanSpace, InnerSpace, Point3, Rad, Vector2, Vector3};
use wgpu::{
util::{BufferInitDescriptor, DeviceExt},
CommandEncoder, SwapChainTexture,
BufferUsage, CommandEncoder, SwapChainTexture,
};
use winit::{
dpi::PhysicalSize,
@ -14,6 +14,7 @@ use winit::{
use crate::{
camera::{Camera, Projection},
chunk::{Block, BlockType, CHUNK_SIZE},
geometry::GeometryBuffers,
render_context::RenderContext,
texture::{Texture, TextureManager},
time::Time,
@ -34,7 +35,7 @@ pub struct WorldState {
pub time_bind_group: wgpu::BindGroup,
pub world: World,
pub chunk_buffers: AHashMap<Vector3<usize>, (wgpu::Buffer, wgpu::Buffer, usize)>,
pub chunk_buffers: AHashMap<Vector3<usize>, GeometryBuffers>,
time: Time,
time_buffer: wgpu::Buffer,
wireframe: bool,
@ -221,26 +222,12 @@ impl WorldState {
let world_geometry = self.world.to_geometry(self.highlighted);
self.chunk_buffers.clear();
for (chunk_position, chunk_geometry) in world_geometry {
self.chunk_buffers.insert(
chunk_position,
(
render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: None,
contents: &bytemuck::cast_slice(&chunk_geometry.vertices),
usage: wgpu::BufferUsage::VERTEX,
}),
render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: None,
contents: &bytemuck::cast_slice(&chunk_geometry.indices),
usage: wgpu::BufferUsage::INDEX,
}),
chunk_geometry.index_count(),
),
let buffers = GeometryBuffers::from_geometry(
render_context,
&chunk_geometry,
BufferUsage::empty(),
);
self.chunk_buffers.insert(chunk_position, buffers);
}
let elapsed = instant.elapsed();
@ -259,26 +246,9 @@ impl WorldState {
World::highlighted_for_chunk(self.highlighted, chunk_position).as_ref(),
);
self.chunk_buffers.insert(
chunk_position,
(
render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: None,
contents: &bytemuck::cast_slice(&geometry.vertices),
usage: wgpu::BufferUsage::VERTEX,
}),
render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: None,
contents: &bytemuck::cast_slice(&geometry.indices),
usage: wgpu::BufferUsage::INDEX,
}),
geometry.index_count(),
),
);
let buffers =
GeometryBuffers::from_geometry(render_context, &geometry, BufferUsage::empty());
self.chunk_buffers.insert(chunk_position, buffers);
}
pub fn toggle_wireframe(&mut self, render_context: &RenderContext) {
@ -401,17 +371,16 @@ impl WorldState {
let camera_pos = self.camera.position.to_vec();
let camera_pos = Vector2::new(camera_pos.x, camera_pos.z);
for (position, (chunk_vertices, chunk_indices, index_count)) in &self.chunk_buffers {
for (position, buffers) in &self.chunk_buffers {
let pos = (position * CHUNK_SIZE).cast().unwrap();
let pos = Vector2::new(pos.x, pos.z);
if (pos - camera_pos).magnitude() > 300.0 {
continue;
}
render_pass.set_vertex_buffer(0, chunk_vertices.slice(..));
render_pass.set_index_buffer(chunk_indices.slice(..), wgpu::IndexFormat::Uint16);
render_pass.draw_indexed(0..*index_count as u32, 0, 0..1);
triangle_count += index_count / 3;
buffers.set_buffers(&mut render_pass);
buffers.draw_indexed(&mut render_pass);
triangle_count += buffers.index_count / 3;
}
triangle_count

View file

@ -1,9 +1,10 @@
use std::convert::TryInto;
use wgpu::util::{BufferInitDescriptor, DeviceExt};
use crate::{
geometry::Geometry, render_context::RenderContext, texture::Texture, vertex::HudVertex,
geometry::{Geometry, GeometryBuffers},
render_context::RenderContext,
texture::Texture,
vertex::HudVertex,
};
pub const DX: f32 = 20.0 / 640.0;
@ -152,25 +153,8 @@ impl TextRenderer {
x: f32,
y: f32,
string: &str,
) -> (wgpu::Buffer, wgpu::Buffer, usize) {
) -> GeometryBuffers {
let geometry = self.string_geometry(x, y, string);
let vertex_buffer = render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: Some("font renderer"),
contents: bytemuck::cast_slice(&geometry.vertices),
usage: wgpu::BufferUsage::VERTEX,
});
let index_buffer = render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: Some("font renderer"),
contents: bytemuck::cast_slice(&geometry.indices),
usage: wgpu::BufferUsage::INDEX,
});
(vertex_buffer, index_buffer, geometry.index_count())
GeometryBuffers::from_geometry(render_context, &geometry, wgpu::BufferUsage::empty())
}
}