diff --git a/Cargo.lock b/Cargo.lock index 1d20dc1..098f774 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1242,6 +1242,7 @@ dependencies = [ "static_assertions", "strum", "tinyset", + "tobj", "uflow", "wgpu", "winapi", @@ -2420,6 +2421,15 @@ dependencies = [ "rand", ] +[[package]] +name = "tobj" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3bd4ba05f29e4c65b6c0c11a58b6465ffa820bac890d76ad407b4e81d8372e8" +dependencies = [ + "ahash", +] + [[package]] name = "toml" version = "0.8.12" diff --git a/assets-src/playermodel1.blend b/assets-src/playermodel1.blend new file mode 100644 index 0000000..4818ac7 Binary files /dev/null and b/assets-src/playermodel1.blend differ diff --git a/assets/playermodel1.obj b/assets/playermodel1.obj new file mode 100644 index 0000000..003e09f --- /dev/null +++ b/assets/playermodel1.obj @@ -0,0 +1,64 @@ +# Blender 4.0.0 Beta +# www.blender.org +o Cube +v 1.000000 1.000000 -1.000000 +v 1.000000 -1.000000 -1.000000 +v 1.000000 1.000000 1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +v -1.000000 -1.000000 -1.000000 +v -1.000000 1.000000 1.000000 +v -1.000000 -1.000000 1.000000 +v 1.000000 1.500000 -1.000000 +v 1.000000 1.500000 1.000000 +v 1.000000 1.000000 -0.333333 +v 1.000000 1.000000 0.333333 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -1.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vt 0.204555 0.291387 +vt 0.043204 0.462923 +vt 0.043204 0.291387 +vt 0.259623 0.207472 +vt 0.024467 0.457472 +vt 0.024467 0.207472 +vt 0.177715 0.183914 +vt 0.010921 0.538561 +vt 0.010921 0.183914 +vt 0.246583 0.218979 +vt 0.011426 0.468979 +vt 0.011426 0.218979 +vt 0.896961 0.811182 +vt 0.168955 0.037222 +vt 0.896961 0.037221 +vt 0.177715 0.538561 +vt 0.010921 0.361238 +vt 0.168955 0.811182 +vt 0.411624 0.811182 +vt 0.204555 0.462923 +vt 0.259623 0.457472 +vt 0.246583 0.468979 +vt 0.177715 0.361238 +vt 0.896961 0.990308 +vt 0.654292 0.811182 +vt 0.168955 0.990308 +s 0 +f 5/1/1 3/2/1 1/3/1 +f 3/4/2 8/5/2 4/6/2 +f 7/7/3 6/8/3 8/9/3 +f 2/10/4 8/11/4 6/12/4 +f 1/13/5 4/14/5 2/15/5 +f 5/16/6 2/17/6 6/8/6 +f 3/18/1 1/13/1 12/19/1 +f 5/1/1 7/20/1 3/2/1 +f 3/4/2 7/21/2 8/5/2 +f 7/7/3 5/16/3 6/8/3 +f 2/10/4 4/22/4 8/11/4 +f 1/13/5 3/18/5 4/14/5 +f 5/16/6 1/23/6 2/17/6 +f 1/13/5 9/24/5 11/25/5 +f 12/19/5 10/26/5 3/18/5 +f 1/13/5 11/25/5 12/19/5 diff --git a/assets/playermodel1.png b/assets/playermodel1.png new file mode 100644 index 0000000..227ee44 Binary files /dev/null and b/assets/playermodel1.png differ diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index eb7b284..b08759c 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -38,7 +38,7 @@ tinyset = "0.4" serde_json = { version = "1.0", optional = true } #only used for `generate_visualizer_data` rand = { version = "0.8", features = ["alloc", "small_rng"]} atomic = "0.6" - +tobj = "4.0" [target.'cfg(target_os = "android")'.dependencies] android-activity = "0.6" diff --git a/kubi/shaders/entities.wgsl b/kubi/shaders/entities.wgsl new file mode 100644 index 0000000..83eb27e --- /dev/null +++ b/kubi/shaders/entities.wgsl @@ -0,0 +1,40 @@ +struct CameraUniform { + view_proj: mat4x4, +}; + +@group(1) @binding(0) +var camera: CameraUniform; + +struct VertexInput { + @location(0) uv: vec2, + @location(1) position: vec3, + @location(2) normal: vec3, +} + +struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) uv: vec2, + @location(1) normal: vec3, +}; + +@vertex +fn vs_main( + in: VertexInput, +) -> VertexOutput { + var out: VertexOutput; + out.clip_position = camera.view_proj * vec4(in.position, 1.0); + out.uv = in.uv; + out.normal = in.normal; + return out; +} + +@group(0) @binding(0) +var t_diffuse: texture_2d; + +@group(0) @binding(1) +var s_diffuse: sampler; + +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4 { + return textureSample(t_diffuse, s_diffuse, in.uv); +} diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index 9932999..2fb3514 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -1,11 +1,35 @@ -use std::{io::{BufReader, Read}, path::Path}; +use std::{io::{BufReader, Read}, path::{Path, PathBuf}}; +use bytemuck::{Pod, Zeroable}; use hui::text::FontHandle; use shipyard::{AllStoragesView, NonSendSync, Unique, UniqueView, UniqueViewMut}; use kubi_shared::block::BlockTexture; -use crate::{filesystem::AssetManager, hui_integration::UiState, rendering::Renderer}; +use crate::{filesystem::AssetManager, hui_integration::UiState, rendering::{BufferPair, Renderer}}; -mod texture; -use texture::load_texture2darray_prefab; +//TODO move to rendering module + +mod loader; +use loader::{load_texture2darray_prefab, load_texture2d_prefab, load_obj_prefab}; + +#[derive(Clone, Copy, Default, Pod, Zeroable)] +#[repr(C, packed)] +pub struct ModelVertex { + pub tex_coords: [f32; 2], + pub position: [f32; 3], + pub _padding: u32, + pub normal: [f32; 3], +} + +impl ModelVertex { + pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![ + 0 => Float32x2, + 1 => Float32x3, + 2 => Float32x3, + ], + }; +} pub trait AssetPaths { fn file_name(self) -> &'static str; @@ -36,10 +60,14 @@ impl AssetPaths for BlockTexture { } #[derive(Unique)] -pub struct TexturePrefabs { +pub struct GpuPrefabs { pub block_diffuse_texture: wgpu::Texture, pub block_diffuse_bind_group_layout: wgpu::BindGroupLayout, pub block_diffuse_bind_group: wgpu::BindGroup, + pub player_model_diffuse_texture: wgpu::Texture, + pub player_model_diffuse_bind_group_layout: wgpu::BindGroupLayout, + pub player_model_diffuse_bind_group: wgpu::BindGroup, + pub player_model: BufferPair, } #[derive(Unique)] @@ -110,10 +138,69 @@ pub fn load_prefabs( } ] }); - storages.add_unique_non_send_sync(TexturePrefabs { + + let player_model_diffuse_texture = load_texture2d_prefab(&renderer, &assman, &PathBuf::from("playermodel1.png")); + let player_model_diffuse_view = player_model_diffuse_texture.create_view(&wgpu::TextureViewDescriptor { + label: Some("player_model_texture_view"), + ..Default::default() + }); + let player_model_diffuse_sampler = renderer.device().create_sampler(&wgpu::SamplerDescriptor { + label: Some("player_model_sampler"), + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }); + let player_model_diffuse_bind_group_layout = renderer.device() + .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("player_model_bind_group_layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + } + ] + }); + let player_model_diffuse_bind_group = renderer.device().create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("player_model_bind_group"), + layout: &player_model_diffuse_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&player_model_diffuse_view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&player_model_diffuse_sampler), + } + ] + }); + + let player_model = load_obj_prefab(&renderer, &assman, &PathBuf::from("playermodel1.obj")); + + storages.add_unique_non_send_sync(GpuPrefabs { block_diffuse_texture, block_diffuse_bind_group_layout, block_diffuse_bind_group, + player_model_diffuse_texture, + player_model_diffuse_bind_group_layout, + player_model_diffuse_bind_group, + player_model, }); log::info!("Loading the UI stuff..."); diff --git a/kubi/src/prefabs/loader.rs b/kubi/src/prefabs/loader.rs new file mode 100644 index 0000000..f32834b --- /dev/null +++ b/kubi/src/prefabs/loader.rs @@ -0,0 +1,164 @@ +use glam::UVec2; +use strum::IntoEnumIterator; +use rayon::prelude::*; +use wgpu::util::{DeviceExt, TextureDataOrder}; +use std::{io::{BufReader, Read}, path::{Path, PathBuf}}; +use crate::{filesystem::AssetManager, prefabs::ModelVertex, rendering::{BufferPair, Renderer}}; +use super::AssetPaths; + +pub fn load_texture2darray_prefab( + renderer: &Renderer, + assman: &AssetManager, + directory: PathBuf, +) -> wgpu::Texture { + log::info!("started loading {}", directory.as_os_str().to_str().unwrap()); + + //Load raw images + let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); + let raw_images: Vec<(Vec, UVec2)> = tex_files.par_iter().map(|&file_name| { + log::info!("loading texture {}", file_name); + + //Get path to the image and open the file + let reader = { + let path = directory.join(file_name); + BufReader::new(assman.open_asset(&path).expect("Failed to open texture file")) + }; + + //Parse image data + let (image_data, dimensions) = { + let image = image::load( + reader, + image::ImageFormat::Png + ).unwrap().to_rgba8(); + let dimensions = image.dimensions(); + (image.into_raw(), dimensions) + }; + (image_data, UVec2::from(dimensions)) + }).collect(); + + assert!(!raw_images.is_empty(), "no images loaded"); + //TODO: check same size + + log::info!("done loading texture files, uploading to the gpu"); + + let size = raw_images[0].1; + let layers = raw_images.len() as u32; + + //Concat data into a single vec + let mut data = Vec::with_capacity((size.x * size.y * layers * 4) as usize); + for (layer_data, _) in raw_images { + data.extend_from_slice(&layer_data); + } + + //Upload images to the GPU + let label = format!("texture2darray_prefab_{}", directory.as_os_str().to_str().unwrap()); + let desc = &wgpu::TextureDescriptor { + label: Some(&label), + size: wgpu::Extent3d { + width: size.x, + height: size.y, + depth_or_array_layers: layers, + }, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + mip_level_count: 1, + sample_count: 1, + view_formats: &[], + }; + + renderer.device().create_texture_with_data( + renderer.queue(), + desc, + TextureDataOrder::MipMajor, + &data + ) +} + +pub fn load_texture2d_prefab( + renderer: &Renderer, + assman: &AssetManager, + path: &Path, +) -> wgpu::Texture { + let image = image::load( + BufReader::new(assman.open_asset(path).expect("Failed to open texture file")), + image::ImageFormat::Png + ).unwrap().to_rgba8(); + let size = image.dimensions(); + let data = image.into_raw(); + + let label = format!("texture2d_prefab_{}", path.file_name().unwrap().to_str().unwrap()); + let desc = wgpu::TextureDescriptor { + label: Some(&label), + size: wgpu::Extent3d { + width: size.0, + height: size.1, + depth_or_array_layers: 1, + }, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + mip_level_count: 1, + sample_count: 1, + view_formats: &[], + }; + + renderer.device().create_texture_with_data( + renderer.queue(), + &desc, + TextureDataOrder::MipMajor, + &data + ) +} + +pub fn load_obj_prefab( + renderer: &Renderer, + assman: &AssetManager, + path: &Path, +) -> BufferPair { + let mut reader = BufReader::new( + assman.open_asset(path).expect("Failed to open texture file") + ); + + let (model, _) = tobj::load_obj_buf( + &mut reader, + &tobj::GPU_LOAD_OPTIONS, + |_| unimplemented!() + ).unwrap(); + + assert_eq!(model.len(), 1, "only single model supported at the moment, sowwy :3"); + let mesh = &model[0].mesh; + debug_assert!(mesh.normal_indices.is_empty() && mesh.texcoord_indices.is_empty(), "forgor single_index"); + + let tex_coords = bytemuck::cast_slice::(&mesh.texcoords); + let positions = bytemuck::cast_slice::(&mesh.positions); + let normals = bytemuck::cast_slice::(&mesh.normals); + + let vertex_buffer: Vec<_> = (0..positions.len()).map(|i| { + ModelVertex { + tex_coords: [tex_coords[i][0], 1. - tex_coords[i][1]], + position: positions[i], + _padding: 0, + normal: normals[i], + } + }).collect(); + + let vertex_buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("obj_vertex_buffer"), + contents: bytemuck::cast_slice(&vertex_buffer), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::VERTEX, + }); + + let index_buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("obj_index_buffer"), + contents: bytemuck::cast_slice(&mesh.indices), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::INDEX, + }); + + BufferPair { + vertex: vertex_buffer, + vertex_len: positions.len() as u32, + index: index_buffer, + index_len: mesh.indices.len() as u32, + } +} diff --git a/kubi/src/prefabs/texture.rs b/kubi/src/prefabs/texture.rs deleted file mode 100644 index caa23dd..0000000 --- a/kubi/src/prefabs/texture.rs +++ /dev/null @@ -1,75 +0,0 @@ -use glam::UVec2; -use strum::IntoEnumIterator; -use rayon::prelude::*; -use wgpu::util::{DeviceExt, TextureDataOrder}; -use std::{io::BufReader, path::PathBuf}; -use crate::{filesystem::AssetManager, rendering::Renderer}; -use super::AssetPaths; - -pub fn load_texture2darray_prefab( - renderer: &Renderer, - assman: &AssetManager, - directory: PathBuf, -) -> wgpu::Texture { - log::info!("started loading {}", directory.as_os_str().to_str().unwrap()); - - //Load raw images - let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); - let raw_images: Vec<(Vec, UVec2)> = tex_files.par_iter().map(|&file_name| { - log::info!("loading texture {}", file_name); - - //Get path to the image and open the file - let reader = { - let path = directory.join(file_name); - BufReader::new(assman.open_asset(&path).expect("Failed to open texture file")) - }; - - //Parse image data - let (image_data, dimensions) = { - let image = image::load( - reader, - image::ImageFormat::Png - ).unwrap().to_rgba8(); - let dimensions = image.dimensions(); - (image.into_raw(), dimensions) - }; - (image_data, UVec2::from(dimensions)) - }).collect(); - - assert!(!raw_images.is_empty(), "no images loaded"); - //TODO: check same size - - log::info!("done loading texture files, uploading to the gpu"); - - let size = raw_images[0].1; - let layers = raw_images.len() as u32; - - //Concat data into a single vec - let mut data = Vec::with_capacity((size.x * size.y * layers * 4) as usize); - for (layer_data, _) in raw_images { - data.extend_from_slice(&layer_data); - } - - //Upload images to the GPU - let desc = &wgpu::TextureDescriptor { - label: Some("block_diffuse_texture"), - size: wgpu::Extent3d { - width: size.x, - height: size.y, - depth_or_array_layers: layers, - }, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, - mip_level_count: 1, - sample_count: 1, - view_formats: &[], - }; - - renderer.device().create_texture_with_data( - renderer.queue(), - desc, - TextureDataOrder::MipMajor, - &data - ) -} diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index f3342ab..4b8c2f9 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -6,6 +6,7 @@ use crate::{events::WindowResizedEvent, hui_integration::kubi_ui_draw, state::is mod renderer; mod primitives; mod selection_box; +mod entities; pub use renderer::Renderer; pub mod background; @@ -35,8 +36,9 @@ pub fn init_rendering() -> Workload { ( depth::init_depth_texture, camera_uniform::init_camera_uniform_buffer, - world::init_world_render_state, //req: depth, camera primitives::init_primitives, + world::init_world_render_state, //req: depth, camera + entities::init_entities_render_state, //req: depth, camera selection_box::init_selection_box_render_state, //req: depth, camera, primitives ).into_sequential_workload() } @@ -65,7 +67,6 @@ pub fn render_master(storages: AllStoragesViewMut) { let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default()); let mut data = RenderCtx { - //renderer: &renderer, encoder: &mut encoder, surface_view: &surface_view, }; @@ -74,8 +75,8 @@ pub fn render_master(storages: AllStoragesViewMut) { if storages.run(is_ingame) { storages.run_with_data(world::draw_world, &mut data); storages.run_with_data(selection_box::draw_selection_box, &mut data); + storages.run_with_data(entities::render_entities, &mut data); } - storages.run_with_data(kubi_ui_draw, &mut data); renderer.queue().submit([encoder.finish()]); diff --git a/kubi/src/rendering/entities.rs b/kubi/src/rendering/entities.rs index 3282cc9..a91e2bb 100644 --- a/kubi/src/rendering/entities.rs +++ b/kubi/src/rendering/entities.rs @@ -1,58 +1,69 @@ -// use shipyard::{NonSendSync, UniqueViewMut, UniqueView, View, IntoIter, IntoWithId}; -// use glium::{DepthTest, Depth, PolygonMode, BackfaceCullingMode, DrawParameters, Surface, uniform}; -// use kubi_shared::{entity::Entity, transform::Transform}; -// use crate::{ -// prefabs::ColoredShaderPrefab, -// camera::Camera, -// settings::GameSettings -// }; -// use super::{ -// RenderTarget, -// primitives::cube::CenteredCubePrimitive -// }; +use shipyard::{AllStoragesView, IntoIter, IntoWithId, Unique, UniqueView, View}; +use kubi_shared::{entity::Entity, transform::Transform}; +use crate::{ + camera::Camera, prefabs::GpuPrefabs, settings::GameSettings +}; -// // TODO: entity models -// pub fn render_entities( -// mut target: NonSendSync>, -// buffers: NonSendSync>, -// program: NonSendSync>, -// camera: View, -// settings: UniqueView, -// entities: View, -// transform: View, -// ) { -// let (camera_id, camera) = camera.iter().with_id().next().expect("No cameras in the scene"); +use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; -// 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() -// }; -// let view = camera.view_matrix.to_cols_array_2d(); -// let perspective = camera.perspective_matrix.to_cols_array_2d(); +mod pipeline; -// 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 } +#[derive(Unique)] +pub struct EntitiesRenderState { + pub pipeline: wgpu::RenderPipeline, +} -// //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(); -// } -// } +pub fn init_entities_render_state(storages: AllStoragesView) { + storages.add_unique(EntitiesRenderState { + pipeline: storages.run(pipeline::init_entities_pipeline), + }); +} + +// TODO: entity models +pub fn render_entities( + ctx: &mut RenderCtx, + state: UniqueView, + depth: UniqueView, + prefabs: UniqueView, + camera_ubo: UniqueView, + camera: View, + settings: UniqueView, + entities: View, + transform: View, +) { + let mut rpass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("rpass_draw_entities"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: ctx.surface_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &depth.depth_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }), + stencil_ops: None, + }), + ..Default::default() + }); + + rpass.set_pipeline(&state.pipeline); + rpass.set_bind_group(0, &prefabs.player_model_diffuse_bind_group, &[]); + rpass.set_bind_group(1, &camera_ubo.camera_bind_group, &[]); + rpass.set_vertex_buffer(0, prefabs.player_model.vertex.slice(..)); + rpass.set_index_buffer(prefabs.player_model.index.slice(..), wgpu::IndexFormat::Uint32); + rpass.draw_indexed(0..prefabs.player_model.index_len, 0, 0..1); + + // let (camera_id, _camera) = camera.iter().with_id().next().expect("No cameras in the scene"); + + // 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 } + + // } +} diff --git a/kubi/src/rendering/entities/pipeline.rs b/kubi/src/rendering/entities/pipeline.rs new file mode 100644 index 0000000..bb963ec --- /dev/null +++ b/kubi/src/rendering/entities/pipeline.rs @@ -0,0 +1,61 @@ +use shipyard::UniqueView; +use wgpu::include_wgsl; +use crate::{prefabs::{GpuPrefabs, ModelVertex}, rendering::{camera_uniform::CameraUniformBuffer, Renderer}}; + +pub fn init_entities_pipeline( + renderer: UniqueView, + prefabs: UniqueView, + camera_ubo: UniqueView, +) -> wgpu::RenderPipeline { + let module = renderer.device().create_shader_module(include_wgsl!("../../../shaders/entities.wgsl")); + + let pipeline_layout = renderer.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("entities_pipeline_layout"), + bind_group_layouts: &[ + &prefabs.player_model_diffuse_bind_group_layout, + &camera_ubo.camera_bind_group_layout, + ], + push_constant_ranges: &[], + }); + + renderer.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("entities_pipeline"), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &module, + compilation_options: wgpu::PipelineCompilationOptions::default(), + entry_point: "vs_main", + buffers: &[ + ModelVertex::LAYOUT, + ], + }, + fragment: Some(wgpu::FragmentState { + module: &module, + compilation_options: wgpu::PipelineCompilationOptions::default(), + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format: renderer.surface_config().format, + blend: Some(wgpu::BlendState::REPLACE), + write_mask: wgpu::ColorWrites::COLOR, + })], + }), + 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, + conservative: false, + unclipped_depth: false, + }, + depth_stencil: Some(wgpu::DepthStencilState { + format: wgpu::TextureFormat::Depth32Float, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + bias: wgpu::DepthBiasState::default(), + stencil: wgpu::StencilState::default(), + }), + multisample: wgpu::MultisampleState::default(), + multiview: None, + }) +} diff --git a/kubi/src/rendering/selection_box.rs b/kubi/src/rendering/selection_box.rs index d33b4c7..ae6a0ce 100644 --- a/kubi/src/rendering/selection_box.rs +++ b/kubi/src/rendering/selection_box.rs @@ -49,7 +49,7 @@ pub fn draw_selection_box( view: &depth.depth_view, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Load, - store: wgpu::StoreOp::Discard, + store: wgpu::StoreOp::Store, }), stencil_ops: None, }), diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 5e57781..eb145c3 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -3,7 +3,7 @@ use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, View} use kubi_shared::chunk::CHUNK_SIZE; use crate::{ camera::Camera, - prefabs::TexturePrefabs, + prefabs::GpuPrefabs, world::{ChunkMeshStorage, ChunkStorage}, }; use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; @@ -30,7 +30,7 @@ pub fn draw_world( state: UniqueView, camera_ubo: UniqueView, depth: UniqueView, - textures: UniqueView, + textures: UniqueView, camera: View, chunks: UniqueView, meshes: NonSendSync>, diff --git a/kubi/src/rendering/world/pipeline.rs b/kubi/src/rendering/world/pipeline.rs index 9a63f65..799fd31 100644 --- a/kubi/src/rendering/world/pipeline.rs +++ b/kubi/src/rendering/world/pipeline.rs @@ -1,13 +1,13 @@ use shipyard::UniqueView; use crate::{ - prefabs::TexturePrefabs, + prefabs::GpuPrefabs, rendering::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, world::ChunkVertex, Renderer} }; pub fn init_world_pipeline( ren: UniqueView, depth: UniqueView, - textures: UniqueView, + textures: UniqueView, camera_ubo: UniqueView, ) -> wgpu::RenderPipeline { let shader = ren.device().create_shader_module(