Compare commits

..

12 commits

Author SHA1 Message Date
griffi-gh 99cc2d1e72 enable all backends 2024-05-06 17:21:18 +02:00
griffi-gh 85c64c9064 flip uvs 2024-05-06 17:19:11 +02:00
griffi-gh 6e9e3fa445 enable depth texture 2024-05-06 17:09:13 +02:00
griffi-gh 8a4549efea restructure stuff and fix some warnings 2024-05-06 16:53:40 +02:00
griffi-gh 6f25cb728f remove WindowSize 2024-05-06 16:24:44 +02:00
griffi-gh 9a01ecd6f2 depth, wip 2024-05-06 16:17:01 +02:00
griffi-gh 8fd1930ce6 forgor vec4 type 2024-05-06 15:54:17 +02:00
griffi-gh 674ec97a6e oops 2024-05-06 15:53:47 +02:00
griffi-gh f04542ac02 discard fully transparent 2024-05-06 15:52:59 +02:00
griffi-gh dd386acea1 owo 2024-05-06 15:48:36 +02:00
griffi-gh d14b5e1b40 ok this is better 2024-05-06 14:29:07 +02:00
griffi-gh f4e4886d33 i see... something? 2024-05-06 13:32:44 +02:00
27 changed files with 590 additions and 316 deletions

View file

@ -9,7 +9,7 @@ pub fn init() {
use env_logger::{fmt::Color, Builder, Env}; use env_logger::{fmt::Color, Builder, Env};
let env = Env::default() let env = Env::default()
.filter_or("RUST_LOG", "trace,gilrs=warn,rusty_xinput=warn,wgpu=warn,wgpu_core=warn,wgpu_hal=warn,hui=info,hui-winit=info,hui-glium=info,hui-wgpu=info"); .filter_or("RUST_LOG", "trace,gilrs=warn,rusty_xinput=warn,wgpu=warn,wgpu_core=warn,wgpu_hal=warn,hui=info,hui-winit=info,hui-glium=info,hui-wgpu=info,naga=warn");
Builder::from_env(env) Builder::from_env(env)
.format(|buf, record| { .format(|buf, record| {
let mut level_style = buf.style(); let mut level_style = buf.style();

View file

@ -1,4 +1,3 @@
use fastnoise_lite::FastNoiseLite;
use glam::ivec3; use glam::ivec3;
use crate::{block::Block, chunk::CHUNK_SIZE, worldgen::SeedThingy}; use crate::{block::Block, chunk::CHUNK_SIZE, worldgen::SeedThingy};
use super::{ use super::{

View file

@ -1,23 +1,22 @@
// struct Uniforms { struct CameraUniform {
// transform: mat4x4<f32>; view_proj: mat4x4<f32>,
// }; };
// @group(1) @binding(0) @group(1) @binding(0)
// var<uniform> uniforms: Uniforms; var<uniform> camera: CameraUniform;
struct VertexInput { struct VertexInput {
@location(0) position: vec3<f32>, @location(0) position: vec3<f32>,
@location(1) normal: vec3<f32>, @location(1) normal: vec3<f32>,
@location(2) uv: vec2<f32>, @location(2) uv: vec2<f32>,
@location(3) @interpolate(flat) tex_index: u32, @location(3) tex_index: u32,
} }
struct VertexOutput { struct VertexOutput {
@builtin(position) clip_position: vec4<f32>, @builtin(position) clip_position: vec4<f32>,
@location(0) uv: vec2<f32>, @location(0) uv: vec2<f32>,
@location(1) normal: vec3<f32>, @location(1) normal: vec3<f32>,
@location(2) color: vec4<f32>, @location(2) @interpolate(flat)tex_index: u32,
@location(3) @interpolate(flat) tex_index: u32,
}; };
@vertex @vertex
@ -26,7 +25,9 @@ fn vs_main(
) -> VertexOutput { ) -> VertexOutput {
var out: VertexOutput; var out: VertexOutput;
out.uv = in.uv; out.uv = in.uv;
out.clip_position = vec4<f32>(in.position, 1.0); out.normal = in.normal;
out.tex_index = in.tex_index;
out.clip_position = camera.view_proj * vec4<f32>(in.position, 1.0);
return out; return out;
} }
@ -38,5 +39,9 @@ var s_diffuse: sampler;
@fragment @fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
return textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); let color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index);
if (color.a == 0.) {
discard;
}
return color;
} }

View file

@ -1,6 +1,6 @@
use glam::{Vec3, Mat4}; use glam::{Vec3, Mat4};
use shipyard::{ViewMut, View, IntoIter, Workload, IntoWorkload, track, UniqueView, SystemModificator}; use shipyard::{ViewMut, View, IntoIter, Workload, IntoWorkload, track, UniqueView, SystemModificator};
use crate::{transform::Transform, rendering::WindowSize, events::WindowResizedEvent}; use crate::{transform::Transform, rendering::Renderer, events::WindowResizedEvent};
use super::Camera; use super::Camera;
//maybe parallelize these two? //maybe parallelize these two?
@ -18,14 +18,15 @@ fn update_view_matrix(
fn update_perspective_matrix( fn update_perspective_matrix(
mut vm_camera: ViewMut<Camera>, mut vm_camera: ViewMut<Camera>,
size: UniqueView<WindowSize>, ren: UniqueView<Renderer>,
) { ) {
let sz = ren.size_vec2();
for mut camera in (&mut vm_camera).iter() { for mut camera in (&mut vm_camera).iter() {
camera.perspective_matrix = Mat4::perspective_rh_gl( camera.perspective_matrix = Mat4::perspective_rh(
camera.fov, camera.fov,
size.0.x as f32 / size.0.y as f32, sz.x / sz.y,
camera.z_near, camera.z_near,
camera.z_far, camera.z_far,
) )
} }
} }

View file

@ -1,5 +1,5 @@
use kubi_shared::networking::client::ClientId; use kubi_shared::networking::client::ClientId;
use shipyard::{AllStoragesView, Unique, UniqueViewMut}; use shipyard::{AllStoragesView, Unique};
pub enum ChatMessage { pub enum ChatMessage {
PlayerMessage { PlayerMessage {

View file

@ -1,7 +1,7 @@
//TODO client-side physics //TODO client-side physics
//TODO move this to shared //TODO move this to shared
use glam::{vec3, IVec3, Mat4, Vec3, Vec3Swizzles}; use glam::{vec3, Mat4, Vec3, Vec3Swizzles};
use shipyard::{track, AllStoragesView, Component, IntoIter, Unique, UniqueView, View, ViewMut}; use shipyard::{track, AllStoragesView, Component, IntoIter, Unique, UniqueView, ViewMut};
use kubi_shared::{block::{Block, CollisionType}, transform::Transform}; use kubi_shared::{block::{Block, CollisionType}, transform::Transform};
use crate::{delta_time::DeltaTime, world::ChunkStorage}; use crate::{delta_time::DeltaTime, world::ChunkStorage};

View file

@ -86,18 +86,18 @@ pub fn process_winit_events(world: &mut World, event: &Event<()>) {
} }
} }
pub fn initial_resize_event( // pub fn initial_resize_event(
mut storages: AllStoragesViewMut, // mut storages: AllStoragesViewMut,
) { // ) {
let (w, h) = { // let (w, h) = {
let renderer = storages.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap(); // let renderer = storages.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
(renderer.size().width, renderer.size().height) // (renderer.size().width, renderer.size().height)
}; // };
storages.add_entity(( // storages.add_entity((
EventComponent, // EventComponent,
WindowResizedEvent(UVec2::new(w, h)) // WindowResizedEvent(UVec2::new(w, h))
)); // ));
} // }
pub fn clear_events( pub fn clear_events(
mut all_storages: AllStoragesViewMut, mut all_storages: AllStoragesViewMut,

View file

@ -1,7 +1,7 @@
use hui::UiInstance; use hui::UiInstance;
//use hui_glium::GliumUiRenderer; //use hui_glium::GliumUiRenderer;
use shipyard::{AllStoragesView, Unique, UniqueView, NonSendSync, UniqueViewMut}; use shipyard::{AllStoragesView, Unique, UniqueView, NonSendSync, UniqueViewMut};
use crate::rendering::{Renderer, WindowSize}; use crate::rendering::Renderer;
#[derive(Unique)] #[derive(Unique)]
pub struct UiState { pub struct UiState {

View file

@ -10,7 +10,7 @@ use nohash_hasher::BuildNoHashHasher;
use shipyard::{AllStoragesView, Unique, View, IntoIter, UniqueViewMut, Workload, IntoWorkload, UniqueView, NonSendSync}; use shipyard::{AllStoragesView, Unique, View, IntoIter, UniqueViewMut, Workload, IntoWorkload, UniqueView, NonSendSync};
use crate::{ use crate::{
events::{InputDeviceEvent, TouchEvent}, events::{InputDeviceEvent, TouchEvent},
rendering::WindowSize rendering::Renderer,
}; };
#[derive(Unique, Clone, Copy, Default, Debug)] #[derive(Unique, Clone, Copy, Default, Debug)]
@ -211,10 +211,10 @@ fn update_input_state_gamepad (
fn update_input_state_touch ( fn update_input_state_touch (
touch_state: UniqueView<RawTouchState>, touch_state: UniqueView<RawTouchState>,
win_size: UniqueView<WindowSize>, renderer: UniqueView<Renderer>,
mut inputs: UniqueViewMut<Inputs>, mut inputs: UniqueViewMut<Inputs>,
) { ) {
let w = win_size.0.as_dvec2(); let w = renderer.size_uvec2().as_dvec2();
//Movement //Movement
if let Some(finger) = touch_state.query_area( if let Some(finger) = touch_state.query_area(

View file

@ -13,7 +13,7 @@
use shipyard::{ use shipyard::{
World, Workload, IntoWorkload, World, Workload, IntoWorkload,
UniqueView, UniqueViewMut, UniqueView, UniqueViewMut,
NonSendSync, WorkloadModificator, WorkloadModificator,
SystemModificator SystemModificator
}; };
use winit::{ use winit::{
@ -58,31 +58,19 @@ pub(crate) mod chat;
use world::{ use world::{
init_game_world, init_game_world,
loading::update_loaded_world_around_player, loading::update_loaded_world_around_player,
raycast::update_raycasts, raycast::update_raycasts,
queue::apply_queued_blocks, queue::apply_queued_blocks,
tasks::ChunkTaskManager, tasks::ChunkTaskManager,
}; };
use player::{spawn_player, MainPlayer}; use player::{spawn_player, MainPlayer};
use prefabs::load_prefabs; use prefabs::load_prefabs;
use settings::{load_settings, GameSettings}; use settings::{load_settings, GameSettings};
use camera::compute_cameras; use camera::compute_cameras;
use events::{ use events::{clear_events, process_winit_events, player_actions::generate_move_events};
clear_events,
process_winit_events,
initial_resize_event,
player_actions::generate_move_events,
};
use input::{init_input, process_inputs}; use input::{init_input, process_inputs};
use player_controller::{debug_switch_ctl_type, update_player_controllers}; use player_controller::{debug_switch_ctl_type, update_player_controllers};
// use rendering::{ use rendering::{BackgroundColor, Renderer, init_rendering, render_master, update_rendering_early, update_rendering_late};
// clear_background, entities::render_entities, init_window_size, primitives::init_primitives, resize_renderer, selection_box::render_selection_box, sumberge::render_submerged_view, update_window_size, world::{draw_current_chunk_border, draw_world, draw_world_trans, init_trans_chunk_queue}, BackgroundColor, RenderTarget, Renderer
// };
use rendering::{
init_window_size, render_master, resize_renderer, update_window_size,
world::{init_trans_chunk_queue, TransChunkQueue},
BackgroundColor, Renderer,
};
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};
use cursor_lock::{debug_toggle_lock, insert_lock_state, lock_cursor_now, update_cursor_lock_state}; use cursor_lock::{debug_toggle_lock, insert_lock_state, lock_cursor_now, update_cursor_lock_state};
@ -112,11 +100,9 @@ fn pre_startup() -> Workload {
fn startup() -> Workload { fn startup() -> Workload {
( (
init_fixed_timestamp_storage, init_fixed_timestamp_storage,
initial_resize_event,
init_window_size,
kubi_ui_init, kubi_ui_init,
load_prefabs, load_prefabs,
//init_primitives, init_rendering,
insert_lock_state, insert_lock_state,
init_state, init_state,
initialize_from_args, initialize_from_args,
@ -132,14 +118,12 @@ fn startup() -> Workload {
fn update() -> Workload { fn update() -> Workload {
( (
update_rendering_early,
debug_toggle_lock, debug_toggle_lock,
update_window_size,
resize_renderer,
update_cursor_lock_state, update_cursor_lock_state,
process_inputs, process_inputs,
kubi_ui_begin, kubi_ui_begin,
( (
init_trans_chunk_queue.run_if_missing_unique::<TransChunkQueue>(),
init_game_world.run_if_missing_unique::<ChunkTaskManager>(), init_game_world.run_if_missing_unique::<ChunkTaskManager>(),
( (
spawn_player.run_if_storage_empty::<MainPlayer>(), spawn_player.run_if_storage_empty::<MainPlayer>(),
@ -174,6 +158,7 @@ fn update() -> Workload {
update_state, update_state,
exit_on_esc, exit_on_esc,
disconnect_on_exit.run_if(is_multiplayer), disconnect_on_exit.run_if(is_multiplayer),
update_rendering_late,
).into_sequential_workload() ).into_sequential_workload()
} }
@ -192,7 +177,7 @@ fn update() -> Workload {
// ).into_sequential_workload() // ).into_sequential_workload()
// } // }
fn after_frame_end() -> Workload { fn after_render() -> Workload {
( (
clear_events, clear_events,
).into_sequential_workload() ).into_sequential_workload()
@ -241,7 +226,7 @@ pub fn kubi_main(
world.add_workload(startup); world.add_workload(startup);
world.add_workload(update); world.add_workload(update);
//world.add_workload(render); //world.add_workload(render);
world.add_workload(after_frame_end); world.add_workload(after_render);
//Save _visualizer.json //Save _visualizer.json
#[cfg(feature = "generate_visualizer_data")] #[cfg(feature = "generate_visualizer_data")]
@ -338,7 +323,7 @@ pub fn kubi_main(
// target.0.finish().unwrap(); // target.0.finish().unwrap();
//After frame end //After frame end
world.run_workload(after_frame_end).unwrap(); world.run_workload(after_render).unwrap();
//Process control flow changes //Process control flow changes
if world.borrow::<UniqueView<RequestExit>>().unwrap().0 { if world.borrow::<UniqueView<RequestExit>>().unwrap().0 {

View file

@ -38,6 +38,7 @@ impl AssetPaths for BlockTexture {
#[derive(Unique)] #[derive(Unique)]
pub struct TexturePrefabs { pub struct TexturePrefabs {
pub block_diffuse_texture: wgpu::Texture, pub block_diffuse_texture: wgpu::Texture,
pub block_diffuse_bind_group_layout: wgpu::BindGroupLayout,
pub block_diffuse_bind_group: wgpu::BindGroup, pub block_diffuse_bind_group: wgpu::BindGroup,
} }
@ -59,8 +60,12 @@ pub fn load_prefabs(
); );
log::info!("Creating bing groups"); log::info!("Creating bing groups");
let block_diffuse_view = block_diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default()); let block_diffuse_view = block_diffuse_texture.create_view(&wgpu::TextureViewDescriptor {
label: Some("block_texture_view"),
..Default::default()
});
let block_diffuse_sampler = renderer.device().create_sampler(&wgpu::SamplerDescriptor { let block_diffuse_sampler = renderer.device().create_sampler(&wgpu::SamplerDescriptor {
label: Some("block_diffuse_sampler"),
address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge,
@ -107,6 +112,7 @@ pub fn load_prefabs(
}); });
storages.add_unique_non_send_sync(TexturePrefabs { storages.add_unique_non_send_sync(TexturePrefabs {
block_diffuse_texture, block_diffuse_texture,
block_diffuse_bind_group_layout,
block_diffuse_bind_group, block_diffuse_bind_group,
}); });

View file

@ -1,16 +1,16 @@
use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, Unique, UniqueView, UniqueViewMut, View}; use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, SystemModificator, Unique, UniqueView, UniqueViewMut, View, Workload, WorkloadModificator};
use winit::dpi::PhysicalSize; use winit::dpi::PhysicalSize;
use glam::{Vec3, UVec2}; use glam::Vec3;
use crate::{events::WindowResizedEvent, state::is_ingame}; use crate::{events::WindowResizedEvent, state::is_ingame};
mod renderer; mod renderer;
pub use renderer::Renderer; pub use renderer::Renderer;
pub mod primitives; use self::{camera::CameraUniformBuffer, world::WorldRenderState};
pub mod world; pub mod world;
pub mod selection_box; pub mod camera;
pub mod entities; pub mod depth;
pub mod sumberge;
pub struct BufferPair { pub struct BufferPair {
pub index: wgpu::Buffer, pub index: wgpu::Buffer,
@ -28,6 +28,27 @@ pub struct RenderCtx<'a> {
pub surface_view: &'a wgpu::TextureView, pub surface_view: &'a wgpu::TextureView,
} }
pub fn init_rendering() -> Workload {
(
depth::init_depth_texture,
camera::init_camera_uniform_buffer,
world::init_world_render_state, //TODO run only once ingame
).into_sequential_workload()
}
pub fn update_rendering_early() -> Workload {
(
resize_renderer,
depth::resize_depth_texture,
).into_sequential_workload()
}
pub fn update_rendering_late() -> Workload {
(
camera::update_camera_uniform_buffer,
).into_workload()
}
pub fn render_master(storages: AllStoragesViewMut) { pub fn render_master(storages: AllStoragesViewMut) {
let renderer = storages.borrow::<UniqueView<Renderer>>().unwrap(); let renderer = storages.borrow::<UniqueView<Renderer>>().unwrap();
@ -85,25 +106,25 @@ pub fn resize_renderer(
//Deprecated WindowSize thingy //Deprecated WindowSize thingy
#[derive(Unique, Clone, Copy)] // #[derive(Unique, Clone, Copy)]
#[repr(transparent)] // #[repr(transparent)]
#[deprecated = "use Renderer.size instead"] // #[deprecated = "use Renderer.size instead"]
#[allow(deprecated)] // #[allow(deprecated)]
pub struct WindowSize(pub UVec2); // pub struct WindowSize(pub UVec2);
pub fn init_window_size(storages: AllStoragesView) { // pub fn init_window_size(storages: AllStoragesView) {
let size = storages.borrow::<View<WindowResizedEvent>>().unwrap().iter().next().unwrap().0; // let size = storages.borrow::<View<WindowResizedEvent>>().unwrap().iter().next().unwrap().0;
storages.add_unique(WindowSize(size)) // storages.add_unique(WindowSize(size))
} // }
pub fn update_window_size( // pub fn update_window_size(
mut win_size: UniqueViewMut<WindowSize>, // mut win_size: UniqueViewMut<WindowSize>,
resize: View<WindowResizedEvent>, // resize: View<WindowResizedEvent>,
) { // ) {
if let Some(resize) = resize.iter().next() { // if let Some(resize) = resize.iter().next() {
win_size.0 = resize.0; // win_size.0 = resize.0;
} // }
} // }
// pub fn if_resized ( // pub fn if_resized (
// resize: View<WindowResizedEvent>, // resize: View<WindowResizedEvent>,

View file

@ -0,0 +1,83 @@
use bytemuck::{Pod, Zeroable};
use kubi_shared::transform::Transform;
use shipyard::{AllStoragesView, IntoIter, Unique, UniqueView, View};
use wgpu::util::DeviceExt;
use crate::camera::{self, Camera};
use super::Renderer;
#[derive(Debug, Clone, Copy, Default, Pod, Zeroable)]
#[repr(C, packed)]
pub struct CameraUniformData {
pub view_proj: [f32; 4 * 4],
}
//TODO if multiple cameras, buffer per camera
#[derive(Unique)]
pub struct CameraUniformBuffer {
pub camera_uniform_buffer: wgpu::Buffer,
pub camera_bind_group_layout: wgpu::BindGroupLayout,
pub camera_bind_group: wgpu::BindGroup,
}
impl CameraUniformBuffer {
pub fn init(renderer: &Renderer, data: CameraUniformData) -> Self {
let camera_uniform_buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("camera_uniform_buffer"),
contents: bytemuck::cast_slice(&[data]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let camera_bind_group_layout = renderer.device().create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("camera_bind_group_layout"),
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
],
});
let camera_bind_group = renderer.device().create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("camera_bind_group"),
layout: &camera_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: camera_uniform_buffer.as_entire_binding(),
},
],
});
Self { camera_uniform_buffer, camera_bind_group_layout, camera_bind_group }
}
pub fn init_default(renderer: &Renderer) -> Self {
Self::init(renderer, CameraUniformData::default())
}
pub fn update(&self, renderer: &Renderer, data: CameraUniformData) {
renderer.queue().write_buffer(&self.camera_uniform_buffer, 0, bytemuck::cast_slice(&[data]));
}
}
pub fn init_camera_uniform_buffer(storages: AllStoragesView) {
let renderer = storages.borrow::<UniqueView<Renderer>>().unwrap();
storages.add_unique(CameraUniformBuffer::init_default(&renderer));
}
pub fn update_camera_uniform_buffer(
renderer: UniqueView<Renderer>,
camera_uniform_buffer: UniqueView<CameraUniformBuffer>,
camera: View<Camera>,
) {
let Some(camera) = camera.iter().next() else { return };
let proj = camera.perspective_matrix * camera.view_matrix;
camera_uniform_buffer.update(&renderer, CameraUniformData { view_proj: proj.to_cols_array() });
}

View file

@ -0,0 +1,72 @@
use glam::{uvec2, UVec2};
use shipyard::{AllStoragesView, Unique, UniqueView, UniqueViewMut};
use super::Renderer;
#[derive(Unique)]
pub struct DepthTexture {
pub depth_texture: wgpu::Texture,
pub depth_view: wgpu::TextureView,
pub depth_sampler: wgpu::Sampler,
}
impl DepthTexture {
fn desc(size: UVec2) -> wgpu::TextureDescriptor<'static> {
wgpu::TextureDescriptor {
label: Some("depth_texture"),
size: wgpu::Extent3d {
width: size.x,
height: size.y,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Depth32Float,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
view_formats: &[wgpu::TextureFormat::Depth32Float],
}
}
pub fn init(renderer: &Renderer) -> Self {
let size = uvec2(renderer.size().width, renderer.size().height);
let depth_texture_desc = Self::desc(size);
let depth_texture = renderer.device().create_texture(&depth_texture_desc);
let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
let depth_sampler = renderer.device().create_sampler(&wgpu::SamplerDescriptor {
label: Some("depth_sampler"),
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Nearest,
min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
..Default::default()
});
Self { depth_texture, depth_view, depth_sampler }
}
pub fn resize(&mut self, renderer: &Renderer) {
let old_size = uvec2(self.depth_texture.size().width, self.depth_texture.size().height);
let new_size = uvec2(renderer.size().width, renderer.size().height);
if old_size == new_size { return }
let depth_texture_desc = Self::desc(new_size);
self.depth_texture = renderer.device().create_texture(&depth_texture_desc);
self.depth_view = self.depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
}
}
pub fn init_depth_texture(
storages: AllStoragesView,
) {
let renderer = storages.borrow::<UniqueView<Renderer>>().unwrap();
storages.add_unique(DepthTexture::init(&renderer));
}
pub fn resize_depth_texture(
mut depth_texture: UniqueViewMut<DepthTexture>,
renderer: UniqueView<Renderer>,
) {
depth_texture.resize(&renderer);
}

View file

@ -75,7 +75,7 @@ impl Renderer {
let size = window.inner_size(); let size = window.inner_size();
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::BROWSER_WEBGPU | wgpu::Backends::VULKAN | wgpu::Backends::GL, backends: wgpu::Backends::all(),
//Disable validation layer //Disable validation layer
flags: wgpu::InstanceFlags::default() & !wgpu::InstanceFlags::VALIDATION, flags: wgpu::InstanceFlags::default() & !wgpu::InstanceFlags::VALIDATION,
//we're using vulkan on windows //we're using vulkan on windows
@ -143,6 +143,14 @@ impl Renderer {
self.size self.size
} }
pub fn size_uvec2(&self) -> glam::UVec2 {
glam::UVec2::new(self.size.width, self.size.height)
}
pub fn size_vec2(&self) -> glam::Vec2 {
glam::Vec2::new(self.size.width as f32, self.size.height as f32)
}
pub fn window(&self) -> &Window { pub fn window(&self) -> &Window {
&self.window &self.window
} }

View file

@ -1,57 +1,43 @@
use bytemuck::{Pod, Zeroable};
use glam::{IVec3, Vec3}; use glam::{IVec3, Vec3};
use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View};
use kubi_shared::{chunk::CHUNK_SIZE, transform::Transform}; use kubi_shared::{chunk::CHUNK_SIZE, transform::Transform};
use wgpu::util::RenderEncoder;
use crate::{ use crate::{
camera::Camera, camera::Camera,
prefabs::TexturePrefabs, prefabs::TexturePrefabs,
settings::GameSettings, settings::GameSettings,
world::{ChunkMeshStorage, ChunkStorage}, world::{ChunkMeshStorage, ChunkStorage},
}; };
use super::{RenderCtx, Renderer}; use super::{camera::{self, CameraUniformBuffer}, depth::DepthTexture, RenderCtx};
#[derive(Clone, Copy, Pod, Zeroable)] mod pipeline;
#[repr(C, packed)] mod vertex;
pub struct ChunkVertex { pub use vertex::ChunkVertex;
pub position: [f32; 3],
pub normal: [f32; 3],
pub uv: [f32; 2],
pub tex_index: u8,
}
impl ChunkVertex {
pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<ChunkVertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![
0 => Float32x3,
1 => Float32x3,
2 => Float32x2,
3 => Uint32,
],
};
}
#[derive(Unique)] #[derive(Unique)]
pub struct TransChunkQueue(pub Vec<IVec3>); pub struct WorldRenderState {
pub pipeline: wgpu::RenderPipeline,
pub trans_chunk_queue: Vec<IVec3>,
}
pub fn init_trans_chunk_queue(storages: AllStoragesView) { pub fn init_world_render_state(storages: AllStoragesView) {
storages.add_unique(TransChunkQueue(Vec::with_capacity(512))); storages.add_unique(WorldRenderState {
pipeline: storages.run(pipeline::init_world_pipeline),
trans_chunk_queue: Vec::with_capacity(512),
})
} }
pub fn draw_world( pub fn draw_world(
ctx: &mut RenderCtx, ctx: &mut RenderCtx,
mut state: UniqueViewMut<WorldRenderState>,
camera_ubo: UniqueView<CameraUniformBuffer>,
depth: UniqueView<DepthTexture>,
textures: UniqueView<TexturePrefabs>, textures: UniqueView<TexturePrefabs>,
camera: View<Camera>,
chunks: UniqueView<ChunkStorage>, chunks: UniqueView<ChunkStorage>,
meshes: NonSendSync<UniqueView<ChunkMeshStorage>>, meshes: NonSendSync<UniqueView<ChunkMeshStorage>>,
transform: View<Transform>, //settings: UniqueView<GameSettings>,
camera: View<Camera>,
settings: UniqueView<GameSettings>,
mut trans_queue: UniqueViewMut<TransChunkQueue>,
) { ) {
let camera = camera.iter().next().expect("No cameras in the scene"); let camera = camera.iter().next().expect("No cameras in the scene");
let camera_matrix = camera.view_matrix * camera.perspective_matrix;
let mut render_pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut render_pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("draw_world"), label: Some("draw_world"),
@ -63,9 +49,21 @@ pub fn draw_world(
store: wgpu::StoreOp::Store, store: wgpu::StoreOp::Store,
}, },
})], })],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
view: &depth.depth_view,
depth_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Clear(1.0),
store: wgpu::StoreOp::Store,
}),
stencil_ops: None,
}),
..Default::default() ..Default::default()
}); });
render_pass.set_pipeline(&state.pipeline);
render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]);
render_pass.set_bind_group(1, &camera_ubo.camera_bind_group, &[]);
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");
@ -85,10 +83,8 @@ pub fn draw_world(
//Draw chunk mesh //Draw chunk mesh
if mesh.main.index.size() > 0 { if mesh.main.index.size() > 0 {
//TODO
render_pass.set_index_buffer(mesh.main.index.slice(..), wgpu::IndexFormat::Uint32); render_pass.set_index_buffer(mesh.main.index.slice(..), wgpu::IndexFormat::Uint32);
render_pass.set_vertex_buffer(0, mesh.main.vertex.slice(..)); render_pass.set_vertex_buffer(0, mesh.main.vertex.slice(..));
render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]);
render_pass.draw_indexed(0..mesh.main.index_len, 0, 0..1); render_pass.draw_indexed(0..mesh.main.index_len, 0, 0..1);
} }

View file

@ -0,0 +1,66 @@
use shipyard::UniqueView;
use crate::{
prefabs::TexturePrefabs,
rendering::{camera::CameraUniformBuffer, depth::DepthTexture, world::ChunkVertex, Renderer}
};
pub fn init_world_pipeline(
ren: UniqueView<Renderer>,
depth: UniqueView<DepthTexture>,
textures: UniqueView<TexturePrefabs>,
camera_ubo: UniqueView<CameraUniformBuffer>,
) -> wgpu::RenderPipeline {
let shader = ren.device().create_shader_module(
wgpu::include_wgsl!("../../../shaders/world.wgsl")
);
let world_pipeline_layout = ren.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("world_pipeline_layout"),
bind_group_layouts: &[
&textures.block_diffuse_bind_group_layout,
&camera_ubo.camera_bind_group_layout,
],
push_constant_ranges: &[],
});
ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("world_pipeline"),
layout: Some(&world_pipeline_layout),
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
compilation_options: wgpu::PipelineCompilationOptions::default(),
targets: &[Some(wgpu::ColorTargetState {
format: ren.surface_config().format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrites::ALL,
})],
}),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
compilation_options: wgpu::PipelineCompilationOptions::default(),
buffers: &[
ChunkVertex::LAYOUT,
],
},
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
strip_index_format: None,
cull_mode: Some(wgpu::Face::Back),
front_face: wgpu::FrontFace::Ccw,
unclipped_depth: false,
polygon_mode: wgpu::PolygonMode::Fill,
conservative: false,
},
depth_stencil: Some(wgpu::DepthStencilState {
format: depth.depth_texture.format(),
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
stencil: wgpu::StencilState::default(),
bias: wgpu::DepthBiasState::default(),
}),
multisample: wgpu::MultisampleState::default(),
multiview: None,
})
}

View file

@ -0,0 +1,23 @@
use bytemuck::{Pod, Zeroable};
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C, packed)]
pub struct ChunkVertex {
pub position: [f32; 3],
pub normal: [f32; 3],
pub uv: [f32; 2],
pub tex_index: u32,
}
impl ChunkVertex {
pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<ChunkVertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![
0 => Float32x3,
1 => Float32x3,
2 => Float32x2,
3 => Uint32,
],
};
}

View file

@ -1,10 +1,10 @@
use hui::{color, element::{container::Container, text::Text, UiElementExt}, layout::Alignment, size}; use hui::{color, element::{container::Container, text::Text, UiElementExt}, layout::Alignment, size};
use shipyard::{NonSendSync, UniqueView, UniqueViewMut}; use shipyard::{NonSendSync, UniqueView, UniqueViewMut};
use crate::{chat::{ChatHistory, ChatMessage}, hui_integration::UiState, rendering::WindowSize}; use crate::{chat::{ChatHistory, ChatMessage}, hui_integration::UiState, rendering::Renderer};
pub fn render_chat( pub fn render_chat(
mut hui: NonSendSync<UniqueViewMut<UiState>>, mut hui: NonSendSync<UniqueViewMut<UiState>>,
size: UniqueView<WindowSize>, ren: UniqueView<Renderer>,
chat: UniqueView<ChatHistory>, chat: UniqueView<ChatHistory>,
) { ) {
let messages = chat.get_messages(); let messages = chat.get_messages();
@ -39,5 +39,5 @@ pub fn render_chat(
.add_child(ui); .add_child(ui);
} }
}) })
.add_root(&mut hui.hui, size.0.as_vec2()); .add_root(&mut hui.hui, ren.size_vec2());
} }

View file

@ -5,7 +5,7 @@ use crate::{
hui_integration::UiState, hui_integration::UiState,
loading_screen::loading_screen_base, loading_screen::loading_screen_base,
networking::{ConnectionRejectionReason, ServerAddress}, networking::{ConnectionRejectionReason, ServerAddress},
rendering::WindowSize, rendering::Renderer,
state::{GameState, NextState} state::{GameState, NextState}
}; };
@ -14,7 +14,7 @@ fn render_connecting_ui(
rejection: Option<UniqueView<ConnectionRejectionReason>>, rejection: Option<UniqueView<ConnectionRejectionReason>>,
join_state: UniqueView<ClientJoinState>, join_state: UniqueView<ClientJoinState>,
mut ui: NonSendSync<UniqueViewMut<UiState>>, mut ui: NonSendSync<UniqueViewMut<UiState>>,
size: UniqueView<WindowSize>, ren: UniqueView<Renderer>,
) { ) {
let text = match (rejection, *join_state) { let text = match (rejection, *join_state) {
(Some(err), _) => { (Some(err), _) => {
@ -32,7 +32,7 @@ fn render_connecting_ui(
Text::new(text) Text::new(text)
.with_text_size(16) .with_text_size(16)
.add_child(ui); .add_child(ui);
}).add_root(&mut ui.hui, size.0.as_vec2()) }).add_root(&mut ui.hui, ren.size_vec2())
} }
fn switch_to_loading_if_connected( fn switch_to_loading_if_connected(

View file

@ -6,7 +6,7 @@ use hui::{
size size
}; };
use shipyard::{AllStoragesViewMut, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; use shipyard::{AllStoragesViewMut, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View};
use crate::{hui_integration::UiState, player::MainPlayer, rendering::WindowSize, settings::GameSettings, world::raycast::LookingAtBlock}; use crate::{hui_integration::UiState, player::MainPlayer, rendering::Renderer, settings::GameSettings, world::raycast::LookingAtBlock};
const CROSSHAIR_SIZE: usize = 9; const CROSSHAIR_SIZE: usize = 9;
const CROSSHAIR: &[u8] = &[ const CROSSHAIR: &[u8] = &[
@ -45,7 +45,7 @@ pub fn init_crosshair_image(storages: AllStoragesViewMut) {
pub fn draw_crosshair( pub fn draw_crosshair(
mut ui: NonSendSync<UniqueViewMut<UiState>>, mut ui: NonSendSync<UniqueViewMut<UiState>>,
crosshair: UniqueView<CrosshairImage>, crosshair: UniqueView<CrosshairImage>,
size: UniqueView<WindowSize>, ren: UniqueView<Renderer>,
player: View<MainPlayer>, player: View<MainPlayer>,
raycast: View<LookingAtBlock>, raycast: View<LookingAtBlock>,
settings: UniqueView<GameSettings>, settings: UniqueView<GameSettings>,
@ -57,6 +57,9 @@ pub fn draw_crosshair(
} }
} }
let size = ren.size_uvec2();
let size_rounded = uvec2(size.x & !1, size.y & !1).as_vec2();
Container::default() Container::default()
.with_size(size!(100%)) .with_size(size!(100%))
.with_align(Alignment::Center) .with_align(Alignment::Center)
@ -66,5 +69,5 @@ pub fn draw_crosshair(
.with_size(size!((CROSSHAIR_SIZE * 2))) .with_size(size!((CROSSHAIR_SIZE * 2)))
.add_child(ui); .add_child(ui);
}) })
.add_root(&mut ui.hui, uvec2(size.0.x & !1, size.0.y & !1).as_vec2()); .add_root(&mut ui.hui, size_rounded);
} }

View file

@ -15,7 +15,7 @@ use crate::{
hui_integration::UiState, hui_integration::UiState,
input::RawKbmInputState, input::RawKbmInputState,
networking::ServerAddress, networking::ServerAddress,
rendering::WindowSize, rendering::Renderer,
state::{GameState, NextState}, state::{GameState, NextState},
world::ChunkStorage, world::ChunkStorage,
}; };
@ -43,7 +43,7 @@ fn render_loading_ui(
addr: Option<UniqueView<ServerAddress>>, addr: Option<UniqueView<ServerAddress>>,
world: UniqueView<ChunkStorage>, world: UniqueView<ChunkStorage>,
mut ui: NonSendSync<UniqueViewMut<UiState>>, mut ui: NonSendSync<UniqueViewMut<UiState>>,
size: UniqueView<WindowSize> ren: UniqueView<Renderer>,
) { ) {
let loaded = world.chunks.iter().fold(0, |acc, (&_, chunk)| { let loaded = world.chunks.iter().fold(0, |acc, (&_, chunk)| {
acc + chunk.desired_state.matches_current(chunk.current_state) as usize acc + chunk.desired_state.matches_current(chunk.current_state) as usize
@ -83,7 +83,7 @@ fn render_loading_ui(
.add_child(ui) .add_child(ui)
}) })
.add_child(ui); .add_child(ui);
}).add_root(&mut ui.hui, size.0.as_vec2()); }).add_root(&mut ui.hui, ren.size_vec2());
} }
fn switch_to_ingame_if_loaded( fn switch_to_ingame_if_loaded(

View file

@ -6,7 +6,7 @@ use hui::{
}; };
use shipyard::{NonSendSync, UniqueView, UniqueViewMut}; use shipyard::{NonSendSync, UniqueView, UniqueViewMut};
use winit::keyboard::KeyCode; use winit::keyboard::KeyCode;
use crate::{hui_integration::UiState, input::RawKbmInputState, rendering::WindowSize, settings::GameSettings}; use crate::{hui_integration::UiState, input::RawKbmInputState, rendering::Renderer, settings::GameSettings};
#[derive(Signal)] #[derive(Signal)]
enum SettingsSignal { enum SettingsSignal {
@ -18,7 +18,7 @@ enum SettingsSignal {
pub fn render_settings_ui( pub fn render_settings_ui(
mut ui: NonSendSync<UniqueViewMut<UiState>>, mut ui: NonSendSync<UniqueViewMut<UiState>>,
size: UniqueView<WindowSize>, ren: UniqueView<Renderer>,
mut settings: UniqueViewMut<GameSettings>, mut settings: UniqueViewMut<GameSettings>,
kbd: UniqueView<RawKbmInputState>, kbd: UniqueView<RawKbmInputState>,
) { ) {
@ -99,7 +99,7 @@ pub fn render_settings_ui(
}) })
.add_child(ui); .add_child(ui);
}) })
.add_root(&mut ui.hui, size.0.as_vec2()); .add_root(&mut ui.hui, ren.size_vec2());
ui.hui.process_signals(|signal: SettingsSignal| match signal { ui.hui.process_signals(|signal: SettingsSignal| match signal {
SettingsSignal::SetRenderDistance(value) => settings.render_distance = value, SettingsSignal::SetRenderDistance(value) => settings.render_distance = value,

View file

@ -1,4 +1,4 @@
use glam::{IVec3, ivec3}; use glam::{ivec3, IVec3, Vec3};
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use kubi_shared::block::{Block, RenderType, Transparency}; use kubi_shared::block::{Block, RenderType, Transparency};
use crate::world::chunk::CHUNK_SIZE; use crate::world::chunk::CHUNK_SIZE;
@ -10,7 +10,7 @@ mod builder;
use data::MeshGenData; use data::MeshGenData;
use builder::{MeshBuilder, CubeFace, DiagonalFace}; use builder::{MeshBuilder, CubeFace, DiagonalFace};
pub fn generate_mesh(data: MeshGenData) -> ( pub fn generate_mesh(position: IVec3, data: MeshGenData) -> (
(Vec<ChunkVertex>, Vec<u32>), (Vec<ChunkVertex>, Vec<u32>),
(Vec<ChunkVertex>, Vec<u32>), (Vec<ChunkVertex>, Vec<u32>),
) { ) {
@ -32,7 +32,7 @@ pub fn generate_mesh(data: MeshGenData) -> (
} }
}; };
let mut builder = MeshBuilder::new(); let mut builder = MeshBuilder::new_with_offset((position * CHUNK_SIZE as i32).as_vec3());
let mut trans_builder = MeshBuilder::new(); let mut trans_builder = MeshBuilder::new();
for x in 0..CHUNK_SIZE as i32 { for x in 0..CHUNK_SIZE as i32 {

View file

@ -1,176 +1,182 @@
use strum::EnumIter; use strum::EnumIter;
use glam::{Vec3, vec3, IVec3, ivec3}; use glam::{ivec3, vec3, IVec3, Vec3};
use std::f32::consts::FRAC_1_SQRT_2; use std::f32::consts::FRAC_1_SQRT_2;
use crate::rendering::world::ChunkVertex; use crate::rendering::world::ChunkVertex;
#[repr(usize)] #[repr(usize)]
#[derive(Clone, Copy, Debug, EnumIter)] #[derive(Clone, Copy, Debug, EnumIter)]
pub enum CubeFace { pub enum CubeFace {
Top = 0, Top = 0,
Front = 4, Front = 4,
Left = 2, Left = 2,
Right = 3, Right = 3,
Back = 1, Back = 1,
Bottom = 5, Bottom = 5,
} }
impl CubeFace { impl CubeFace {
pub const fn normal(self) -> IVec3 { pub const fn normal(self) -> IVec3 {
CUBE_FACE_NORMALS_IVEC3[self as usize] CUBE_FACE_NORMALS_IVEC3[self as usize]
} }
} }
const CUBE_FACE_VERTICES: [[Vec3; 4]; 6] = [ const CUBE_FACE_VERTICES: [[Vec3; 4]; 6] = [
[vec3(0., 1., 0.), vec3(0., 1., 1.), vec3(1., 1., 0.), vec3(1., 1., 1.)], [vec3(0., 1., 0.), vec3(0., 1., 1.), vec3(1., 1., 0.), vec3(1., 1., 1.)],
[vec3(0., 0., 0.), vec3(0., 1., 0.), vec3(1., 0., 0.), vec3(1., 1., 0.)], [vec3(0., 0., 0.), vec3(0., 1., 0.), vec3(1., 0., 0.), vec3(1., 1., 0.)],
[vec3(0., 0., 1.), vec3(0., 1., 1.), vec3(0., 0., 0.), vec3(0., 1., 0.)], [vec3(0., 0., 1.), vec3(0., 1., 1.), vec3(0., 0., 0.), vec3(0., 1., 0.)],
[vec3(1., 0., 0.), vec3(1., 1., 0.), vec3(1., 0., 1.), vec3(1., 1., 1.)], [vec3(1., 0., 0.), vec3(1., 1., 0.), vec3(1., 0., 1.), vec3(1., 1., 1.)],
[vec3(1., 0., 1.), vec3(1., 1., 1.), vec3(0., 0., 1.), vec3(0., 1., 1.)], [vec3(1., 0., 1.), vec3(1., 1., 1.), vec3(0., 0., 1.), vec3(0., 1., 1.)],
[vec3(0., 0., 1.), vec3(0., 0., 0.), vec3(1., 0., 1.), vec3(1., 0., 0.)], [vec3(0., 0., 1.), vec3(0., 0., 0.), vec3(1., 0., 1.), vec3(1., 0., 0.)],
]; ];
const CUBE_FACE_NORMALS_IVEC3: [IVec3; 6] = [ const CUBE_FACE_NORMALS_IVEC3: [IVec3; 6] = [
ivec3( 0, 1, 0), ivec3( 0, 1, 0),
ivec3( 0, 0, -1), ivec3( 0, 0, -1),
ivec3(-1, 0, 0), ivec3(-1, 0, 0),
ivec3( 1, 0, 0), ivec3( 1, 0, 0),
ivec3( 0, 0, 1), ivec3( 0, 0, 1),
ivec3( 0, -1, 0) ivec3( 0, -1, 0)
]; ];
const CUBE_FACE_NORMALS: [Vec3; 6] = [ const CUBE_FACE_NORMALS: [Vec3; 6] = [
vec3(0., 1., 0.), vec3(0., 1., 0.),
vec3(0., 0., -1.), vec3(0., 0., -1.),
vec3(-1.,0., 0.), vec3(-1.,0., 0.),
vec3(1., 0., 0.), vec3(1., 0., 0.),
vec3(0., 0., 1.), vec3(0., 0., 1.),
vec3(0., -1.,0.) vec3(0., -1.,0.)
]; ];
const CUBE_FACE_INDICES: [u32; 6] = [0, 1, 2, 2, 1, 3]; const CUBE_FACE_INDICES: [u32; 6] = [0, 1, 2, 2, 1, 3];
#[repr(usize)] #[repr(usize)]
pub enum DiagonalFace { pub enum DiagonalFace {
RigthZ = 0, RigthZ = 0,
LeftZ = 1, LeftZ = 1,
} }
const CROSS_FACES: [[Vec3; 4]; 2] = [ const CROSS_FACES: [[Vec3; 4]; 2] = [
[ [
vec3(0., 0., 0.), vec3(0., 0., 0.),
vec3(0., 1., 0.), vec3(0., 1., 0.),
vec3(1., 0., 1.), vec3(1., 0., 1.),
vec3(1., 1., 1.), vec3(1., 1., 1.),
], ],
[ [
vec3(0., 0., 1.), vec3(0., 0., 1.),
vec3(0., 1., 1.), vec3(0., 1., 1.),
vec3(1., 0., 0.), vec3(1., 0., 0.),
vec3(1., 1., 0.), vec3(1., 1., 0.),
] ]
]; ];
const CROSS_FACE_NORMALS: [Vec3; 2] = [ const CROSS_FACE_NORMALS: [Vec3; 2] = [
vec3(-FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2), vec3(-FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2),
vec3( FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2), vec3( FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2),
]; ];
const CROSS_FACE_NORMALS_BACK: [Vec3; 2] = [ const CROSS_FACE_NORMALS_BACK: [Vec3; 2] = [
vec3( FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2), vec3( FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2),
vec3(-FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2), vec3(-FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2),
]; ];
const CROSS_FACE_INDICES: [u32; 12] = [ const CROSS_FACE_INDICES: [u32; 12] = [
0, 1, 2, 2, 1, 3, //Front side 0, 1, 2, 2, 1, 3, //Front side
6, 5, 4, 7, 5, 6, //Back side 6, 5, 4, 7, 5, 6, //Back side
]; ];
const UV_COORDS: [[f32; 2]; 4] = [ const UV_COORDS: [[f32; 2]; 4] = [
[0., 0.], [0., 1.],
[0., 1.], [0., 0.],
[1., 0.], [1., 1.],
[1., 1.], [1., 0.],
]; ];
#[derive(Default)] #[derive(Default)]
pub struct MeshBuilder { pub struct MeshBuilder {
vertex_buffer: Vec<ChunkVertex>, offset: Vec3,
index_buffer: Vec<u32>, vertex_buffer: Vec<ChunkVertex>,
idx_counter: u32, index_buffer: Vec<u32>,
} idx_counter: u32,
impl MeshBuilder { }
pub fn new() -> Self { impl MeshBuilder {
Self::default() pub fn new() -> Self {
} Self::default()
}
pub fn add_face(&mut self, face: CubeFace, coord: IVec3, texture: u8) {
let coord = coord.as_vec3(); pub fn new_with_offset(offset: Vec3) -> Self {
let face_index = face as usize; Self { offset, ..Self::new() }
}
//Push vertices
let norm = CUBE_FACE_NORMALS[face_index]; pub fn add_face(&mut self, face: CubeFace, coord: IVec3, texture: u8) {
let vert = CUBE_FACE_VERTICES[face_index]; let coord = coord.as_vec3();
self.vertex_buffer.reserve(4); let face_index = face as usize;
for i in 0..4 {
self.vertex_buffer.push(ChunkVertex { //Push vertices
position: (coord + vert[i]).to_array(), let norm = CUBE_FACE_NORMALS[face_index];
normal: norm.to_array(), let vert = CUBE_FACE_VERTICES[face_index];
uv: UV_COORDS[i], self.vertex_buffer.reserve(4);
tex_index: texture for i in 0..4 {
}); self.vertex_buffer.push(ChunkVertex {
} position: (coord + vert[i] + self.offset).to_array(),
normal: norm.to_array(),
//Push indices uv: UV_COORDS[i],
self.index_buffer.extend_from_slice(&CUBE_FACE_INDICES.map(|x| x + self.idx_counter)); tex_index: texture as u32
});
//Increment idx counter }
self.idx_counter += 4;
} //Push indices
self.index_buffer.extend_from_slice(&CUBE_FACE_INDICES.map(|x| x + self.idx_counter));
pub fn add_diagonal_face(&mut self, coord: IVec3, face_type: DiagonalFace, front_texture: u8, back_texture: u8) {
//Push vertices //Increment idx counter
let face_type = face_type as usize; self.idx_counter += 4;
let vertices = CROSS_FACES[face_type]; }
let normal_front = CROSS_FACE_NORMALS[face_type].to_array();
let normal_back = CROSS_FACE_NORMALS_BACK[face_type].to_array(); pub fn add_diagonal_face(&mut self, coord: IVec3, face_type: DiagonalFace, front_texture: u8, back_texture: u8) {
self.vertex_buffer.reserve(8); //Push vertices
for i in 0..4 { //push front vertices let face_type = face_type as usize;
self.vertex_buffer.push(ChunkVertex { let vertices = CROSS_FACES[face_type];
position: (coord.as_vec3() + vertices[i]).to_array(), let normal_front = CROSS_FACE_NORMALS[face_type].to_array();
normal: normal_front, let normal_back = CROSS_FACE_NORMALS_BACK[face_type].to_array();
uv: UV_COORDS[i], self.vertex_buffer.reserve(8);
tex_index: front_texture for i in 0..4 { //push front vertices
}) self.vertex_buffer.push(ChunkVertex {
} position: (coord.as_vec3() + vertices[i] + self.offset).to_array(),
for i in 0..4 { //push back vertices normal: normal_front,
self.vertex_buffer.push(ChunkVertex { uv: UV_COORDS[i],
position: (coord.as_vec3() + vertices[i]).to_array(), tex_index: front_texture as u32
normal: normal_back, })
uv: UV_COORDS[i], }
tex_index: back_texture for i in 0..4 { //push back vertices
}) self.vertex_buffer.push(ChunkVertex {
} position: (coord.as_vec3() + vertices[i] + self.offset).to_array(),
normal: normal_back,
//Push indices uv: UV_COORDS[i],
self.index_buffer.extend_from_slice(&CROSS_FACE_INDICES.map(|x| x + self.idx_counter)); tex_index: back_texture as u32
})
//Increment idx counter }
self.idx_counter += 8;
} //Push indices
self.index_buffer.extend_from_slice(&CROSS_FACE_INDICES.map(|x| x + self.idx_counter));
pub fn add_model(&mut self, position: Vec3, vertices: &[ChunkVertex], indices: Option<&[u32]>) {
//push vertices //Increment idx counter
self.vertex_buffer.extend(vertices.iter().map(|vertex| { self.idx_counter += 8;
let mut vertex = *vertex; }
vertex.position[0] += position.x;
vertex.position[0] += position.y; //XXX: needs offset supprt
vertex.position[0] += position.z; // pub fn add_model(&mut self, position: Vec3, vertices: &[ChunkVertex], indices: Option<&[u32]>) {
vertex // //push vertices
})); // self.vertex_buffer.extend(vertices.iter().map(|vertex| {
//push indices // let mut vertex = *vertex;
if let Some(indices) = indices { // vertex.position[0] += position.x;
self.index_buffer.extend(indices.iter().map(|x| x + self.idx_counter)); // vertex.position[0] += position.y;
} else { // vertex.position[0] += position.z;
self.index_buffer.extend(0..(self.vertex_buffer.len() as u32)); // vertex
} // }));
//increment idx counter // //push indices
self.idx_counter += vertices.len() as u32; // if let Some(indices) = indices {
} // self.index_buffer.extend(indices.iter().map(|x| x + self.idx_counter));
// } else {
pub fn finish(self) -> (Vec<ChunkVertex>, Vec<u32>) { // self.index_buffer.extend(0..(self.vertex_buffer.len() as u32));
(self.vertex_buffer, self.index_buffer) // }
} // //increment idx counter
} // self.idx_counter += vertices.len() as u32;
// }
pub fn finish(self) -> (Vec<ChunkVertex>, Vec<u32>) {
(self.vertex_buffer, self.index_buffer)
}
}

View file

@ -63,7 +63,7 @@ impl ChunkTaskManager {
let ( let (
(vertices, indices), (vertices, indices),
(trans_vertices, trans_indices), (trans_vertices, trans_indices),
) = generate_mesh(data); ) = generate_mesh(position, data);
ChunkTaskResponse::GeneratedMesh { ChunkTaskResponse::GeneratedMesh {
position, position,
vertices, indices, vertices, indices,