This commit is contained in:
2026-09-09 21:49:25 +02:00
parent 445f1c454c
commit aaaa053349
2 changed files with 148 additions and 28 deletions
+5
View File
@@ -73,6 +73,9 @@ fn unpack_color(color: u32) -> vec4<f32>
@group(0) @binding(5) var<storage, read_write> structure_table_pointer: array<u32>;
@group(0) @binding(6) var<storage, read_write> structure_table_request_buffer: array<atomic<u32>>;
@group(1) @binding(0) var prepass_depth_sampler: sampler;
@group(1) @binding(1) var prepass_depth: texture_2d<f32>;
@vertex
fn chunk(@builtin(vertex_index) index: u32, @location(0) position: vec3<f32>, @location(1) id: u32) -> VertexOutput
{
@@ -357,6 +360,7 @@ struct FragmentOutput {
}
struct FragmentPrepassOutput {
@location(0) depth_prepass: f32, // Equivalent to gl_FragDepth
@builtin(frag_depth) depth: f32, // Equivalent to gl_FragDepth
}
@@ -377,6 +381,7 @@ fn fragment_prepass(in: VertexOutput) -> FragmentPrepassOutput
//frag_out.color = result.color;
frag_out.depth = depth;
frag_out.depth_prepass = depth;
return frag_out;
}
+143 -28
View File
@@ -24,6 +24,7 @@ use wgpu::BindGroupLayout;
use wgpu::BlendState;
use wgpu::Buffer;
use wgpu::BufferUsages;
use wgpu::Color;
use wgpu::ComputePipeline;
use wgpu::Device;
use wgpu::Extent3d;
@@ -36,6 +37,7 @@ use wgpu::PipelineCompilationOptions;
use wgpu::RenderPipeline;
use wgpu::ShaderStages;
use wgpu::Texture;
use wgpu::TextureFormat;
use wgpu::TextureUsages;
use wgpu::TextureView;
use wgpu::util::BufferInitDescriptor;
@@ -85,8 +87,10 @@ struct State
queue: wgpu::Queue,
size: winit::dpi::PhysicalSize<u32>,
surface: wgpu::Surface<'static>,
depth_buffer: (wgpu::Texture, wgpu::TextureView, wgpu::TextureView),
prepass_depth_buffer: (wgpu::Texture, wgpu::TextureView, wgpu::TextureView),
depth_buffer: (wgpu::Texture, wgpu::TextureView),
prepass_depth_buffer: (wgpu::Texture, wgpu::TextureView),
prepass_depth: (wgpu::Texture, wgpu::TextureView),
upsampled_prepass_depth: (wgpu::Texture, wgpu::TextureView),
prepass_downsampling: u32,
upsample_pipeline: ComputePipeline,
surface_format: wgpu::TextureFormat,
@@ -95,6 +99,7 @@ struct State
pipeline: RenderPipeline,
prepass_pipeline: RenderPipeline,
prepass_upsample_bg_layout: BindGroupLayout,
prepass_depth_bind_group_layout: BindGroupLayout,
voxel_cache: Arc<Mutex<VoxelCache<4>>>,
cache_interface: Arc<CacheProducerInterface<4>>,
terrain_generator: Arc<TerrainGenerator<4>>,
@@ -224,16 +229,17 @@ impl State
),
});
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Voxel pipeline layout"),
let prepass_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Voxel pipeline layout"),
bind_group_layouts: &[Some(&voxel_cache.bind_group_layout())],
immediate_size: size_of::<Immediates>() as u32,
});
bind_group_layouts: &[Some(&voxel_cache.bind_group_layout())],
immediate_size: size_of::<Immediates>() as u32,
});
let prepass_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Render pipeline"),
layout: Some(&pipeline_layout),
layout: Some(&prepass_pipeline_layout),
vertex: wgpu::VertexState {
module: &shader_module,
entry_point: Some("chunk"),
@@ -277,7 +283,7 @@ impl State
entry_point: Some("fragment_prepass"),
compilation_options: wgpu::PipelineCompilationOptions::default(),
targets: &[Some(wgpu::ColorTargetState {
format: surface_format,
format: TextureFormat::R32Float,
blend: None,
write_mask: wgpu::ColorWrites::default(),
})],
@@ -286,9 +292,43 @@ impl State
cache: None,
});
let prepass_depth_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("prepass_upsample_bind_group_layout "),
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering),
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float { filterable: false },
view_dimension: wgpu::TextureViewDimension::D2,
multisampled: false,
},
count: None,
},
],
});
let chunk_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Voxel pipeline layout"),
bind_group_layouts: &[
Some(&voxel_cache.bind_group_layout()),
Some(&prepass_depth_bind_group_layout),
],
immediate_size: size_of::<Immediates>() as u32,
});
let chunk_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Render pipeline"),
layout: Some(&pipeline_layout),
layout: Some(&chunk_pipeline_layout),
vertex: wgpu::VertexState {
module: &shader_module,
entry_point: Some("chunk"),
@@ -350,7 +390,7 @@ impl State
visibility: ShaderStages::COMPUTE,
ty: wgpu::BindingType::StorageTexture {
access: wgpu::StorageTextureAccess::ReadOnly,
format: wgpu::TextureFormat::Depth32Float,
format: wgpu::TextureFormat::R32Float,
view_dimension: wgpu::TextureViewDimension::D2,
},
count: None,
@@ -360,7 +400,7 @@ impl State
visibility: ShaderStages::COMPUTE,
ty: wgpu::BindingType::StorageTexture {
access: wgpu::StorageTextureAccess::WriteOnly,
format: wgpu::TextureFormat::Depth24PlusStencil8,
format: wgpu::TextureFormat::R32Float,
view_dimension: wgpu::TextureViewDimension::D2,
},
count: None,
@@ -397,14 +437,14 @@ impl State
{{
for(var oy = 0; oy < {prepass_downsampling}; oy ++)
{{
depth = min(depth, textureLoad(sp + vec<i32>(ox, oy), p, 0));
depth = min(depth, textureLoad(input_tex, sp + vec2<i32>(ox, oy)).x);
}}
}}
textureStore(
output_tex,
dp,
depth
vec4<f32>(depth)
);
}}
"
@@ -430,6 +470,16 @@ impl State
size.width / prepass_downsampling,
size.height / prepass_downsampling,
),
prepass_depth: Self::create_prepass_depth_buffer(
&device,
size.width / prepass_downsampling,
size.height / prepass_downsampling,
),
upsampled_prepass_depth: Self::create_prepass_depth_buffer(
&device,
size.width,
size.height,
),
prepass_downsampling,
upsample_pipeline: prepass_upsample,
queue,
@@ -438,6 +488,7 @@ impl State
pipeline: chunk_pipeline,
prepass_pipeline,
prepass_upsample_bg_layout,
prepass_depth_bind_group_layout,
voxel_cache: Arc::new(Mutex::new(voxel_cache)),
cache_interface: cache_interface.into(),
insertion_debounce: true,
@@ -494,11 +545,36 @@ impl State
}
}
fn create_depth_buffer(
fn create_prepass_depth_buffer(
device: &Device,
width: u32,
height: u32,
) -> (Texture, TextureView, TextureView)
) -> (Texture, TextureView)
{
let texture = device.create_texture(&wgpu::wgt::TextureDescriptor {
label: Some("Prepass Depth buffer"),
size: Extent3d {
width,
height,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::R32Float,
usage: TextureUsages::RENDER_ATTACHMENT
| TextureUsages::TEXTURE_BINDING
| TextureUsages::STORAGE_BINDING,
view_formats: &[wgpu::TextureFormat::R32Float.add_srgb_suffix()],
});
let texture_view = texture.create_view(&wgpu::wgt::TextureViewDescriptor {
label: Some("prepass depth view"),
..Default::default()
});
(texture, texture_view)
}
fn create_depth_buffer(device: &Device, width: u32, height: u32) -> (Texture, TextureView)
{
let texture = device.create_texture(&wgpu::wgt::TextureDescriptor {
label: Some("Depth buffer"),
@@ -518,12 +594,7 @@ impl State
label: Some("depth view"),
..Default::default()
});
let texture_view_upsample = texture.create_view(&wgpu::wgt::TextureViewDescriptor {
label: Some("prepass depth view upsample"),
aspect: wgpu::TextureAspect::DepthOnly,
..Default::default()
});
(texture, texture_view, texture_view_upsample)
(texture, texture_view)
}
fn configure_surface(&self)
@@ -557,6 +628,13 @@ impl State
new_size.width / self.prepass_downsampling,
new_size.height / self.prepass_downsampling,
);
self.prepass_depth = Self::create_prepass_depth_buffer(
&self.device,
new_size.width / self.prepass_downsampling,
new_size.height / self.prepass_downsampling,
);
self.upsampled_prepass_depth =
Self::create_prepass_depth_buffer(&self.device, new_size.width, new_size.height);
}
fn render(&mut self)
@@ -592,6 +670,29 @@ impl State
usage: BufferUsages::COPY_DST | BufferUsages::VERTEX,
});
let prepass_depth_sampler = self.device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("prepass_depth_sampler"),
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
..Default::default()
});
let prepass_depth_bind_group = self.device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("prepass_depth_bind_group"),
layout: &self.prepass_depth_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Sampler(&prepass_depth_sampler),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::TextureView(&self.upsampled_prepass_depth.1),
},
],
});
// Create texture view.
// NOTE: We must handle Timeout because the surface may be unavailable
// (e.g., when the window is occluded on macOS).
@@ -653,11 +754,11 @@ impl State
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&self.prepass_depth_buffer.2),
resource: wgpu::BindingResource::TextureView(&self.prepass_depth.1),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::TextureView(&self.depth_buffer.2),
resource: wgpu::BindingResource::TextureView(&self.upsampled_prepass_depth.1),
},
],
});
@@ -667,9 +768,22 @@ impl State
{
let mut renderpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[],
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &self.prepass_depth.1,
depth_slice: None,
resolve_target: None,
ops: Operations {
load: wgpu::LoadOp::Clear(Color {
r: 1.,
g: 1.,
b: 1.,
a: 1.,
}),
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
view: &self.prepass_depth_buffer.1,
view: &self.depth_buffer.1,
depth_ops: Some(Operations {
load: wgpu::LoadOp::Clear(1.),
store: wgpu::StoreOp::Store,
@@ -687,9 +801,9 @@ impl State
cam_pos: self.camera.position,
frame_timestamp: self.voxel_cache.lock().current_timestamp(),
}];
renderpass.set_immediates(0, unsafe { as_raw_bytes(&imm) });
renderpass.set_pipeline(&self.prepass_pipeline);
renderpass.set_immediates(0, unsafe { as_raw_bytes(&imm) });
renderpass.draw(0..36, 0..(self.instance_count as u32));
// End the renderpass.
@@ -748,14 +862,15 @@ impl State
});
renderpass.set_vertex_buffer(0, instance_buffer.slice(..));
renderpass.set_bind_group(0, Some(&self.voxel_cache.lock().bind_group()), &[]);
renderpass.set_bind_group(1, Some(&prepass_depth_bind_group), &[]);
let imm = [Immediates {
view_proj: self.camera.view_proj(),
cam_pos: self.camera.position,
frame_timestamp: self.voxel_cache.lock().current_timestamp(),
}];
renderpass.set_immediates(0, unsafe { as_raw_bytes(&imm) });
renderpass.set_pipeline(&self.pipeline);
renderpass.set_immediates(0, unsafe { as_raw_bytes(&imm) });
renderpass.draw(0..36, 0..(self.instance_count as u32));
// End the renderpass.