Fix mesh extraction for meshes without associated material. (#18631)

# Objective

Fixes #17986
Fixes #18608

## Solution

Guard against situations where an extracted mesh does not have an
associated material. The way that mesh is dependent on the material api
(although decoupled) here is a bit unfortunate and we might consider
ways in the future to support these material features without this
indirect dependency.
This commit is contained in:
charlotte 2025-03-31 11:09:27 -07:00 committed by GitHub
parent 95b9117eac
commit 17e3efac12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 15 deletions

View File

@ -1,10 +1,10 @@
use super::{meshlet_mesh_manager::MeshletMeshManager, MeshletMesh, MeshletMesh3d}; use super::{meshlet_mesh_manager::MeshletMeshManager, MeshletMesh, MeshletMesh3d};
use crate::{ use crate::{
Material, MeshFlags, MeshTransforms, MeshUniform, NotShadowCaster, NotShadowReceiver, Material, MaterialBindingId, MeshFlags, MeshTransforms, MeshUniform, NotShadowCaster,
PreviousGlobalTransform, RenderMaterialBindings, RenderMaterialInstances, NotShadowReceiver, PreviousGlobalTransform, RenderMaterialBindings, RenderMaterialInstances,
RenderMeshMaterialIds, RenderMeshMaterialIds, StandardMaterial,
}; };
use bevy_asset::{AssetEvent, AssetServer, Assets, UntypedAssetId}; use bevy_asset::{AssetEvent, AssetId, AssetServer, Assets, UntypedAssetId};
use bevy_ecs::{ use bevy_ecs::{
entity::{Entities, Entity, EntityHashMap}, entity::{Entities, Entity, EntityHashMap},
event::EventReader, event::EventReader,
@ -113,10 +113,16 @@ impl InstanceManager {
}; };
let mesh_material = mesh_material_ids.mesh_material(instance); let mesh_material = mesh_material_ids.mesh_material(instance);
let mesh_material_binding_id = render_material_bindings let mesh_material_binding_id =
.get(&mesh_material) if mesh_material != AssetId::<StandardMaterial>::invalid().untyped() {
.cloned() render_material_bindings
.unwrap_or_default(); .get(&mesh_material)
.cloned()
.unwrap_or_default()
} else {
// Use a dummy binding ID if the mesh has no material
MaterialBindingId::default()
};
let mesh_uniform = MeshUniform::new( let mesh_uniform = MeshUniform::new(
&transforms, &transforms,

View File

@ -1162,13 +1162,19 @@ impl RenderMeshInstanceGpuBuilder {
// yet loaded. In that case, add the mesh to // yet loaded. In that case, add the mesh to
// `meshes_to_reextract_next_frame` and bail. // `meshes_to_reextract_next_frame` and bail.
let mesh_material = mesh_material_ids.mesh_material(entity); let mesh_material = mesh_material_ids.mesh_material(entity);
let mesh_material_binding_id = match render_material_bindings.get(&mesh_material) { let mesh_material_binding_id =
Some(binding_id) => *binding_id, if mesh_material != AssetId::<StandardMaterial>::invalid().untyped() {
None => { match render_material_bindings.get(&mesh_material) {
meshes_to_reextract_next_frame.insert(entity); Some(binding_id) => *binding_id,
return None; None => {
} meshes_to_reextract_next_frame.insert(entity);
}; return None;
}
}
} else {
// Use a dummy material binding ID.
MaterialBindingId::default()
};
self.shared.material_bindings_index = mesh_material_binding_id; self.shared.material_bindings_index = mesh_material_binding_id;
let lightmap_slot = match render_lightmaps.render_lightmaps.get(&entity) { let lightmap_slot = match render_lightmaps.render_lightmaps.get(&entity) {