diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index 161322e..c383963 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -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, diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 65e6eae..e664645 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -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>, - color: UniqueView, -) { - +pub fn renderer_finish_init() -> Workload { + ( + compile_shaders, + init_pipelines.after_all(compile_shaders), + init_primitives, + ).into_workload() } #[deprecated] diff --git a/kubi/src/rendering/entities.rs b/kubi/src/rendering/entities.rs index 0bdebde..b12cf0b 100644 --- a/kubi/src/rendering/entities.rs +++ b/kubi/src/rendering/entities.rs @@ -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>, + mut target: NonSendSync>, buffers: NonSendSync>, - program: NonSendSync>, + shaders: NonSendSync>, camera: View, settings: UniqueView, entities: View, transform: View, ) { - #[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(); } } diff --git a/kubi/src/rendering/pipelines.rs b/kubi/src/rendering/pipelines.rs new file mode 100644 index 0000000..0f6c0e6 --- /dev/null +++ b/kubi/src/rendering/pipelines.rs @@ -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::>>().unwrap(); + let shaders = storages.borrow::>().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, + }), + }) +} diff --git a/kubi/src/rendering/primitives/cube.rs b/kubi/src/rendering/primitives/cube.rs index b9c7e8f..c05c9ab 100644 --- a/kubi/src/rendering/primitives/cube.rs +++ b/kubi/src/rendering/primitives/cube.rs @@ -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> + renderer: NonSendSync> ) { - { - 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, + } + ) + } + ); } diff --git a/kubi/src/rendering/primitives/rect.rs b/kubi/src/rendering/primitives/rect.rs index b3e96af..c4e0191 100644 --- a/kubi/src/rendering/primitives/rect.rs +++ b/kubi/src/rendering/primitives/rect.rs @@ -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, pub IndexBuffer); +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> + renderer: NonSendSync> ) { - 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 }); } diff --git a/kubi/src/rendering/selection_box.rs b/kubi/src/rendering/selection_box.rs index a96992b..6b6c52b 100644 --- a/kubi/src/rendering/selection_box.rs +++ b/kubi/src/rendering/selection_box.rs @@ -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, camera: View, mut target: NonSendSync>, program: NonSendSync>, - buffers: NonSendSync>, + buffers: UniqueView, ) { let camera = camera.iter().next().unwrap(); let Some(lookat) = lookat.iter().next() else { return }; diff --git a/kubi/src/rendering/shaders.rs b/kubi/src/rendering/shaders.rs index abdc47b..a39af46 100644 --- a/kubi/src/rendering/shaders.rs +++ b/kubi/src/rendering/shaders.rs @@ -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::>>().unwrap(); - let shaders = upload_shaders! { + storages.add_unique(build_shaders! { Shaders [renderer, "../../shaders"] { world: "world.wgsl", colored: "colored.wgsl" } - }; + }); } diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index ac56940..93ae1c0 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -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>, chunks: UniqueView, @@ -35,71 +34,72 @@ pub fn draw_world( camera: View, settings: UniqueView ) { - #[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; - - //Skip mesh if its empty - if mesh.index_buffer.len() == 0 { + 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 { + 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>, player: View, transforms: View, - buffers: NonSendSync>, + buffers: UniqueView, program: NonSendSync>, camera: View, settings: UniqueView, diff --git a/kubi/src/world/chunk.rs b/kubi/src/world/chunk.rs index 157254c..fa7fbb9 100644 --- a/kubi/src/world/chunk.rs +++ b/kubi/src/world/chunk.rs @@ -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, - pub index_buffer: IndexBuffer, + pub vertex_buffer: wgpu::Buffer, + pub index_buffer: wgpu::Buffer, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index 502108e..bb5a2a2 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -2,18 +2,19 @@ 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, settings::GameSettings, - rendering::Renderer, - state::GameState, + rendering::Renderer, + state::GameState, networking::UdpClient, }; use super::{ ChunkStorage, ChunkMeshStorage, chunk::{Chunk, DesiredChunkState, CHUNK_SIZE, ChunkMesh, CurrentChunkState, ChunkData}, - tasks::{ChunkTaskManager, ChunkTaskResponse, ChunkTask}, + tasks::{ChunkTaskManager, ChunkTaskResponse, ChunkTask}, queue::BlockUpdateQueue }; @@ -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,