Fix Z-fighting between overlay and stencil with OpenGL wgpu back-end.
This commit is contained in:
parent
4a8d4409fe
commit
35032e05a3
|
@ -20,6 +20,7 @@ bevy = { version = "0.10", default-features = false, features = [
|
||||||
bitfield = "0.14"
|
bitfield = "0.14"
|
||||||
interpolation = "0.2"
|
interpolation = "0.2"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
wgpu-types = "0.15"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy = { version = "0.10", default-features = false, features = [
|
bevy = { version = "0.10", default-features = false, features = [
|
||||||
|
|
11
src/draw.rs
11
src/draw.rs
|
@ -3,7 +3,9 @@ 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};
|
||||||
|
@ -32,6 +34,7 @@ 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>,
|
||||||
|
@ -52,7 +55,8 @@ 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();
|
||||||
|
@ -105,6 +109,7 @@ 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>,
|
||||||
|
@ -129,7 +134,9 @@ pub(crate) fn queue_outline_volume_mesh(
|
||||||
.get_id::<DrawOutline>()
|
.get_id::<DrawOutline>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let base_key = PipelineKey::new().with_msaa(*msaa);
|
let base_key = PipelineKey::new()
|
||||||
|
.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();
|
||||||
|
|
|
@ -1,24 +1,32 @@
|
||||||
#ifdef VOLUME
|
struct FragmentOutput {
|
||||||
|
@location(0) colour: vec4<f32>,
|
||||||
|
#ifdef OPENGL_WORKAROUND
|
||||||
|
@builtin(frag_depth) frag_depth: f32,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct OutlineFragmentUniform {
|
struct OutlineFragmentUniform {
|
||||||
@align(16)
|
@align(16)
|
||||||
colour: vec4<f32>,
|
colour: vec4<f32>,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef VOLUME
|
||||||
@group(3) @binding(1)
|
@group(3) @binding(1)
|
||||||
var<uniform> fstage: OutlineFragmentUniform;
|
var<uniform> fstage: OutlineFragmentUniform;
|
||||||
|
|
||||||
@fragment
|
|
||||||
fn fragment() -> @location(0) vec4<f32> {
|
|
||||||
return fstage.colour;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
// Stencil
|
|
||||||
|
|
||||||
@fragment
|
|
||||||
fn fragment() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
#ifdef OPENGL_WORKAROUND
|
||||||
|
fn fragment(@location(0) normalised_depth: f32) -> FragmentOutput {
|
||||||
|
#else
|
||||||
|
fn fragment() -> FragmentOutput {
|
||||||
|
#endif
|
||||||
|
var out: FragmentOutput;
|
||||||
|
#ifdef VOLUME
|
||||||
|
out.colour = fstage.colour;
|
||||||
|
#endif
|
||||||
|
#ifdef OPENGL_WORKAROUND
|
||||||
|
out.frag_depth = normalised_depth;
|
||||||
|
#endif
|
||||||
|
return out;
|
||||||
|
}
|
|
@ -12,6 +12,13 @@ struct VertexInput {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VertexOutput {
|
||||||
|
@builtin(position) position: vec4<f32>,
|
||||||
|
#ifdef OPENGL_WORKAROUND
|
||||||
|
@location(0) normalised_depth: f32,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct OutlineViewUniform {
|
struct OutlineViewUniform {
|
||||||
@align(16)
|
@align(16)
|
||||||
scale: vec2<f32>,
|
scale: vec2<f32>,
|
||||||
|
@ -53,7 +60,7 @@ fn model_origin_z(plane: vec3<f32>, view_proj: mat4x4<f32>) -> f32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vertex(vertex: VertexInput) -> @builtin(position) vec4<f32> {
|
fn vertex(vertex: VertexInput) -> VertexOutput {
|
||||||
#ifdef SKINNED
|
#ifdef SKINNED
|
||||||
let model = skin_model(vertex.joint_indexes, vertex.joint_weights);
|
let model = skin_model(vertex.joint_indexes, vertex.joint_weights);
|
||||||
#else
|
#else
|
||||||
|
@ -72,5 +79,10 @@ fn vertex(vertex: VertexInput) -> @builtin(position) vec4<f32> {
|
||||||
let ndc_delta = vstage.offset * normalize(clip_norm.xy) * view_uniform.scale * clip_pos.w;
|
let ndc_delta = vstage.offset * normalize(clip_norm.xy) * view_uniform.scale * clip_pos.w;
|
||||||
let out_xy = clip_pos.xy + ndc_delta;
|
let out_xy = clip_pos.xy + ndc_delta;
|
||||||
#endif
|
#endif
|
||||||
return vec4<f32>(out_xy, out_z, clip_pos.w);
|
var out: VertexOutput;
|
||||||
|
out.position = vec4<f32>(out_xy, out_z, clip_pos.w);
|
||||||
|
#ifdef OPENGL_WORKAROUND
|
||||||
|
out.normalised_depth = 0.5 + 0.5 * (out_z / clip_pos.w);
|
||||||
|
#endif
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +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(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
|
@ -129,6 +130,11 @@ impl PipelineKey {
|
||||||
self.set_hdr_format(hdr_format);
|
self.set_hdr_format(hdr_format);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn with_opengl_workaround(mut self, opengl_workaround: bool) -> Self {
|
||||||
|
self.set_opengl_workaround(opengl_workaround);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
|
@ -294,6 +300,11 @@ 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![mesh_layout.get_layout(&buffer_attrs)?];
|
let buffers = vec![mesh_layout.get_layout(&buffer_attrs)?];
|
||||||
Ok(RenderPipelineDescriptor {
|
Ok(RenderPipelineDescriptor {
|
||||||
vertex: VertexState {
|
vertex: VertexState {
|
||||||
|
|
Loading…
Reference in New Issue