diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl index 185b3bd..ed5d35d 100644 --- a/kubi/shaders/world.wgsl +++ b/kubi/shaders/world.wgsl @@ -45,3 +45,8 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { } return color; } + +@fragment +fn fs_main_trans(in: VertexOutput) -> @location(0) vec4 { + return textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); +} diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 7c5736e..923e8ac 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -77,6 +77,7 @@ pub fn render_master(storages: AllStoragesViewMut) { 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(world::rpass_submit_trans_bundle, &mut data); } storages.run_with_data(kubi_ui_draw, &mut data); diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index eb145c3..772e1bb 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -1,12 +1,12 @@ use glam::Vec3; -use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, View}; +use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; use kubi_shared::chunk::CHUNK_SIZE; use crate::{ camera::Camera, prefabs::GpuPrefabs, world::{ChunkMeshStorage, ChunkStorage}, }; -use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; +use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx, Renderer}; mod pipeline; mod vertex; @@ -15,19 +15,22 @@ pub use vertex::ChunkVertex; #[derive(Unique)] pub struct WorldRenderState { pub pipeline: wgpu::RenderPipeline, - //pub trans_chunk_queue: Vec, + pub pipeline_trans: wgpu::RenderPipeline, + pub trans_bundle: Option, } pub fn init_world_render_state(storages: AllStoragesView) { + let (pipeline, pipeline_trans) = storages.run(pipeline::init_world_pipeline); storages.add_unique(WorldRenderState { - pipeline: storages.run(pipeline::init_world_pipeline), - //trans_chunk_queue: Vec::with_capacity(512), + pipeline, pipeline_trans, + trans_bundle: None, }) } pub fn draw_world( ctx: &mut RenderCtx, - state: UniqueView, + mut state: UniqueViewMut, + renderer: UniqueView, camera_ubo: UniqueView, depth: UniqueView, textures: UniqueView, @@ -63,6 +66,23 @@ pub fn draw_world( render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); render_pass.set_bind_group(1, &camera_ubo.camera_bind_group, &[]); + let mut trans_bundle_used = false; + let mut trans_bundle = renderer.device().create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor { + label: Some("trans_bundle_encoder"), + color_formats: &[Some(renderer.surface_config().format)], + depth_stencil: Some(wgpu::RenderBundleDepthStencil { + format: depth.depth_texture.format(), + depth_read_only: true, + stencil_read_only: true, + }), + sample_count: 1, + multiview: None, + }); + + trans_bundle.set_pipeline(&state.pipeline_trans); + trans_bundle.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); + trans_bundle.set_bind_group(1, &camera_ubo.camera_bind_group, &[]); + for (&position, chunk) in &chunks.chunks { if let Some(key) = chunk.mesh_index { let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); @@ -81,16 +101,61 @@ pub fn draw_world( } //Draw chunk mesh - if mesh.main.index.size() > 0 { + if mesh.main.index_len > 0 { render_pass.set_index_buffer(mesh.main.index.slice(..), wgpu::IndexFormat::Uint32); render_pass.set_vertex_buffer(0, mesh.main.vertex.slice(..)); render_pass.draw_indexed(0..mesh.main.index_len, 0, 0..1); } - //TODO trans chunks - // if mesh.trans_index_buffer.len() > 0 { - // trans_queue.0.push(position); - // } + //Draw transparent chunk mesh + if mesh.trans.index_len > 0 { + trans_bundle_used = true; + trans_bundle.set_index_buffer(mesh.trans.index.slice(..), wgpu::IndexFormat::Uint32); + trans_bundle.set_vertex_buffer(0, mesh.trans.vertex.slice(..)); + trans_bundle.draw_indexed(0..mesh.trans.index_len, 0, 0..1); + } } } + + drop(render_pass); + + if trans_bundle_used { + let bundle = trans_bundle.finish(&wgpu::RenderBundleDescriptor { + label: Some("trans_bundle"), + }); + state.trans_bundle = Some(bundle); + } else { + state.trans_bundle = None; + } +} + +pub fn rpass_submit_trans_bundle( + ctx: &mut RenderCtx, + state: UniqueView, + depth: UniqueView, +) { + let Some(bundle) = state.trans_bundle.as_ref() else { + return + }; + let mut rpass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("rpass_submit_trans_bundle"), + 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.execute_bundles(Some(bundle)); } diff --git a/kubi/src/rendering/world/pipeline.rs b/kubi/src/rendering/world/pipeline.rs index 799fd31..692cb7c 100644 --- a/kubi/src/rendering/world/pipeline.rs +++ b/kubi/src/rendering/world/pipeline.rs @@ -9,7 +9,7 @@ pub fn init_world_pipeline( depth: UniqueView, textures: UniqueView, camera_ubo: UniqueView, -) -> wgpu::RenderPipeline { +) -> (wgpu::RenderPipeline, wgpu::RenderPipeline) { let shader = ren.device().create_shader_module( wgpu::include_wgsl!("../../../shaders/world.wgsl") ); @@ -23,7 +23,7 @@ pub fn init_world_pipeline( push_constant_ranges: &[], }); - ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { + let pipeline_main = ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("world_pipeline"), layout: Some(&world_pipeline_layout), fragment: Some(wgpu::FragmentState { @@ -62,5 +62,48 @@ pub fn init_world_pipeline( }), multisample: wgpu::MultisampleState::default(), multiview: None, - }) + }); + + let pipeline_trans = ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("world_pipeline_trans"), + layout: Some(&world_pipeline_layout), + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "fs_main_trans", + compilation_options: wgpu::PipelineCompilationOptions::default(), + targets: &[Some(wgpu::ColorTargetState { + format: ren.surface_config().format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::COLOR, + })], + }), + 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: None, + 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: false, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState::default(), + }), + multisample: wgpu::MultisampleState::default(), + multiview: None, + }); + + (pipeline_main, pipeline_trans) } diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index 6037473..0033ec8 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -362,9 +362,9 @@ fn process_completed_tasks( let trans_buffer_pair = BufferPair { vertex: vtx_buffer_trans, - vertex_len: vertices.len() as u32, + vertex_len: trans_vertices.len() as u32, index: idx_buffer_trans, - index_len: indices.len() as u32, + index_len: trans_indices.len() as u32, }; let mesh = ChunkMesh { diff --git a/kubi/src/world/mesh.rs b/kubi/src/world/mesh.rs index 3b43116..98d1ec6 100644 --- a/kubi/src/world/mesh.rs +++ b/kubi/src/world/mesh.rs @@ -33,7 +33,7 @@ pub fn generate_mesh(position: IVec3, data: MeshGenData) -> ( }; 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_with_offset((position * CHUNK_SIZE as i32).as_vec3()); for x in 0..CHUNK_SIZE as i32 { for y in 0..CHUNK_SIZE as i32 {