Fix noisy depth values in flat mode.

This commit is contained in:
Robin KAY 2023-11-02 00:33:09 +00:00
parent 3740766157
commit 613e1ddde7
4 changed files with 17 additions and 48 deletions

View File

@ -3,9 +3,7 @@ use bevy::prelude::*;
use bevy::render::render_asset::RenderAssets; use bevy::render::render_asset::RenderAssets;
use bevy::render::render_phase::{DrawFunctions, RenderPhase, SetItemPipeline}; use bevy::render::render_phase::{DrawFunctions, RenderPhase, SetItemPipeline};
use bevy::render::render_resource::{PipelineCache, SpecializedMeshPipelines}; use bevy::render::render_resource::{PipelineCache, SpecializedMeshPipelines};
use bevy::render::renderer::RenderAdapterInfo;
use bevy::render::view::{ExtractedView, RenderLayers}; use bevy::render::view::{ExtractedView, RenderLayers};
use wgpu_types::Backend;
use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline}; use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline};
use crate::pipeline::{OutlinePipeline, PassType, PipelineKey}; use crate::pipeline::{OutlinePipeline, PassType, PipelineKey};
@ -34,7 +32,6 @@ pub(crate) fn queue_outline_stencil_mesh(
mut pipelines: ResMut<SpecializedMeshPipelines<OutlinePipeline>>, mut pipelines: ResMut<SpecializedMeshPipelines<OutlinePipeline>>,
pipeline_cache: Res<PipelineCache>, pipeline_cache: Res<PipelineCache>,
render_meshes: Res<RenderAssets<Mesh>>, render_meshes: Res<RenderAssets<Mesh>>,
adapter_info: Res<RenderAdapterInfo>,
material_meshes: Query<( material_meshes: Query<(
Entity, Entity,
&Handle<Mesh>, &Handle<Mesh>,
@ -55,8 +52,7 @@ pub(crate) fn queue_outline_stencil_mesh(
let base_key = PipelineKey::new() let base_key = PipelineKey::new()
.with_msaa(*msaa) .with_msaa(*msaa)
.with_pass_type(PassType::Stencil) .with_pass_type(PassType::Stencil);
.with_opengl_workaround(adapter_info.0.backend == Backend::Gl);
for (view, mut stencil_phase, view_mask) in views.iter_mut() { for (view, mut stencil_phase, view_mask) in views.iter_mut() {
let rangefinder = view.rangefinder3d(); let rangefinder = view.rangefinder3d();
@ -112,7 +108,6 @@ pub(crate) fn queue_outline_volume_mesh(
mut pipelines: ResMut<SpecializedMeshPipelines<OutlinePipeline>>, mut pipelines: ResMut<SpecializedMeshPipelines<OutlinePipeline>>,
pipeline_cache: Res<PipelineCache>, pipeline_cache: Res<PipelineCache>,
render_meshes: Res<RenderAssets<Mesh>>, render_meshes: Res<RenderAssets<Mesh>>,
adapter_info: Res<RenderAdapterInfo>,
material_meshes: Query<( material_meshes: Query<(
Entity, Entity,
&Handle<Mesh>, &Handle<Mesh>,
@ -137,9 +132,7 @@ pub(crate) fn queue_outline_volume_mesh(
.get_id::<DrawOutline>() .get_id::<DrawOutline>()
.unwrap(); .unwrap();
let base_key = PipelineKey::new() let base_key = PipelineKey::new().with_msaa(*msaa);
.with_msaa(*msaa)
.with_opengl_workaround(adapter_info.0.backend == Backend::Gl);
for (view, mut opaque_phase, mut transparent_phase, view_mask) in views.iter_mut() { for (view, mut opaque_phase, mut transparent_phase, view_mask) in views.iter_mut() {
let view_mask = view_mask.copied().unwrap_or_default(); let view_mask = view_mask.copied().unwrap_or_default();

View File

@ -1,6 +1,6 @@
struct FragmentOutput { struct FragmentOutput {
@location(0) colour: vec4<f32>, @location(0) colour: vec4<f32>,
#ifdef OPENGL_WORKAROUND #ifdef FLAT_DEPTH
@builtin(frag_depth) frag_depth: f32, @builtin(frag_depth) frag_depth: f32,
#endif #endif
}; };
@ -16,8 +16,8 @@ var<uniform> fstage: OutlineFragmentUniform;
#endif #endif
@fragment @fragment
#ifdef OPENGL_WORKAROUND #ifdef FLAT_DEPTH
fn fragment(@location(0) normalised_depth: f32) -> FragmentOutput { fn fragment(@location(0) @interpolate(flat) flat_depth: f32) -> FragmentOutput {
#else #else
fn fragment() -> FragmentOutput { fn fragment() -> FragmentOutput {
#endif #endif
@ -25,8 +25,8 @@ fn fragment() -> FragmentOutput {
#ifdef VOLUME #ifdef VOLUME
out.colour = fstage.colour; out.colour = fstage.colour;
#endif #endif
#ifdef OPENGL_WORKAROUND #ifdef FLAT_DEPTH
out.frag_depth = normalised_depth; out.frag_depth = flat_depth;
#endif #endif
return out; return out;
} }

View File

@ -20,8 +20,8 @@ struct Vertex {
struct VertexOutput { struct VertexOutput {
@builtin(position) position: vec4<f32>, @builtin(position) position: vec4<f32>,
#ifdef OPENGL_WORKAROUND #ifdef FLAT_DEPTH
@location(0) normalised_depth: f32, @location(0) @interpolate(flat) flat_depth: f32,
#endif #endif
}; };
@ -93,11 +93,6 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
let model = mesh.model; let model = mesh.model;
#endif #endif
let clip_pos = view.view_proj * (model * vec4<f32>(vertex.position, 1.0)); let clip_pos = view.view_proj * (model * vec4<f32>(vertex.position, 1.0));
#ifdef FLAT_DEPTH
let out_z = model_origin_z(vstage.origin, view.view_proj) * clip_pos.w;
#else
let out_z = clip_pos.z;
#endif
#ifdef OFFSET_ZERO #ifdef OFFSET_ZERO
let out_xy = clip_pos.xy; let out_xy = clip_pos.xy;
#else #else
@ -106,9 +101,9 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
let out_xy = clip_pos.xy + ndc_delta; let out_xy = clip_pos.xy + ndc_delta;
#endif #endif
var out: VertexOutput; var out: VertexOutput;
out.position = vec4<f32>(out_xy, out_z, clip_pos.w); out.position = vec4<f32>(out_xy, clip_pos.zw);
#ifdef OPENGL_WORKAROUND #ifdef FLAT_DEPTH
out.normalised_depth = 0.5 + 0.5 * (out_z / clip_pos.w); out.flat_depth = model_origin_z(vstage.origin, view.view_proj);
#endif #endif
return out; return out;
} }

View File

@ -56,8 +56,7 @@ impl PipelineKey {
depth_mode_int, set_depth_mode_int: 12, 11; depth_mode_int, set_depth_mode_int: 12, 11;
pub offset_zero, set_offset_zero: 13; pub offset_zero, set_offset_zero: 13;
pub hdr_format, set_hdr_format: 14; pub hdr_format, set_hdr_format: 14;
pub opengl_workaround, set_opengl_workaround: 15; pub morph_targets, set_morph_targets: 15;
pub morph_targets, set_morph_targets: 16;
} }
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
@ -132,11 +131,6 @@ impl PipelineKey {
self self
} }
pub(crate) fn with_opengl_workaround(mut self, opengl_workaround: bool) -> Self {
self.set_opengl_workaround(opengl_workaround);
self
}
pub(crate) fn with_morph_targets(mut self, morph_targets: bool) -> Self { pub(crate) fn with_morph_targets(mut self, morph_targets: bool) -> Self {
self.set_morph_targets(morph_targets); self.set_morph_targets(morph_targets);
self self
@ -269,7 +263,9 @@ impl SpecializedMeshPipeline for OutlinePipeline {
bind_layouts.push(self.outline_view_bind_group_layout.clone()); bind_layouts.push(self.outline_view_bind_group_layout.clone());
let cull_mode; let cull_mode;
if key.depth_mode() == DepthMode::Flat { if key.depth_mode() == DepthMode::Flat {
vertex_defs.push(ShaderDefVal::from("FLAT_DEPTH")); let val = ShaderDefVal::from("FLAT_DEPTH");
vertex_defs.push(val.clone());
fragment_defs.push(val);
cull_mode = Some(Face::Back); cull_mode = Some(Face::Back);
} else if key.pass_type() == PassType::Stencil { } else if key.pass_type() == PassType::Stencil {
cull_mode = Some(Face::Back); cull_mode = Some(Face::Back);
@ -311,11 +307,6 @@ impl SpecializedMeshPipeline for OutlinePipeline {
bind_layouts.push(self.outline_volume_bind_group_layout.clone()); bind_layouts.push(self.outline_volume_bind_group_layout.clone());
} }
} }
if key.opengl_workaround() {
let val = ShaderDefVal::from("OPENGL_WORKAROUND");
vertex_defs.push(val.clone());
fragment_defs.push(val);
}
let buffers = vec![layout.get_layout(&buffer_attrs)?]; let buffers = vec![layout.get_layout(&buffer_attrs)?];
Ok(RenderPipelineDescriptor { Ok(RenderPipelineDescriptor {
vertex: VertexState { vertex: VertexState {
@ -345,17 +336,7 @@ impl SpecializedMeshPipeline for OutlinePipeline {
depth_write_enabled: true, depth_write_enabled: true,
depth_compare: CompareFunction::Greater, depth_compare: CompareFunction::Greater,
stencil: StencilState::default(), stencil: StencilState::default(),
bias: if key.depth_mode() == DepthMode::Flat && key.pass_type() == PassType::Stencil bias: DepthBiasState::default(),
{
DepthBiasState {
// Values determined empirically
constant: 3,
slope_scale: 1.0,
..default()
}
} else {
default()
},
}), }),
multisample: MultisampleState { multisample: MultisampleState {
count: key.msaa().samples(), count: key.msaa().samples(),