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

View file

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

View file

@ -1,59 +1,57 @@
use shipyard::{NonSendSync, UniqueViewMut, UniqueView, View, IntoIter, IntoWithId};
use kubi_shared::{entity::Entity, transform::Transform};
use crate::{
assets::ColoredShaderPrefab,
camera::Camera,
settings::GameSettings
};
use super::{
RenderTarget,
primitives::cube::CenteredCubePrimitive
};
use super::shaders::Shaders;
// TODO: entity models
pub fn render_entities() {}
#[cfg(fuck)]
pub fn render_entities(
mut target: NonSendSync<UniqueViewMut<RenderTarget>>,
buffers: NonSendSync<UniqueView<CenteredCubePrimitive>>,
program: NonSendSync<UniqueView<ColoredShaderPrefab>>,
shaders: NonSendSync<UniqueView<Shaders>>,
camera: View<Camera>,
settings: UniqueView<GameSettings>,
entities: View<Entity>,
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 {
depth: Depth {
test: DepthTest::IfLess,
write: true,
..Default::default()
},
multisampling: settings.msaa.is_some(),
polygon_mode: PolygonMode::Fill,
backface_culling: BackfaceCullingMode::CullClockwise,
let draw_parameters = DrawParameters {
depth: Depth {
test: DepthTest::IfLess,
write: true,
..Default::default()
};
let view = camera.view_matrix.to_cols_array_2d();
let perspective = camera.perspective_matrix.to_cols_array_2d();
},
multisampling: settings.msaa.is_some(),
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() {
//skip rendering camera holder (as the entity would block the view)
if entity_id == camera_id { continue }
for (entity_id, (_, trans)) in (&entities, &transform).iter().with_id() {
//skip rendering camera holder (as the entity would block the view)
if entity_id == camera_id { continue }
//render entity
// target.0.draw(
// &buffers.0,
// &buffers.1,
// &program.0,
// &uniform! {
// color: [1.0, 1.0, 1.0, 1.0_f32],
// model: trans.0.to_cols_array_2d(),
// view: view,
// perspective: perspective,
// },
// &draw_parameters
// ).unwrap();
}
//render entity
// target.0.draw(
// &buffers.0,
// &buffers.1,
// &program.0,
// &uniform! {
// color: [1.0, 1.0, 1.0, 1.0_f32],
// model: trans.0.to_cols_array_2d(),
// view: view,
// perspective: perspective,
// },
// &draw_parameters
// ).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 wgpu::util::DeviceExt;
use crate::rendering::Renderer;
use super::PositionVertex;
#[derive(Unique)]
pub struct CubePrimitive {
pub vert: wgpu::Buffer,
pub idx: wgpu::Buffer
}
#[derive(Unique)]
pub struct CenteredCubePrimitive {
pub vert: wgpu::Buffer,
pub vert_centered: wgpu::Buffer,
pub idx: wgpu::Buffer
}
@ -61,30 +57,31 @@ const CUBE_INDICES: &[u16] = &[
pub(super) fn init_cube_primitive(
storages: AllStoragesView,
display: NonSendSync<UniqueView<Renderer>>
renderer: NonSendSync<UniqueView<Renderer>>
) {
{
let vert = VertexBuffer::new(
&display.display,
CUBE_VERTICES
).unwrap();
let index = IndexBuffer::new(
&display.display,
PrimitiveType::TrianglesList,
CUBE_INDICES
).unwrap();
storages.add_unique_non_send_sync(CubePrimitive(vert, index));
}
{
let vert = VertexBuffer::new(
&display.display,
CENTERED_CUBE_VERTICES
).unwrap();
let index = IndexBuffer::new(
&display.display,
PrimitiveType::TrianglesList,
CUBE_INDICES
).unwrap();
storages.add_unique_non_send_sync(CenteredCubePrimitive(vert, index));
}
storages.add_unique(
CubePrimitive {
vert: renderer.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("CubePrimitiveVertexBuffer"),
contents: bytemuck::cast_slice(CUBE_VERTICES),
usage: wgpu::BufferUsages::VERTEX,
}
),
vert_centered: renderer.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("CubePrimitiveCenteredVertexBuffer"),
contents: bytemuck::cast_slice(CUBE_VERTICES),
usage: wgpu::BufferUsages::VERTEX,
}
),
idx: renderer.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("CubePrimitiveIndexBuffer"),
contents: bytemuck::cast_slice(CUBE_VERTICES),
usage: wgpu::BufferUsages::INDEX,
}
)
}
);
}

View file

@ -1,9 +1,13 @@
use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView};
use wgpu::util::DeviceExt;
use crate::rendering::Renderer;
use super::PositionVertex2d;
#[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] = &[
PositionVertex2d { position: [0., 0.] },
@ -15,16 +19,21 @@ const RECT_INDEX: &[u16] = &[0, 1, 2, 1, 3, 2];
pub(super) fn init_rect_primitive(
storages: AllStoragesView,
display: NonSendSync<UniqueView<Renderer>>
renderer: NonSendSync<UniqueView<Renderer>>
) {
let vert = VertexBuffer::new(
&display.display,
RECT_VERTEX
).unwrap();
let index = IndexBuffer::new(
&display.display,
PrimitiveType::TrianglesList,
RECT_INDEX
).unwrap();
storages.add_unique_non_send_sync(RectPrimitive(vert, index));
let vert = renderer.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("RectPrimitiveVertexBuffer"),
contents: bytemuck::cast_slice(RECT_VERTEX),
usage: wgpu::BufferUsages::VERTEX,
}
);
let index = renderer.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
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 shipyard::{View, IntoIter, NonSendSync, UniqueViewMut, UniqueView};
use glium::{
Surface,
DrawParameters,
BackfaceCullingMode,
Blend, Depth, DepthTest,
uniform,
};
use crate::{
world::raycast::LookingAtBlock,
camera::Camera,
assets::ColoredShaderPrefab
};
use super::{
RenderTarget,
@ -19,12 +11,15 @@ use super::{
const SMOL: f32 = 0.0001;
pub fn render_selection_box() { }
#[cfg(fuck)]
pub fn render_selection_box(
lookat: View<LookingAtBlock>,
camera: View<Camera>,
mut target: NonSendSync<UniqueViewMut<RenderTarget>>,
program: NonSendSync<UniqueView<ColoredShaderPrefab>>,
buffers: NonSendSync<UniqueView<CubePrimitive>>,
buffers: UniqueView<CubePrimitive>,
) {
let camera = camera.iter().next().unwrap();
let Some(lookat) = lookat.iter().next() else { return };

View file

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

View file

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

View file

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

View file

@ -2,6 +2,7 @@ use glam::{IVec3, ivec3};
use kubi_shared::networking::messages::ClientToServerMessage;
use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync, track};
use uflow::SendMode;
use wgpu::util::DeviceExt;
use crate::{
player::MainPlayer,
transform::Transform,
@ -233,8 +234,20 @@ fn process_completed_tasks(
}
//apply the mesh
let vertex_buffer = VertexBuffer::new(&renderer.display, &vertices).unwrap();
let index_buffer = IndexBuffer::new(&renderer.display, PrimitiveType::TrianglesList, &indexes).unwrap();
let vertex_buffer = renderer.device.create_buffer_init(
&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 {
vertex_buffer,
index_buffer,