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"
|
category = "3D Rendering"
|
||||||
wasm = true
|
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]]
|
[[example]]
|
||||||
name = "lighting"
|
name = "lighting"
|
||||||
path = "examples/3d/lighting.rs"
|
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
|
[Decal](../examples/3d/decal.rs) | Decal rendering
|
||||||
[Deferred Rendering](../examples/3d/deferred_rendering.rs) | Renders meshes with both forward and deferred pipelines
|
[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
|
[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](../examples/3d/fog.rs) | A scene showcasing the distance fog effect
|
||||||
[Fog volumes](../examples/3d/fog_volumes.rs) | Demonstrates fog volumes
|
[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
|
[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