diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index b4c9bb2857..5ee78c5d49 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -122,17 +122,17 @@ impl ViewNode for DeferredGBufferPrepassNode { let view_entity = graph.view_entity(); render_context.add_command_buffer_generation_task(move |render_device| { #[cfg(feature = "trace")] - let _deferred_span = info_span!("deferred").entered(); + let _deferred_span = info_span!("deferred_prepass").entered(); // Command encoder setup let mut command_encoder = render_device.create_command_encoder(&CommandEncoderDescriptor { - label: Some("deferred_command_encoder"), + label: Some("deferred_prepass_command_encoder"), }); // Render pass setup let render_pass = command_encoder.begin_render_pass(&RenderPassDescriptor { - label: Some("deferred"), + label: Some("deferred_prepass"), color_attachments: &color_attachments, depth_stencil_attachment, timestamp_writes: None, @@ -148,20 +148,20 @@ impl ViewNode for DeferredGBufferPrepassNode { || !opaque_deferred_phase.unbatchable_keys.is_empty() { #[cfg(feature = "trace")] - let _opaque_prepass_span = info_span!("opaque_deferred").entered(); + let _opaque_prepass_span = info_span!("opaque_deferred_prepass").entered(); opaque_deferred_phase.render(&mut render_pass, world, view_entity); } // Alpha masked draws if !alpha_mask_deferred_phase.is_empty() { #[cfg(feature = "trace")] - let _alpha_mask_deferred_span = info_span!("alpha_mask_deferred").entered(); + let _alpha_mask_deferred_span = info_span!("alpha_mask_deferred_prepass").entered(); alpha_mask_deferred_phase.render(&mut render_pass, world, view_entity); } drop(render_pass); - // Copy prepass depth to the main depth texture + // After rendering to the view depth texture, copy it to the prepass depth texture if let Some(prepass_depth_texture) = &view_prepass_textures.depth { command_encoder.copy_texture_to_texture( view_depth_texture.texture.as_image_copy(), diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index be0ea5a7f9..d493a20c70 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -162,7 +162,7 @@ impl ViewNode for PrepassNode { pass_span.end(&mut render_pass); drop(render_pass); - // Copy prepass depth to the main depth texture if deferred isn't going to + // After rendering to the view depth texture, copy it to the prepass depth texture if deferred isn't going to if deferred_prepass.is_none() { if let Some(prepass_depth_texture) = &view_prepass_textures.depth { command_encoder.copy_texture_to_texture( diff --git a/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs b/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs index 0a4c8d005f..153eafcc09 100644 --- a/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs +++ b/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs @@ -10,8 +10,13 @@ use crate::{ MeshViewBindGroup, PrepassViewBindGroup, ViewFogUniformOffset, ViewLightProbesUniformOffset, ViewLightsUniformOffset, ViewScreenSpaceReflectionsUniformOffset, }; -use bevy_core_pipeline::prepass::{PreviousViewUniformOffset, ViewPrepassTextures}; -use bevy_ecs::{query::QueryItem, world::World}; +use bevy_core_pipeline::prepass::{ + MotionVectorPrepass, PreviousViewUniformOffset, ViewPrepassTextures, +}; +use bevy_ecs::{ + query::{Has, QueryItem}, + world::World, +}; use bevy_render::{ camera::ExtractedCamera, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, @@ -138,7 +143,8 @@ impl ViewNode for MeshletPrepassNode { &'static ExtractedCamera, &'static ViewPrepassTextures, &'static ViewUniformOffset, - Option<&'static PreviousViewUniformOffset>, + &'static PreviousViewUniformOffset, + Has, &'static MeshletViewMaterialsPrepass, &'static MeshletViewBindGroups, &'static MeshletViewResources, @@ -153,6 +159,7 @@ impl ViewNode for MeshletPrepassNode { view_prepass_textures, view_uniform_offset, previous_view_uniform_offset, + view_has_motion_vector_prepass, meshlet_view_materials, meshlet_view_bind_groups, meshlet_view_resources, @@ -212,7 +219,7 @@ impl ViewNode for MeshletPrepassNode { render_pass.set_camera_viewport(viewport); } - if let Some(previous_view_uniform_offset) = previous_view_uniform_offset { + if view_has_motion_vector_prepass { render_pass.set_bind_group( 0, prepass_view_bind_group.motion_vectors.as_ref().unwrap(), @@ -259,7 +266,8 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode { &'static ExtractedCamera, &'static ViewPrepassTextures, &'static ViewUniformOffset, - Option<&'static PreviousViewUniformOffset>, + &'static PreviousViewUniformOffset, + Has, &'static MeshletViewMaterialsDeferredGBufferPrepass, &'static MeshletViewBindGroups, &'static MeshletViewResources, @@ -274,6 +282,7 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode { view_prepass_textures, view_uniform_offset, previous_view_uniform_offset, + view_has_motion_vector_prepass, meshlet_view_materials, meshlet_view_bind_groups, meshlet_view_resources, @@ -338,7 +347,7 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode { render_pass.set_camera_viewport(viewport); } - if let Some(previous_view_uniform_offset) = previous_view_uniform_offset { + if view_has_motion_vector_prepass { render_pass.set_bind_group( 0, prepass_view_bind_group.motion_vectors.as_ref().unwrap(), diff --git a/crates/bevy_pbr/src/meshlet/material_draw_prepare.rs b/crates/bevy_pbr/src/meshlet/material_draw_prepare.rs index 65fa6272a2..f572edc0c7 100644 --- a/crates/bevy_pbr/src/meshlet/material_draw_prepare.rs +++ b/crates/bevy_pbr/src/meshlet/material_draw_prepare.rs @@ -142,7 +142,8 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass( continue; }; - if material.properties.alpha_mode != AlphaMode::Opaque + if material.properties.render_method != OpaqueRendererMethod::Forward + || material.properties.alpha_mode != AlphaMode::Opaque || material.properties.reads_view_transmission_texture { continue; diff --git a/crates/bevy_pbr/src/meshlet/mod.rs b/crates/bevy_pbr/src/meshlet/mod.rs index 5176087d49..91c664d169 100644 --- a/crates/bevy_pbr/src/meshlet/mod.rs +++ b/crates/bevy_pbr/src/meshlet/mod.rs @@ -109,6 +109,10 @@ const MESHLET_MESH_MATERIAL_SHADER_HANDLE: Handle = /// /// This plugin does not work on WASM. /// +/// Mixing forward+prepass and deferred rendering for opaque materials is not currently supported when using this plugin. +/// You must use one or the other by setting [`crate::DefaultOpaqueRendererMethod`]. +/// Do not override [`crate::Material::opaque_render_method`] for any material when using this plugin. +/// /// ![A render of the Stanford dragon as a `MeshletMesh`](https://raw.githubusercontent.com/bevyengine/bevy/main/crates/bevy_pbr/src/meshlet/meshlet_preview.png) pub struct MeshletPlugin; @@ -206,18 +210,18 @@ impl Plugin for MeshletPlugin { .add_render_graph_edges( Core3d, ( - // TODO: Meshlet VisibilityBufferRaster should be after main pass when not using depth prepass + // Non-meshlet shading passes _must_ come before meshlet shading passes NodePbr::ShadowPass, - Node3d::Prepass, - Node3d::DeferredPrepass, NodeMeshlet::VisibilityBufferRasterPass, NodeMeshlet::Prepass, + Node3d::Prepass, NodeMeshlet::DeferredPrepass, + Node3d::DeferredPrepass, Node3d::CopyDeferredLightingId, Node3d::EndPrepasses, Node3d::StartMainPass, - Node3d::MainOpaquePass, NodeMeshlet::MainOpaquePass, + Node3d::MainOpaquePass, Node3d::EndMainPass, ), )