diff --git a/Cargo.lock b/Cargo.lock index 216818a..7bd2b84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -265,6 +265,20 @@ name = "bytemuck" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.23", +] [[package]] name = "byteorder" @@ -898,6 +912,7 @@ version = "0.0.0" dependencies = [ "android-activity", "anyhow", + "bytemuck", "flume", "gilrs", "glam", diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index 4f757c7..87b1b55 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -30,6 +30,7 @@ serde_json = { version = "1.0", optional = true } #only used for `generate_visua lz4_flex = { version = "0.11", default-features = false, features = ["std"] } tinyset = "0.4" pollster = "0.3" +bytemuck = { version = "1.12", features = ["derive"] } [target.'cfg(target_os = "android")'.dependencies] android-activity = { version = "0.4", features = ["native-activity"] } diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index bc6c304..ea235d4 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -52,22 +52,22 @@ use prefabs::load_prefabs; use settings::{load_settings, GameSettings}; use camera::compute_cameras; use events::{ - clear_events, - process_glutin_events, + clear_events, + process_glutin_events, initial_resize_event, - player_actions::generate_move_events, + player_actions::generate_move_events, }; use input::{init_input, process_inputs}; use fly_controller::update_controllers; use rendering::{ - Renderer, - RenderTarget, - BackgroundColor, + Renderer, + RenderTarget, + BackgroundColor, clear_background, primitives::init_primitives, world::{draw_world, draw_current_chunk_border}, selection_box::render_selection_box, - entities::render_entities, + entities::render_entities, }; use block_placement::update_block_placement; use delta_time::{DeltaTime, init_delta_time}; @@ -244,7 +244,7 @@ pub fn kubi_main() { //Start rendering (maybe use custom views for this?) let target = { let renderer = world.borrow::>>().unwrap(); - renderer.display.draw() + renderer.render() }; world.add_unique_non_send_sync(RenderTarget(target)); diff --git a/kubi/src/loading_screen.rs b/kubi/src/loading_screen.rs index 3774295..f448d2a 100644 --- a/kubi/src/loading_screen.rs +++ b/kubi/src/loading_screen.rs @@ -9,7 +9,7 @@ use crate::{ GuiComponent, progressbar::ProgressbarComponent }, - rendering::{WindowSize, if_resized}, + rendering::{Renderer, if_resized}, input::RawKbmInputState, }; @@ -19,11 +19,11 @@ struct ProgressbarId(EntityId); fn spawn_loading_screen( mut storages: AllStoragesViewMut, ) { - let size = *storages.borrow::>().unwrap(); + let size = storages.borrow::>().unwrap().size; let entity = storages.add_entity(( GuiComponent, Transform2d(Mat3::from_scale_angle_translation( - vec2(size.0.x as f32, 16.), + vec2(size.width as f32, 16.), 0., vec2(0., 0.) )), @@ -35,12 +35,12 @@ fn spawn_loading_screen( } fn resize_progress_bar( - size: UniqueView, + renderer: UniqueView, bar: UniqueView, mut transforms: ViewMut ) { let mut trans = (&mut transforms).get(bar.0).unwrap(); - trans.0.x_axis.x = size.0.x as f32; + trans.0.x_axis.x = renderer.size.width as f32; } fn update_progress_bar_progress ( diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 92bbae3..36aecad 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,4 +1,5 @@ use shipyard::{Unique, NonSendSync, UniqueView, UniqueViewMut, View, IntoIter, AllStoragesView}; +use wgpu::SurfaceConfiguration; use winit::{ event_loop::EventLoop, window::{Window, WindowBuilder, Fullscreen}, @@ -33,11 +34,14 @@ pub struct Renderer { pub device: wgpu::Device, pub queue: wgpu::Queue, pub size: PhysicalSize, + pub config: wgpu::SurfaceConfiguration, } impl Renderer { pub async fn init(event_loop: &EventLoop<()>, settings: &GameSettings) -> Self { log::info!("initializing display"); + // ========== Create a winit window ========== + //Build window let window = WindowBuilder::new() .with_title("kubi") @@ -62,21 +66,31 @@ impl Renderer { } } })); + + let size = window.inner_size(); + + // ========== Create wgpu stuff ========== + + // instance - //Create wgpu stuff let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { backends: wgpu::Backends::all(), dx12_shader_compiler: if cfg!(all(windows, feature = "dx12-dxc")) { + // Better, but requires shipping ms dxil dlls wgpu::Dx12Compiler::Dxc { dxil_path: None, dxc_path: None } } else { wgpu::Dx12Compiler::Fxc } }); + // surface + let surface = unsafe { instance.create_surface(&window) }.expect("Failed to create a Surface"); + // adapter + let adapter = instance.request_adapter( &wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::HighPerformance, @@ -84,7 +98,10 @@ impl Renderer { force_fallback_adapter: false, }, ).await.expect("Failed to create wgpu adapter"); - + log::info!("Adapter: {:?}", adapter.get_info()); + + // device/queue + let (device, queue) = adapter.request_device( &wgpu::DeviceDescriptor { features: wgpu::Features::empty(), @@ -100,9 +117,31 @@ impl Renderer { None, ).await.unwrap(); - log::info!("Adapter: {:?}", adapter.get_info()); + // surf. format - Self { window, instance, surface, adapter, device, queue, size: PhysicalSize::default() } + let surface_capabilities = surface.get_capabilities(&adapter); + let surface_format = surface_capabilities.formats.iter() + .copied() + .find(|f| f.is_srgb()) + .unwrap_or(surface_capabilities.formats[0]); + + // config + + let config = wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format: surface_format, + width: size.width, + height: size.height, + present_mode: match settings.vsync { + true => wgpu::PresentMode::AutoVsync, + false => wgpu::PresentMode::AutoNoVsync, + }, + alpha_mode: surface_capabilities.alpha_modes[0], + view_formats: vec![], + }; + surface.configure(&device, &config); + + Self { window, instance, surface, adapter, device, queue, size, config }; } /// do not call from async functions @@ -112,7 +151,20 @@ impl Renderer { /// Start a new frame pub fn render() -> RenderTarget { + todo!() + } + /// Resize the surface + /// ## Panics: + /// - ...if any dimension is equal to zero + pub fn resize(&self, new_size: PhysicalSize) { + //XXX: just check instead? + assert!(new_size.width > 0, "width cannot be zero"); + assert!(new_size.height > 0, "height cannot be zero"); + self.size = new_size; + self.config.width = new_size.width; + self.config.height = new_size.height; + self.surface.configure(&self.device, &self.config); } } diff --git a/kubi/src/rendering/entities.rs b/kubi/src/rendering/entities.rs index 7bd3534..d408c8c 100644 --- a/kubi/src/rendering/entities.rs +++ b/kubi/src/rendering/entities.rs @@ -20,38 +20,40 @@ pub fn render_entities( entities: View, transform: View, ) { - let (camera_id, camera) = camera.iter().with_id().next().expect("No cameras in the scene"); + #[cfg(fuck)] { + 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, + 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, ..Default::default() - }, - 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(); + }; + 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/primitives/cube.rs b/kubi/src/rendering/primitives/cube.rs index 297dcb1..d2ade06 100644 --- a/kubi/src/rendering/primitives/cube.rs +++ b/kubi/src/rendering/primitives/cube.rs @@ -1,13 +1,18 @@ use shipyard::{AllStoragesView, NonSendSync, UniqueView, Unique}; -use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; use crate::rendering::Renderer; use super::PositionOnlyVertex; #[derive(Unique)] -pub struct CubePrimitive(pub VertexBuffer, pub IndexBuffer); +pub struct CubePrimitive { + pub vert: wgpu::Buffer, + pub idx: wgpu::Buffer +} #[derive(Unique)] -pub struct CenteredCubePrimitive(pub VertexBuffer, pub IndexBuffer); +pub struct CenteredCubePrimitive { + pub vert: wgpu::Buffer, + pub idx: wgpu::Buffer +} const CENTERED_CUBE_VERTICES: &[PositionOnlyVertex] = &[ // front diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 0485408..29227c5 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -18,7 +18,7 @@ use crate::{ use super::{RenderTarget, primitives::cube::CubePrimitive}; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] pub struct ChunkVertex { pub position: [f32; 3], pub normal: [f32; 3], @@ -35,60 +35,62 @@ pub fn draw_world( camera: View, settings: UniqueView ) { - let camera = camera.iter().next().expect("No cameras in the scene"); - let draw_parameters = DrawParameters { - depth: Depth { - test: DepthTest::IfLess, - write: true, + #[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, ..Default::default() - }, - 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(); + }; + 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 { - 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) { + 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 } - } - //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(); + //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(); + } } } } @@ -102,65 +104,67 @@ pub fn draw_current_chunk_border( camera: View, settings: UniqueView, ) { - if cfg!(target_os = "android") { - return - } - if !settings.debug_draw_current_chunk_border { - return - } - let camera = camera.iter().next().expect("No cameras in the scene"); - let view = camera.view_matrix.to_cols_array_2d(); - let perspective = camera.perspective_matrix.to_cols_array_2d(); - let (_, &player_transform) = (&player, &transforms).iter().next().expect("No player"); - let (_, _, player_position) = player_transform.0.to_scale_rotation_translation(); - let player_in_chunk = ivec3( - (player_position.x as i32).div_euclid(CHUNK_SIZE as i32), - (player_position.y as i32).div_euclid(CHUNK_SIZE as i32), - (player_position.z as i32).div_euclid(CHUNK_SIZE as i32), - ); - let world_position = player_in_chunk.as_vec3() * CHUNK_SIZE as f32; - target.0.draw( - &buffers.0, - &buffers.1, - &program.0, - &uniform! { - model: Mat4::from_scale_rotation_translation( - Vec3::splat(CHUNK_SIZE as f32), - Quat::default(), - world_position - ).to_cols_array_2d(), - color: [0.25f32; 4], - view: view, - perspective: perspective, - }, - &DrawParameters { - depth: Depth { - test: DepthTest::IfLess, - ..Default::default() + #[cfg(fuck)] { + if cfg!(target_os = "android") { + return + } + if !settings.debug_draw_current_chunk_border { + return + } + let camera = camera.iter().next().expect("No cameras in the scene"); + let view = camera.view_matrix.to_cols_array_2d(); + let perspective = camera.perspective_matrix.to_cols_array_2d(); + let (_, &player_transform) = (&player, &transforms).iter().next().expect("No player"); + let (_, _, player_position) = player_transform.0.to_scale_rotation_translation(); + let player_in_chunk = ivec3( + (player_position.x as i32).div_euclid(CHUNK_SIZE as i32), + (player_position.y as i32).div_euclid(CHUNK_SIZE as i32), + (player_position.z as i32).div_euclid(CHUNK_SIZE as i32), + ); + let world_position = player_in_chunk.as_vec3() * CHUNK_SIZE as f32; + target.0.draw( + &buffers.0, + &buffers.1, + &program.0, + &uniform! { + model: Mat4::from_scale_rotation_translation( + Vec3::splat(CHUNK_SIZE as f32), + Quat::default(), + world_position + ).to_cols_array_2d(), + color: [0.25f32; 4], + view: view, + perspective: perspective, }, - blend: Blend::alpha_blending(), - ..Default::default() - } - ).unwrap(); - target.0.draw( - &buffers.0, - &buffers.1, - &program.0, - &uniform! { - model: Mat4::from_scale_rotation_translation( - Vec3::splat(CHUNK_SIZE as f32), - Quat::default(), - world_position - ).to_cols_array_2d(), - color: [0.0f32; 4], - view: view, - perspective: perspective, - }, - &DrawParameters { - polygon_mode: PolygonMode::Point, - line_width: Some(2.), - point_size: Some(5.), - ..Default::default() - } - ).unwrap(); + &DrawParameters { + depth: Depth { + test: DepthTest::IfLess, + ..Default::default() + }, + blend: Blend::alpha_blending(), + ..Default::default() + } + ).unwrap(); + target.0.draw( + &buffers.0, + &buffers.1, + &program.0, + &uniform! { + model: Mat4::from_scale_rotation_translation( + Vec3::splat(CHUNK_SIZE as f32), + Quat::default(), + world_position + ).to_cols_array_2d(), + color: [0.0f32; 4], + view: view, + perspective: perspective, + }, + &DrawParameters { + polygon_mode: PolygonMode::Point, + line_width: Some(2.), + point_size: Some(5.), + ..Default::default() + } + ).unwrap(); + } }