Fix custom mesh pipelines (#3381)

# Objective

Fixes #3379 

## Solution

The custom mesh pipelines needed to be specialized on each mesh's primitive topology, as done in `queue_meshes()`

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
davier 2021-12-20 20:33:39 +00:00
parent 46c1480f42
commit c79ec9cad6
3 changed files with 55 additions and 38 deletions

View file

@ -4,10 +4,10 @@ use bevy_app::Plugin;
use bevy_asset::{Assets, Handle, HandleUntyped}; use bevy_asset::{Assets, Handle, HandleUntyped};
use bevy_core_pipeline::Opaque3d; use bevy_core_pipeline::Opaque3d;
use bevy_ecs::{prelude::*, reflect::ReflectComponent}; use bevy_ecs::{prelude::*, reflect::ReflectComponent};
use bevy_reflect::Reflect; use bevy_reflect::{Reflect, TypeUuid};
use bevy_reflect::TypeUuid;
use bevy_render::{ use bevy_render::{
mesh::Mesh, mesh::Mesh,
render_asset::RenderAssets,
render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline}, render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline},
render_resource::{RenderPipelineCache, Shader, SpecializedPipeline, SpecializedPipelines}, render_resource::{RenderPipelineCache, Shader, SpecializedPipeline, SpecializedPipelines},
view::{ExtractedView, Msaa}, view::{ExtractedView, Msaa},
@ -93,14 +93,15 @@ impl SpecializedPipeline for WireframePipeline {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn queue_wireframes( fn queue_wireframes(
opaque_3d_draw_functions: Res<DrawFunctions<Opaque3d>>, opaque_3d_draw_functions: Res<DrawFunctions<Opaque3d>>,
render_meshes: Res<RenderAssets<Mesh>>,
wireframe_config: Res<WireframeConfig>, wireframe_config: Res<WireframeConfig>,
wireframe_pipeline: Res<WireframePipeline>, wireframe_pipeline: Res<WireframePipeline>,
mut pipeline_cache: ResMut<RenderPipelineCache>, mut pipeline_cache: ResMut<RenderPipelineCache>,
mut specialized_pipelines: ResMut<SpecializedPipelines<WireframePipeline>>, mut specialized_pipelines: ResMut<SpecializedPipelines<WireframePipeline>>,
msaa: Res<Msaa>, msaa: Res<Msaa>,
mut material_meshes: QuerySet<( mut material_meshes: QuerySet<(
QueryState<(Entity, &MeshUniform), With<Handle<Mesh>>>, QueryState<(Entity, &Handle<Mesh>, &MeshUniform)>,
QueryState<(Entity, &MeshUniform), (With<Handle<Mesh>>, With<Wireframe>)>, QueryState<(Entity, &Handle<Mesh>, &MeshUniform), With<Wireframe>>,
)>, )>,
mut views: Query<(&ExtractedView, &mut RenderPhase<Opaque3d>)>, mut views: Query<(&ExtractedView, &mut RenderPhase<Opaque3d>)>,
) { ) {
@ -113,18 +114,23 @@ fn queue_wireframes(
let view_matrix = view.transform.compute_matrix(); let view_matrix = view.transform.compute_matrix();
let view_row_2 = view_matrix.row(2); let view_row_2 = view_matrix.row(2);
let add_render_phase = |(entity, mesh_uniform): (Entity, &MeshUniform)| { let add_render_phase =
transparent_phase.add(Opaque3d { |(entity, mesh_handle, mesh_uniform): (Entity, &Handle<Mesh>, &MeshUniform)| {
entity, if let Some(mesh) = render_meshes.get(mesh_handle) {
pipeline: specialized_pipelines.specialize( let key =
&mut pipeline_cache, key | MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
&wireframe_pipeline, transparent_phase.add(Opaque3d {
key, entity,
), pipeline: specialized_pipelines.specialize(
draw_function: draw_custom, &mut pipeline_cache,
distance: view_row_2.dot(mesh_uniform.transform.col(3)), &wireframe_pipeline,
}); key,
}; ),
draw_function: draw_custom,
distance: view_row_2.dot(mesh_uniform.transform.col(3)),
});
}
};
if wireframe_config.global { if wireframe_config.global {
material_meshes.q0().iter().for_each(add_render_phase); material_meshes.q0().iter().for_each(add_render_phase);

View file

@ -6,6 +6,7 @@ use bevy::{
}, },
prelude::*, prelude::*,
render::{ render::{
render_asset::RenderAssets,
render_component::{ExtractComponent, ExtractComponentPlugin}, render_component::{ExtractComponent, ExtractComponentPlugin},
render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline}, render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline},
render_resource::{ render_resource::{
@ -126,13 +127,15 @@ type DrawIsRed = (
DrawMesh, DrawMesh,
); );
#[allow(clippy::too_many_arguments)]
fn queue_custom( fn queue_custom(
transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>, transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>,
render_meshes: Res<RenderAssets<Mesh>>,
custom_pipeline: Res<IsRedPipeline>, custom_pipeline: Res<IsRedPipeline>,
msaa: Res<Msaa>, msaa: Res<Msaa>,
mut pipelines: ResMut<SpecializedPipelines<IsRedPipeline>>, mut pipelines: ResMut<SpecializedPipelines<IsRedPipeline>>,
mut pipeline_cache: ResMut<RenderPipelineCache>, mut pipeline_cache: ResMut<RenderPipelineCache>,
material_meshes: Query<(Entity, &MeshUniform, &IsRed), With<Handle<Mesh>>>, material_meshes: Query<(Entity, &Handle<Mesh>, &MeshUniform, &IsRed)>,
mut views: Query<(&ExtractedView, &mut RenderPhase<Transparent3d>)>, mut views: Query<(&ExtractedView, &mut RenderPhase<Transparent3d>)>,
) { ) {
let draw_custom = transparent_3d_draw_functions let draw_custom = transparent_3d_draw_functions
@ -143,15 +146,18 @@ fn queue_custom(
for (view, mut transparent_phase) in views.iter_mut() { for (view, mut transparent_phase) in views.iter_mut() {
let view_matrix = view.transform.compute_matrix(); let view_matrix = view.transform.compute_matrix();
let view_row_2 = view_matrix.row(2); let view_row_2 = view_matrix.row(2);
for (entity, mesh_uniform, is_red) in material_meshes.iter() { for (entity, mesh_handle, mesh_uniform, is_red) in material_meshes.iter() {
let pipeline = if let Some(mesh) = render_meshes.get(mesh_handle) {
pipelines.specialize(&mut pipeline_cache, &custom_pipeline, (*is_red, key)); let key = key | MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
transparent_phase.add(Transparent3d { let pipeline =
entity, pipelines.specialize(&mut pipeline_cache, &custom_pipeline, (*is_red, key));
pipeline, transparent_phase.add(Transparent3d {
draw_function: draw_custom, entity,
distance: view_row_2.dot(mesh_uniform.transform.col(3)), pipeline,
}); draw_function: draw_custom,
distance: view_row_2.dot(mesh_uniform.transform.col(3)),
});
}
} }
} }
} }

View file

@ -171,11 +171,12 @@ impl FromWorld for CustomPipeline {
pub fn queue_custom( pub fn queue_custom(
transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>, transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>,
materials: Res<RenderAssets<CustomMaterial>>, materials: Res<RenderAssets<CustomMaterial>>,
render_meshes: Res<RenderAssets<Mesh>>,
custom_pipeline: Res<CustomPipeline>, custom_pipeline: Res<CustomPipeline>,
mut pipeline_cache: ResMut<RenderPipelineCache>, mut pipeline_cache: ResMut<RenderPipelineCache>,
mut specialized_pipelines: ResMut<SpecializedPipelines<CustomPipeline>>, mut specialized_pipelines: ResMut<SpecializedPipelines<CustomPipeline>>,
msaa: Res<Msaa>, msaa: Res<Msaa>,
material_meshes: Query<(Entity, &Handle<CustomMaterial>, &MeshUniform), With<Handle<Mesh>>>, material_meshes: Query<(Entity, &Handle<CustomMaterial>, &Handle<Mesh>, &MeshUniform)>,
mut views: Query<(&ExtractedView, &mut RenderPhase<Transparent3d>)>, mut views: Query<(&ExtractedView, &mut RenderPhase<Transparent3d>)>,
) { ) {
let draw_custom = transparent_3d_draw_functions let draw_custom = transparent_3d_draw_functions
@ -186,18 +187,22 @@ pub fn queue_custom(
for (view, mut transparent_phase) in views.iter_mut() { for (view, mut transparent_phase) in views.iter_mut() {
let view_matrix = view.transform.compute_matrix(); let view_matrix = view.transform.compute_matrix();
let view_row_2 = view_matrix.row(2); let view_row_2 = view_matrix.row(2);
for (entity, material_handle, mesh_uniform) in material_meshes.iter() { for (entity, material_handle, mesh_handle, mesh_uniform) in material_meshes.iter() {
if materials.contains_key(material_handle) { if materials.contains_key(material_handle) {
transparent_phase.add(Transparent3d { if let Some(mesh) = render_meshes.get(mesh_handle) {
entity, let key =
pipeline: specialized_pipelines.specialize( key | MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
&mut pipeline_cache, transparent_phase.add(Transparent3d {
&custom_pipeline, entity,
key, pipeline: specialized_pipelines.specialize(
), &mut pipeline_cache,
draw_function: draw_custom, &custom_pipeline,
distance: view_row_2.dot(mesh_uniform.transform.col(3)), key,
}); ),
draw_function: draw_custom,
distance: view_row_2.dot(mesh_uniform.transform.col(3)),
});
}
} }
} }
} }