replace buffers with wgpu, create pipelines/shaders

This commit is contained in:
griffi-gh 2023-07-16 14:22:09 +02:00
parent ae58706f10
commit 3b752dfbf8
11 changed files with 234 additions and 172 deletions

View file

@ -59,11 +59,10 @@ use rendering::{
Renderer, Renderer,
RenderTarget, RenderTarget,
BackgroundColor, BackgroundColor,
clear_background,
primitives::init_primitives,
world::{draw_world, draw_current_chunk_border}, world::{draw_world, draw_current_chunk_border},
selection_box::render_selection_box, selection_box::render_selection_box,
entities::render_entities, entities::render_entities,
renderer_finish_init,
}; };
use block_placement::update_block_placement; use block_placement::update_block_placement;
use delta_time::{DeltaTime, init_delta_time}; use delta_time::{DeltaTime, init_delta_time};
@ -85,10 +84,10 @@ fn pre_startup() -> Workload {
fn startup() -> Workload { fn startup() -> Workload {
( (
renderer_finish_init,
init_fixed_timestamp_storage, init_fixed_timestamp_storage,
initial_resize_event, initial_resize_event,
load_prefabs, load_prefabs,
init_primitives,
insert_lock_state, insert_lock_state,
init_state, init_state,
initialize_from_args, initialize_from_args,
@ -136,7 +135,6 @@ fn update() -> Workload {
fn render() -> Workload { fn render() -> Workload {
( (
clear_background,
( (
draw_world, draw_world,
draw_current_chunk_border, draw_current_chunk_border,

View file

@ -1,15 +1,17 @@
use shipyard::{Unique, NonSendSync, UniqueView, UniqueViewMut, View, IntoIter, AllStoragesView}; use shipyard::{Unique, View, Workload, SystemModificator, IntoWorkload};
use wgpu::SurfaceConfiguration;
use winit::{ use winit::{
event_loop::EventLoop, event_loop::EventLoop,
window::{Window, WindowBuilder, Fullscreen}, window::{Window, WindowBuilder, Fullscreen},
dpi::PhysicalSize, dpi::PhysicalSize,
}; };
use glam::{Vec3, UVec2}; use glam::Vec3;
use pollster::FutureExt as _; use pollster::FutureExt as _;
use crate::{events::WindowResizedEvent, settings::{GameSettings, FullscreenMode}}; use crate::{events::WindowResizedEvent, settings::{GameSettings, FullscreenMode}};
use self::{pipelines::init_pipelines, primitives::init_primitives, shaders::compile_shaders};
pub mod shaders; pub mod shaders;
pub mod pipelines;
pub mod primitives; pub mod primitives;
pub mod world; pub mod world;
pub mod selection_box; pub mod selection_box;
@ -166,11 +168,12 @@ impl Renderer {
} }
} }
pub fn clear_background( pub fn renderer_finish_init() -> Workload {
mut target: NonSendSync<UniqueViewMut<RenderTarget>>, (
color: UniqueView<BackgroundColor>, compile_shaders,
) { init_pipelines.after_all(compile_shaders),
init_primitives,
).into_workload()
} }
#[deprecated] #[deprecated]

View file

@ -1,59 +1,57 @@
use shipyard::{NonSendSync, UniqueViewMut, UniqueView, View, IntoIter, IntoWithId}; use shipyard::{NonSendSync, UniqueViewMut, UniqueView, View, IntoIter, IntoWithId};
use kubi_shared::{entity::Entity, transform::Transform}; use kubi_shared::{entity::Entity, transform::Transform};
use crate::{ use crate::{
assets::ColoredShaderPrefab,
camera::Camera, camera::Camera,
settings::GameSettings settings::GameSettings
}; };
use super::{ use super::shaders::Shaders;
RenderTarget,
primitives::cube::CenteredCubePrimitive
};
// TODO: entity models // TODO: entity models
pub fn render_entities() {}
#[cfg(fuck)]
pub fn render_entities( pub fn render_entities(
mut target: NonSendSync<UniqueViewMut<RenderTarget>>, mut target: NonSendSync<UniqueViewMut<RenderTarget>>,
buffers: NonSendSync<UniqueView<CenteredCubePrimitive>>, buffers: NonSendSync<UniqueView<CenteredCubePrimitive>>,
program: NonSendSync<UniqueView<ColoredShaderPrefab>>, shaders: NonSendSync<UniqueView<Shaders>>,
camera: View<Camera>, camera: View<Camera>,
settings: UniqueView<GameSettings>, settings: UniqueView<GameSettings>,
entities: View<Entity>, entities: View<Entity>,
transform: View<Transform>, transform: View<Transform>,
) { ) {
#[cfg(fuck)] { let (camera_id, camera) = camera.iter().with_id().next().expect("No cameras in the scene");
let (camera_id, camera) = camera.iter().with_id().next().expect("No cameras in the scene");
let draw_parameters = DrawParameters { let draw_parameters = DrawParameters {
depth: Depth { depth: Depth {
test: DepthTest::IfLess, test: DepthTest::IfLess,
write: true, write: true,
..Default::default()
},
multisampling: settings.msaa.is_some(),
polygon_mode: PolygonMode::Fill,
backface_culling: BackfaceCullingMode::CullClockwise,
..Default::default() ..Default::default()
}; },
let view = camera.view_matrix.to_cols_array_2d(); multisampling: settings.msaa.is_some(),
let perspective = camera.perspective_matrix.to_cols_array_2d(); polygon_mode: PolygonMode::Fill,
backface_culling: BackfaceCullingMode::CullClockwise,
..Default::default()
};
let view = camera.view_matrix.to_cols_array_2d();
let perspective = camera.perspective_matrix.to_cols_array_2d();
for (entity_id, (_, trans)) in (&entities, &transform).iter().with_id() { for (entity_id, (_, trans)) in (&entities, &transform).iter().with_id() {
//skip rendering camera holder (as the entity would block the view) //skip rendering camera holder (as the entity would block the view)
if entity_id == camera_id { continue } if entity_id == camera_id { continue }
//render entity //render entity
// target.0.draw( // target.0.draw(
// &buffers.0, // &buffers.0,
// &buffers.1, // &buffers.1,
// &program.0, // &program.0,
// &uniform! { // &uniform! {
// color: [1.0, 1.0, 1.0, 1.0_f32], // color: [1.0, 1.0, 1.0, 1.0_f32],
// model: trans.0.to_cols_array_2d(), // model: trans.0.to_cols_array_2d(),
// view: view, // view: view,
// perspective: perspective, // perspective: perspective,
// }, // },
// &draw_parameters // &draw_parameters
// ).unwrap(); // ).unwrap();
}
} }
} }

View file

@ -0,0 +1,51 @@
use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView};
use super::{shaders::Shaders, Renderer};
#[derive(Unique)]
pub struct Pipelines {
pub world: wgpu::RenderPipeline
}
pub fn init_pipelines(
storages: AllStoragesView
) {
let renderer = storages.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
let shaders = storages.borrow::<UniqueView<Shaders>>().unwrap();
storages.add_unique(Pipelines {
world: renderer.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("WorldRenderPipeline"),
layout: Some(&renderer.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("WorldRenderPipelineLayout"),
bind_group_layouts: &[],
push_constant_ranges: &[],
})),
vertex: wgpu::VertexState {
module: &shaders.world,
entry_point: "vs_main",
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shaders.world,
entry_point: "fs_main",
targets: &[Some(wgpu::ColorTargetState {
format: renderer.config.format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrites::ALL,
})],
}),
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,
},
//TODO enable depth buffer
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
multiview: None,
}),
})
}

View file

@ -1,16 +1,12 @@
use shipyard::{AllStoragesView, NonSendSync, UniqueView, Unique}; use shipyard::{AllStoragesView, NonSendSync, UniqueView, Unique};
use wgpu::util::DeviceExt;
use crate::rendering::Renderer; use crate::rendering::Renderer;
use super::PositionVertex; use super::PositionVertex;
#[derive(Unique)] #[derive(Unique)]
pub struct CubePrimitive { pub struct CubePrimitive {
pub vert: wgpu::Buffer, pub vert: wgpu::Buffer,
pub idx: wgpu::Buffer pub vert_centered: wgpu::Buffer,
}
#[derive(Unique)]
pub struct CenteredCubePrimitive {
pub vert: wgpu::Buffer,
pub idx: wgpu::Buffer pub idx: wgpu::Buffer
} }
@ -61,30 +57,31 @@ const CUBE_INDICES: &[u16] = &[
pub(super) fn init_cube_primitive( pub(super) fn init_cube_primitive(
storages: AllStoragesView, storages: AllStoragesView,
display: NonSendSync<UniqueView<Renderer>> renderer: NonSendSync<UniqueView<Renderer>>
) { ) {
{ storages.add_unique(
let vert = VertexBuffer::new( CubePrimitive {
&display.display, vert: renderer.device.create_buffer_init(
CUBE_VERTICES &wgpu::util::BufferInitDescriptor {
).unwrap(); label: Some("CubePrimitiveVertexBuffer"),
let index = IndexBuffer::new( contents: bytemuck::cast_slice(CUBE_VERTICES),
&display.display, usage: wgpu::BufferUsages::VERTEX,
PrimitiveType::TrianglesList, }
CUBE_INDICES ),
).unwrap(); vert_centered: renderer.device.create_buffer_init(
storages.add_unique_non_send_sync(CubePrimitive(vert, index)); &wgpu::util::BufferInitDescriptor {
} label: Some("CubePrimitiveCenteredVertexBuffer"),
{ contents: bytemuck::cast_slice(CUBE_VERTICES),
let vert = VertexBuffer::new( usage: wgpu::BufferUsages::VERTEX,
&display.display, }
CENTERED_CUBE_VERTICES ),
).unwrap(); idx: renderer.device.create_buffer_init(
let index = IndexBuffer::new( &wgpu::util::BufferInitDescriptor {
&display.display, label: Some("CubePrimitiveIndexBuffer"),
PrimitiveType::TrianglesList, contents: bytemuck::cast_slice(CUBE_VERTICES),
CUBE_INDICES usage: wgpu::BufferUsages::INDEX,
).unwrap(); }
storages.add_unique_non_send_sync(CenteredCubePrimitive(vert, index)); )
} }
);
} }

View file

@ -1,9 +1,13 @@
use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView}; use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView};
use wgpu::util::DeviceExt;
use crate::rendering::Renderer; use crate::rendering::Renderer;
use super::PositionVertex2d; use super::PositionVertex2d;
#[derive(Unique)] #[derive(Unique)]
pub struct RectPrimitive(pub VertexBuffer<PositionVertex2d>, pub IndexBuffer<u16>); pub struct RectPrimitive {
pub vert: wgpu::Buffer,
pub index: wgpu::Buffer,
}
const RECT_VERTEX: &[PositionVertex2d] = &[ const RECT_VERTEX: &[PositionVertex2d] = &[
PositionVertex2d { position: [0., 0.] }, PositionVertex2d { position: [0., 0.] },
@ -15,16 +19,21 @@ const RECT_INDEX: &[u16] = &[0, 1, 2, 1, 3, 2];
pub(super) fn init_rect_primitive( pub(super) fn init_rect_primitive(
storages: AllStoragesView, storages: AllStoragesView,
display: NonSendSync<UniqueView<Renderer>> renderer: NonSendSync<UniqueView<Renderer>>
) { ) {
let vert = VertexBuffer::new( let vert = renderer.device.create_buffer_init(
&display.display, &wgpu::util::BufferInitDescriptor {
RECT_VERTEX label: Some("RectPrimitiveVertexBuffer"),
).unwrap(); contents: bytemuck::cast_slice(RECT_VERTEX),
let index = IndexBuffer::new( usage: wgpu::BufferUsages::VERTEX,
&display.display, }
PrimitiveType::TrianglesList, );
RECT_INDEX let index = renderer.device.create_buffer_init(
).unwrap(); &wgpu::util::BufferInitDescriptor {
storages.add_unique_non_send_sync(RectPrimitive(vert, index)); label: Some("RectPrimitiveIndexBuffer"),
contents: bytemuck::cast_slice(RECT_INDEX),
usage: wgpu::BufferUsages::INDEX,
}
);
storages.add_unique(RectPrimitive { vert, index });
} }

View file

@ -1,16 +1,8 @@
use glam::{Mat4, Vec3, Quat}; use glam::{Mat4, Vec3, Quat};
use shipyard::{View, IntoIter, NonSendSync, UniqueViewMut, UniqueView}; use shipyard::{View, IntoIter, NonSendSync, UniqueViewMut, UniqueView};
use glium::{
Surface,
DrawParameters,
BackfaceCullingMode,
Blend, Depth, DepthTest,
uniform,
};
use crate::{ use crate::{
world::raycast::LookingAtBlock, world::raycast::LookingAtBlock,
camera::Camera, camera::Camera,
assets::ColoredShaderPrefab
}; };
use super::{ use super::{
RenderTarget, RenderTarget,
@ -19,12 +11,15 @@ use super::{
const SMOL: f32 = 0.0001; const SMOL: f32 = 0.0001;
pub fn render_selection_box() { }
#[cfg(fuck)]
pub fn render_selection_box( pub fn render_selection_box(
lookat: View<LookingAtBlock>, lookat: View<LookingAtBlock>,
camera: View<Camera>, camera: View<Camera>,
mut target: NonSendSync<UniqueViewMut<RenderTarget>>, mut target: NonSendSync<UniqueViewMut<RenderTarget>>,
program: NonSendSync<UniqueView<ColoredShaderPrefab>>, program: NonSendSync<UniqueView<ColoredShaderPrefab>>,
buffers: NonSendSync<UniqueView<CubePrimitive>>, buffers: UniqueView<CubePrimitive>,
) { ) {
let camera = camera.iter().next().unwrap(); let camera = camera.iter().next().unwrap();
let Some(lookat) = lookat.iter().next() else { return }; let Some(lookat) = lookat.iter().next() else { return };

View file

@ -8,12 +8,13 @@ pub struct Shaders {
pub colored: wgpu::ShaderModule pub colored: wgpu::ShaderModule
} }
macro_rules! upload_shaders { macro_rules! build_shaders {
{$container: ident [$renderer: expr, $dir: literal] { $($name: ident : $path: literal $(,)*),* } } => {{ {$container: ident [$renderer: expr, $dir: literal] { $($name: ident : $path: literal $(,)*),* } } => {{
//ensure types //ensure types
let _: &super::Renderer = $renderer; let _: &super::Renderer = $renderer;
let _: &str = $dir; let _: &str = $dir;
$( let _: &str = $path; )* $( let _: &str = $path; )*
//build wgsl shaders
$container { $container {
$($name: { $($name: {
let source = include_str!(concat!($dir, "/", $path)).into(); let source = include_str!(concat!($dir, "/", $path)).into();
@ -31,10 +32,10 @@ pub fn compile_shaders(
storages: AllStoragesView, storages: AllStoragesView,
) { ) {
let renderer = &storages.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap(); let renderer = &storages.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
let shaders = upload_shaders! { storages.add_unique(build_shaders! {
Shaders [renderer, "../../shaders"] { Shaders [renderer, "../../shaders"] {
world: "world.wgsl", world: "world.wgsl",
colored: "colored.wgsl" colored: "colored.wgsl"
} }
}; });
} }

View file

@ -4,11 +4,7 @@ use crate::{
camera::Camera, camera::Camera,
player::MainPlayer, player::MainPlayer,
transform::Transform, transform::Transform,
assets::{ assets::BlockTexturesPrefab,
ChunkShaderPrefab,
BlockTexturesPrefab,
ColoredShaderPrefab,
},
world::{ world::{
ChunkStorage, ChunkStorage,
ChunkMeshStorage, ChunkMeshStorage,
@ -26,6 +22,9 @@ pub struct ChunkVertex {
pub tex_index: u8, pub tex_index: u8,
} }
pub fn draw_world() {}
#[cfg(fuck)]
pub fn draw_world( pub fn draw_world(
mut target: NonSendSync<UniqueViewMut<RenderTarget>>, mut target: NonSendSync<UniqueViewMut<RenderTarget>>,
chunks: UniqueView<ChunkStorage>, chunks: UniqueView<ChunkStorage>,
@ -35,71 +34,72 @@ pub fn draw_world(
camera: View<Camera>, camera: View<Camera>,
settings: UniqueView<GameSettings> settings: UniqueView<GameSettings>
) { ) {
#[cfg(fuck)] { let camera = camera.iter().next().expect("No cameras in the scene");
let camera = camera.iter().next().expect("No cameras in the scene"); let draw_parameters = DrawParameters {
let draw_parameters = DrawParameters { depth: Depth {
depth: Depth { test: DepthTest::IfLess,
test: DepthTest::IfLess, write: true,
write: true,
..Default::default()
},
multisampling: settings.msaa.is_some(),
polygon_mode: PolygonMode::Fill, //Change to Line for wireframe
backface_culling: BackfaceCullingMode::CullClockwise,
..Default::default() ..Default::default()
}; },
let texture_sampler = Sampler(&texture.0, SamplerBehavior { multisampling: settings.msaa.is_some(),
minify_filter: MinifySamplerFilter::LinearMipmapLinear, polygon_mode: PolygonMode::Fill, //Change to Line for wireframe
magnify_filter: MagnifySamplerFilter::Nearest, backface_culling: BackfaceCullingMode::CullClockwise,
max_anisotropy: settings.max_anisotropy.unwrap_or_default(), ..Default::default()
wrap_function: (SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp), };
..Default::default() let texture_sampler = Sampler(&texture.0, SamplerBehavior {
}); minify_filter: MinifySamplerFilter::LinearMipmapLinear,
let view = camera.view_matrix.to_cols_array_2d(); magnify_filter: MagnifySamplerFilter::Nearest,
let perspective = camera.perspective_matrix.to_cols_array_2d(); max_anisotropy: settings.max_anisotropy.unwrap_or_default(),
wrap_function: (SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp),
..Default::default()
});
let view = camera.view_matrix.to_cols_array_2d();
let perspective = camera.perspective_matrix.to_cols_array_2d();
for (&position, chunk) in &chunks.chunks { for (&position, chunk) in &chunks.chunks {
if let Some(key) = chunk.mesh_index { if let Some(key) = chunk.mesh_index {
let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); let mesh = meshes.get(key).expect("Mesh index pointing to nothing");
let world_position = position.as_vec3() * CHUNK_SIZE as f32; let world_position = position.as_vec3() * CHUNK_SIZE as f32;
//Skip mesh if its empty //Skip mesh if its empty
if mesh.index_buffer.len() == 0 { if mesh.index_buffer.len() == 0 {
continue
}
//Frustum culling
{
let minp = world_position;
let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32);
if !camera.frustum.is_box_visible(minp, maxp) {
continue continue
} }
//Frustum culling
{
let minp = world_position;
let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32);
if !camera.frustum.is_box_visible(minp, maxp) {
continue
}
}
//Draw chunk mesh
target.0.draw(
&mesh.vertex_buffer,
&mesh.index_buffer,
&program.0,
&uniform! {
position_offset: world_position.to_array(),
view: view,
perspective: perspective,
tex: texture_sampler,
},
&draw_parameters
).unwrap();
} }
//Draw chunk mesh
target.0.draw(
&mesh.vertex_buffer,
&mesh.index_buffer,
&program.0,
&uniform! {
position_offset: world_position.to_array(),
view: view,
perspective: perspective,
tex: texture_sampler,
},
&draw_parameters
).unwrap();
} }
} }
} }
pub fn draw_current_chunk_border() {}
#[cfg(fuck)]
pub fn draw_current_chunk_border( pub fn draw_current_chunk_border(
mut target: NonSendSync<UniqueViewMut<RenderTarget>>, mut target: NonSendSync<UniqueViewMut<RenderTarget>>,
player: View<MainPlayer>, player: View<MainPlayer>,
transforms: View<Transform, track::All>, transforms: View<Transform, track::All>,
buffers: NonSendSync<UniqueView<CubePrimitive>>, buffers: UniqueView<CubePrimitive>,
program: NonSendSync<UniqueView<ColoredShaderPrefab>>, program: NonSendSync<UniqueView<ColoredShaderPrefab>>,
camera: View<Camera>, camera: View<Camera>,
settings: UniqueView<GameSettings>, settings: UniqueView<GameSettings>,

View file

@ -1,7 +1,4 @@
use glam::IVec3; use glam::IVec3;
use glium::{VertexBuffer, IndexBuffer};
use crate::rendering::world::ChunkVertex;
pub use kubi_shared::chunk::{CHUNK_SIZE, BlockData}; pub use kubi_shared::chunk::{CHUNK_SIZE, BlockData};
pub struct ChunkData { pub struct ChunkData {
@ -15,8 +12,8 @@ impl ChunkData {
} }
pub struct ChunkMesh { pub struct ChunkMesh {
pub vertex_buffer: VertexBuffer<ChunkVertex>, pub vertex_buffer: wgpu::Buffer,
pub index_buffer: IndexBuffer<u32>, pub index_buffer: wgpu::Buffer,
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]

View file

@ -2,18 +2,19 @@ use glam::{IVec3, ivec3};
use kubi_shared::networking::messages::ClientToServerMessage; use kubi_shared::networking::messages::ClientToServerMessage;
use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync, track}; use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync, track};
use uflow::SendMode; use uflow::SendMode;
use wgpu::util::DeviceExt;
use crate::{ use crate::{
player::MainPlayer, player::MainPlayer,
transform::Transform, transform::Transform,
settings::GameSettings, settings::GameSettings,
rendering::Renderer, rendering::Renderer,
state::GameState, state::GameState,
networking::UdpClient, networking::UdpClient,
}; };
use super::{ use super::{
ChunkStorage, ChunkMeshStorage, ChunkStorage, ChunkMeshStorage,
chunk::{Chunk, DesiredChunkState, CHUNK_SIZE, ChunkMesh, CurrentChunkState, ChunkData}, chunk::{Chunk, DesiredChunkState, CHUNK_SIZE, ChunkMesh, CurrentChunkState, ChunkData},
tasks::{ChunkTaskManager, ChunkTaskResponse, ChunkTask}, tasks::{ChunkTaskManager, ChunkTaskResponse, ChunkTask},
queue::BlockUpdateQueue queue::BlockUpdateQueue
}; };
@ -233,8 +234,20 @@ fn process_completed_tasks(
} }
//apply the mesh //apply the mesh
let vertex_buffer = VertexBuffer::new(&renderer.display, &vertices).unwrap(); let vertex_buffer = renderer.device.create_buffer_init(
let index_buffer = IndexBuffer::new(&renderer.display, PrimitiveType::TrianglesList, &indexes).unwrap(); &wgpu::util::BufferInitDescriptor {
label: Some("ChunkVertexBuffer"),
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsages::VERTEX,
}
);
let index_buffer = renderer.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("ChunkIndexBuffer"),
contents: bytemuck::cast_slice(&indexes),
usage: wgpu::BufferUsages::INDEX,
}
);
let mesh = ChunkMesh { let mesh = ChunkMesh {
vertex_buffer, vertex_buffer,
index_buffer, index_buffer,