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 crate::{
Material, MeshFlags, MeshTransforms, MeshUniform, NotShadowCaster, NotShadowReceiver,
PreviousGlobalTransform, RenderMaterialBindings, RenderMaterialInstances,
RenderMeshMaterialIds,
Material, MaterialBindingId, MeshFlags, MeshTransforms, MeshUniform, NotShadowCaster,
NotShadowReceiver, PreviousGlobalTransform, RenderMaterialBindings, RenderMaterialInstances,
RenderMeshMaterialIds, StandardMaterial,
};
use bevy_asset::{AssetEvent, AssetServer, Assets, UntypedAssetId};
use bevy_asset::{AssetEvent, AssetId, AssetServer, Assets, UntypedAssetId};
use bevy_ecs::{
entity::{Entities, Entity, EntityHashMap},
event::EventReader,
@ -113,10 +113,16 @@ impl InstanceManager {
};
let mesh_material = mesh_material_ids.mesh_material(instance);
let mesh_material_binding_id = render_material_bindings
.get(&mesh_material)
.cloned()
.unwrap_or_default();
let mesh_material_binding_id =
if mesh_material != AssetId::<StandardMaterial>::invalid().untyped() {
render_material_bindings
.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(
&transforms,

View File

@ -1162,13 +1162,19 @@ impl RenderMeshInstanceGpuBuilder {
// yet loaded. In that case, add the mesh to
// `meshes_to_reextract_next_frame` and bail.
let mesh_material = mesh_material_ids.mesh_material(entity);
let mesh_material_binding_id = match render_material_bindings.get(&mesh_material) {
Some(binding_id) => *binding_id,
None => {
meshes_to_reextract_next_frame.insert(entity);
return None;
}
};
let mesh_material_binding_id =
if mesh_material != AssetId::<StandardMaterial>::invalid().untyped() {
match render_material_bindings.get(&mesh_material) {
Some(binding_id) => *binding_id,
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;
let lightmap_slot = match render_lightmaps.render_lightmaps.get(&entity) {