diff --git a/shaders/voxel.wgsl b/shaders/voxel.wgsl index 9b3db90..13e62d3 100644 --- a/shaders/voxel.wgsl +++ b/shaders/voxel.wgsl @@ -2,12 +2,12 @@ struct VertexOutput { @builtin(position) postion: vec4, @location(0) @interpolate(flat) chunk_index: u32, - @location(1) color: vec4, - @location(2) cam_pos: vec3, - @location(3) world_pos: vec3, - @location(4) @interpolate(flat) structure_id: u32, - @location(5) chunk_position: vec3, - @location(6) ndc: vec4 + @location(1) ndc: vec4, + @location(2) color: vec4, + @location(3) cam_pos: vec3, + @location(4) world_pos: vec3, + @location(5) @interpolate(flat) structure_id: u32, + @location(6) chunk_position: vec3, } struct ChunkImmediate @@ -15,6 +15,8 @@ struct ChunkImmediate view_proj: mat4x4, cam_pos: vec3, frame_timestamp: u32, + width: u32, + downsampling_factor: u32, } var constants: ChunkImmediate; @@ -25,7 +27,7 @@ struct CacheChunkObject transform: mat4x4, color: vec4, id: u32, - pointer: u32 + pointer: u32, } @@ -74,8 +76,7 @@ fn unpack_color(color: u32) -> vec4 @group(0) @binding(5) var structure_table_pointer: array; @group(0) @binding(6) var structure_table_request_buffer: array>; -@group(1) @binding(0) var prepass_depth_sampler: sampler; -@group(1) @binding(1) var prepass_depth: texture_2d; +@group(1) @binding(0) var prepass_depth: texture_2d; @vertex fn chunk(@builtin(vertex_index) index: u32, @location(0) position: vec3, @location(1) id: u32) -> VertexOutput @@ -118,13 +119,13 @@ fn chunk(@builtin(vertex_index) index: u32, @location(0) position: vec3, @l var output: VertexOutput; output.postion = output_vertex; + output.ndc = output_vertex / output_vertex.w; output.color = vec4(1.); output.chunk_index = 0; output.cam_pos = constants.cam_pos; output.world_pos = vertex + position; output.structure_id = id; output.chunk_position = position; - output.ndc = output_vertex; //let output = vec4(vertex, 1.0f); return output; @@ -216,9 +217,9 @@ fn new_traverse(ray_dir: vec3, ray_origin: vec3, root_id: u32, dist_of { let max_depth = 5; let dist_offset_voxel = dist_offset * f32(1 << u32(max_depth * 2)); - let fovy_deg = 100. / 1920.; + let fovy_deg = 100. / f32(constants.width); let fovy_rad = (fovy_deg * 3.14) / 180.; - let cone_factor = tan(fovy_rad / 2.) * 2.; + let cone_factor = 1.414 * f32(constants.downsampling_factor) * (tan(fovy_rad / 2.) * 2.); // How many pixels per distance a voxel takes let st_pointer = structure_table_pointer[root_id]; @@ -263,6 +264,7 @@ fn new_traverse(ray_dir: vec3, ray_origin: vec3, root_id: u32, dist_of var inv_ray_dir = 1. / ray_dir; var ray_positive = ray_dir > vec3(0.); var step_dir = select(vec3(-1), vec3(1), ray_positive); + var min_child_size = cone_factor * dist_offset_voxel; for(var iter = 0; iter < 400; iter ++) { @@ -275,9 +277,9 @@ fn new_traverse(ray_dir: vec3, ray_origin: vec3, root_id: u32, dist_of var current_node = dfs_stack[current_depth]; var pointer = structure_pool[current_node].pointers[child_index]; - let min_child_size = (length(vec3(voxel) - pos_origin) + dist_offset_voxel) * cone_factor; + min_child_size = (length(vec3(voxel) - pos_origin) + dist_offset_voxel) * cone_factor; while(node_subdivided(pointer) && - f32(child_size / 4) >= min_child_size + f32(child_size) / 4 > min_child_size ) { if(!node_pointer_valid(pointer) && node_subdivided(pointer)) @@ -311,7 +313,8 @@ fn new_traverse(ray_dir: vec3, ray_origin: vec3, root_id: u32, dist_of var result: HitResult; result.color = unpack_color(color); //result.color = vec4(f32(iter) / 400.); - result.hit_pos = (far_t / f32(1 << u32(max_depth * 2))) * ray_dir + ray_origin; + //result.hit_pos = (far_t / f32(1 << u32(max_depth * 2))) * ray_dir + ray_origin; + result.hit_pos = (far_t * ray_dir + pos_origin) / f32(1 << u32(max_depth * 2)); return result; } @@ -363,16 +366,19 @@ struct FragmentOutput { struct FragmentPrepassOutput { @location(0) depth_prepass: f32, // Equivalent to gl_FragDepth - @builtin(frag_depth) depth: f32, // Equivalent to gl_FragDepth + //@builtin(frag_depth) depth: f32, // Equivalent to gl_FragDepth } -@early_depth_test(less_equal) + +//fn fragment_prepass(in: VertexOutput) -> @location(0) vec4 + +//@early_depth_test(less_equal) @fragment fn fragment_prepass(in: VertexOutput) -> FragmentPrepassOutput { let ray_dir = normalize(in.world_pos - in.cam_pos); - let interp = box_inter(in.cam_pos - in.chunk_position, ray_dir, vec3(0.), vec3(1)); - let ray_origin = (in.cam_pos - in.chunk_position) + ray_dir * (max(0., interp.x)); + let interp = box_inter(in.cam_pos, ray_dir, in.chunk_position + vec3(0.), in.chunk_position + vec3(1)); + let ray_origin = in.cam_pos + ray_dir * max(interp.x, 0.) - in.chunk_position; let result = new_traverse(ray_dir, ray_origin, in.structure_id, length(in.cam_pos - (ray_origin + in.chunk_position))); let clip_pos = constants.view_proj * vec4(result.hit_pos + in.chunk_position, 1.); @@ -380,10 +386,14 @@ fn fragment_prepass(in: VertexOutput) -> FragmentPrepassOutput var frag_out: FragmentPrepassOutput; //frag_out.color = result.color; - //frag_out.color = result.color; + //frag_out.depth_prepass = in.postion.z; + frag_out.depth_prepass = length(ray_origin + in.chunk_position - in.cam_pos); + //frag_out.depth_prepass = interp.x; + //frag_out.depth_prepass = 100.; + //frag_out.depth = depth; - frag_out.depth = depth; - frag_out.depth_prepass = depth; + //frag_out.depth = depth; + //frag_out.depth_prepass = depth; return frag_out; } @@ -391,20 +401,54 @@ fn fragment_prepass(in: VertexOutput) -> FragmentPrepassOutput @fragment fn fragment(in: VertexOutput) -> FragmentOutput { - let surface_depth = in.ndc.z; - let prepass_depth = textureSample(prepass_depth, prepass_depth_sampler, in.ndc.xy).x; + let surface_depth = in.postion.z; + let prepass_depth_sample = textureLoad(prepass_depth, vec2(in.postion.xy), 0).x; + let lin_depth = (100. * 0.01) / (100. - surface_depth * (100. - 0.01)); - if surface_depth <= prepass_depth + if lin_depth < prepass_depth_sample || prepass_depth_sample == -1. { discard; } + //frag_out.color = vec4(2 * 0.01 / (100. + 0.01 - depth * (100. - 0.01))); + let ray_dir = normalize(in.world_pos - in.cam_pos); + let prepass_origin = in.cam_pos + ray_dir * max(prepass_depth_sample - 0.01, 0.); + let interp = box_inter(prepass_origin, ray_dir, in.chunk_position + vec3(0.), in.chunk_position + vec3(1)); + let ray_origin = prepass_origin + ray_dir * max(interp.x, 0.) - in.chunk_position; + //let ray_origin = in.cam_pos + ray_dir * (max(0., lin_depth - 0.1)) - in.chunk_position; + //let ray_origin = in.cam_pos + ray_dir * max(interp.x, 0.) - in.chunk_position; + //let ray_origin = in.cam_pos + ray_dir * max(prepass_depth, 0.) - in.chunk_position; + //let space_ro = in.cam_pos + ray_dir * lin_depth; + //let ray_origin = space_ro - in.chunk_position; + + + let result = new_traverse(ray_dir, ray_origin, in.structure_id, length(in.cam_pos - (ray_origin + in.chunk_position))); + let clip_pos = constants.view_proj * vec4(result.hit_pos + in.chunk_position, 1.); + let depth = clip_pos.z / clip_pos.w; + var frag_out: FragmentOutput; + frag_out.color = result.color; + //frag_out.color = vec4(vec3(prepass_depth_sample) / 100., 1.); + //frag_out.color = vec4(smpl); + //frag_out.color = vec4(ray_origin, 1.); + //frag_out.color = result.color; + //frag_out.color = vec4(ray_origin, 1.); + //frag_out.color = vec4(vec3(lin_depth) / 100., 1.); + frag_out.depth = depth; + return frag_out; + + //return vec4(ray_origin, 1.); + //return frag_out; + //return vec4(interp.y / 10.); +} + +@fragment +fn _fragment(in: VertexOutput) -> FragmentOutput +{ //frag_out.color = vec4(2 * 0.01 / (100. + 0.01 - depth * (100. - 0.01))); let ray_dir = normalize(in.world_pos - in.cam_pos); let interp = box_inter(in.cam_pos - in.chunk_position, ray_dir, vec3(0.), vec3(1)); let ray_origin = (in.cam_pos - in.chunk_position) + ray_dir * (max(0., interp.x)); - let result = new_traverse(ray_dir, ray_origin, in.structure_id, length(in.cam_pos - (ray_origin + in.chunk_position))); let clip_pos = constants.view_proj * vec4(result.hit_pos + in.chunk_position, 1.); let depth = clip_pos.z / clip_pos.w; diff --git a/src/main.rs b/src/main.rs index 6ee1c6f..0ee83d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,7 @@ use wgpu::InstanceDescriptor; use wgpu::InstanceFlags; use wgpu::MemoryBudgetThresholds; use wgpu::Operations; +use wgpu::Origin3d; use wgpu::PipelineCompilationOptions; use wgpu::RenderPipeline; use wgpu::ShaderStages; @@ -125,6 +126,8 @@ struct Immediates view_proj: Mat4, cam_pos: Vec3, frame_timestamp: u32, + width: u32, + downsample_factor: u32, } #[derive(Debug, Clone, Copy, Zeroable, Pod)] @@ -179,8 +182,7 @@ impl State let mut voxel_cache = VoxelCache::<4>::new(100_000, device.clone(), queue.clone()); let cache_interface = CacheProducerInterface::new(1024, &device); - let terrain_generator = - TerrainGenerator::<4>::new(5, "vxls_height.tif", 0.2, "img_low.jpg"); + let terrain_generator = TerrainGenerator::<4>::new(5, "vxls_height.tif", 0.2, "img.jpg"); //let terrain_generator = TerrainGenerator::<4>::new(5, "vxls_height.tif", 0.2, "img.jpg"); // let terrain_generator = TerrainGenerator::<4>::new( // 5, @@ -285,7 +287,7 @@ impl State targets: &[Some(wgpu::ColorTargetState { format: TextureFormat::R32Float, blend: None, - write_mask: wgpu::ColorWrites::default(), + write_mask: wgpu::ColorWrites::all(), })], }), multiview_mask: None, @@ -295,24 +297,16 @@ impl State 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, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: false }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, }, - 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, - }, - ], + count: None, + }], }); let chunk_pipeline_layout = @@ -430,8 +424,7 @@ impl State fn main(@builtin(global_invocation_id) id: vec3) {{ let source_pos = vec2(id.xy); - var depth = 1.; - depth = min(depth, textureLoad(input_tex, source_pos + vec2(0, 0)).x); + var depth = textureLoad(input_tex, source_pos + vec2(0, 0)).x; depth = min(depth, textureLoad(input_tex, source_pos + vec2(1, 0)).x); depth = min(depth, textureLoad(input_tex, source_pos + vec2(0, 1)).x); depth = min(depth, textureLoad(input_tex, source_pos + vec2(1, 1)).x); @@ -569,7 +562,7 @@ impl State usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING | TextureUsages::STORAGE_BINDING, - view_formats: &[wgpu::TextureFormat::R32Float.add_srgb_suffix()], + view_formats: &[wgpu::TextureFormat::R32Float], }); let texture_view = texture.create_view(&wgpu::wgt::TextureViewDescriptor { label: Some("prepass depth view"), @@ -674,27 +667,13 @@ 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.prepass_depth.1), - }, - ], + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&self.upsampled_prepass_depth.1), + }], }); // Create texture view. @@ -778,10 +757,10 @@ impl State resolve_target: None, ops: Operations { load: wgpu::LoadOp::Clear(Color { - r: 1., - g: 1., - b: 1., - a: 1., + r: -1., + g: 0., + b: 0., + a: 0., }), store: wgpu::StoreOp::Store, }, @@ -790,7 +769,7 @@ impl State view: &self.prepass_depth_buffer.1, depth_ops: Some(Operations { load: wgpu::LoadOp::Clear(1.), - store: wgpu::StoreOp::Store, + store: wgpu::StoreOp::Discard, }), stencil_ops: None, }), @@ -804,6 +783,8 @@ impl State view_proj: self.camera.view_proj(), cam_pos: self.camera.position, frame_timestamp: self.voxel_cache.lock().current_timestamp(), + width: self.size.width / self.prepass_downsampling, + downsample_factor: self.prepass_downsampling, }]; renderpass.set_pipeline(&self.prepass_pipeline); @@ -871,6 +852,8 @@ impl State view_proj: self.camera.view_proj(), cam_pos: self.camera.position, frame_timestamp: self.voxel_cache.lock().current_timestamp(), + width: self.size.width, + downsample_factor: 1, }]; renderpass.set_pipeline(&self.pipeline);