Add edit_material_on_gltf
example (#17677)
# Objective Create a minimal example of how to modify the material from a `Gltf`. This is frequently asked about on the help channel of the discord. ## Solution Create the example. ## Showcase 
This commit is contained in:
parent
989f547080
commit
9ea9c5df00
11
Cargo.toml
11
Cargo.toml
@ -920,6 +920,17 @@ description = "Showcases different blend modes"
|
||||
category = "3D Rendering"
|
||||
wasm = true
|
||||
|
||||
[[example]]
|
||||
name = "edit_material_on_gltf"
|
||||
path = "examples/3d/edit_material_on_gltf.rs"
|
||||
doc-scrape-examples = true
|
||||
|
||||
[package.metadata.example.edit_material_on_gltf]
|
||||
name = "Edit Gltf Material"
|
||||
description = "Showcases changing materials of a Gltf after Scene spawn"
|
||||
category = "3D Rendering"
|
||||
wasm = true
|
||||
|
||||
[[example]]
|
||||
name = "lighting"
|
||||
path = "examples/3d/lighting.rs"
|
||||
|
93
examples/3d/edit_material_on_gltf.rs
Normal file
93
examples/3d/edit_material_on_gltf.rs
Normal file
@ -0,0 +1,93 @@
|
||||
//! Showcases how to change the material of a `Scene` spawned from a Gltf
|
||||
|
||||
use bevy::{
|
||||
app::{App, PluginGroup, Startup},
|
||||
asset::{AssetServer, Assets},
|
||||
audio::AudioPlugin,
|
||||
color::{palettes, Color},
|
||||
gltf::GltfAssetLabel,
|
||||
math::{Dir3, Vec3},
|
||||
pbr::{DirectionalLight, MeshMaterial3d, StandardMaterial},
|
||||
prelude::{Camera3d, Children, Commands, Component, Query, Res, ResMut, Transform, Trigger},
|
||||
scene::{SceneInstanceReady, SceneRoot},
|
||||
DefaultPlugins,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins.build().disable::<AudioPlugin>())
|
||||
.add_systems(Startup, setup_scene)
|
||||
.add_observer(change_material)
|
||||
.run();
|
||||
}
|
||||
|
||||
/// This is added to a [`SceneRoot`] and will cause the [`StandardMaterial::base_color`]
|
||||
/// of all materials to be overwritten
|
||||
#[derive(Component)]
|
||||
struct ColorOverride(Color);
|
||||
|
||||
fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
commands.spawn((
|
||||
Camera3d::default(),
|
||||
Transform::from_xyz(0., 1., 2.5).looking_at(Vec3::new(0., 0.25, 0.), Dir3::Y),
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
DirectionalLight::default(),
|
||||
Transform::from_xyz(0., 1., 0.25).looking_at(Vec3::ZERO, Dir3::Y),
|
||||
));
|
||||
|
||||
// FlightHelmet handle
|
||||
let flight_helmet = asset_server
|
||||
.load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf"));
|
||||
// This model will keep its original materials
|
||||
commands.spawn(SceneRoot(flight_helmet.clone()));
|
||||
// This model will be tinted red
|
||||
commands.spawn((
|
||||
SceneRoot(flight_helmet.clone()),
|
||||
Transform::from_xyz(-1.25, 0., 0.),
|
||||
ColorOverride(palettes::tailwind::RED_300.into()),
|
||||
));
|
||||
// This model will be tinted green
|
||||
commands.spawn((
|
||||
SceneRoot(flight_helmet),
|
||||
Transform::from_xyz(1.25, 0., 0.),
|
||||
ColorOverride(palettes::tailwind::GREEN_300.into()),
|
||||
));
|
||||
}
|
||||
|
||||
fn change_material(
|
||||
trigger: Trigger<SceneInstanceReady>,
|
||||
mut commands: Commands,
|
||||
children: Query<&Children>,
|
||||
color_override: Query<&ColorOverride>,
|
||||
mesh_materials: Query<&MeshMaterial3d<StandardMaterial>>,
|
||||
mut asset_materials: ResMut<Assets<StandardMaterial>>,
|
||||
) {
|
||||
// Get the `ColorOverride` of the entity, if it does not have a color override, skip
|
||||
let Ok(color_override) = color_override.get(trigger.target()) else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Iterate over all children recursively
|
||||
for descendants in children.iter_descendants(trigger.target()) {
|
||||
// Get the material of the descendant
|
||||
if let Some(material) = mesh_materials
|
||||
.get(descendants)
|
||||
.ok()
|
||||
.and_then(|id| asset_materials.get_mut(id.id()))
|
||||
{
|
||||
// Create a copy of the material and override base color
|
||||
// If you intend on creating multiple models with the same tint, it
|
||||
// is best to cache the handle somewhere, as having multiple materials
|
||||
// that are identical is expensive
|
||||
let mut new_material = material.clone();
|
||||
new_material.base_color = color_override.0;
|
||||
|
||||
// Override `MeshMaterial3d` with new material
|
||||
commands
|
||||
.entity(descendants)
|
||||
.insert(MeshMaterial3d(asset_materials.add(new_material)));
|
||||
}
|
||||
}
|
||||
}
|
@ -150,6 +150,7 @@ Example | Description
|
||||
[Decal](../examples/3d/decal.rs) | Decal rendering
|
||||
[Deferred Rendering](../examples/3d/deferred_rendering.rs) | Renders meshes with both forward and deferred pipelines
|
||||
[Depth of field](../examples/3d/depth_of_field.rs) | Demonstrates depth of field
|
||||
[Edit Gltf Material](../examples/3d/edit_material_on_gltf.rs) | Showcases changing materials of a Gltf after Scene spawn
|
||||
[Fog](../examples/3d/fog.rs) | A scene showcasing the distance fog effect
|
||||
[Fog volumes](../examples/3d/fog_volumes.rs) | Demonstrates fog volumes
|
||||
[Generate Custom Mesh](../examples/3d/generate_custom_mesh.rs) | Simple showcase of how to generate a custom mesh with a custom texture
|
||||
|
Loading…
Reference in New Issue
Block a user