Path: blob/main/examples/gltf/gltf_extension_mesh_2d.rs
9396 views
//! Uses glTF extension processing to convert incoming 3d Meshes to 2d Meshes12use bevy::{3asset::LoadContext,4gltf::{5extensions::{GltfExtensionHandler, GltfExtensionHandlers},6GltfPlugin,7},8mesh::{MeshVertexAttribute, MeshVertexBufferLayoutRef},9pbr::PbrPlugin,10prelude::*,11reflect::TypePath,12render::render_resource::*,13shader::ShaderRef,14sprite_render::{Material2d, Material2dKey, Material2dPlugin},15};1617/// This example uses a shader source file from the assets subdirectory18const SHADER_ASSET_PATH: &str = "shaders/custom_gltf_2d.wgsl";1920/// This vertex attribute supplies barycentric coordinates for each triangle.21///22/// Each component of the vector corresponds to one corner of a triangle. It's23/// equal to 1.0 in that corner and 0.0 in the other two. Hence, its value in24/// the fragment shader indicates proximity to a corner or the opposite edge.25const ATTRIBUTE_BARYCENTRIC: MeshVertexAttribute =26MeshVertexAttribute::new("Barycentric", 2137464976, VertexFormat::Float32x3);2728fn main() {29App::new()30.insert_resource(GlobalAmbientLight {31color: Color::WHITE,32brightness: 2000.,33..default()34})35.add_plugins((36DefaultPlugins37.set(38GltfPlugin::default()39// Map a custom glTF attribute name to a `MeshVertexAttribute`.40// The glTF file used here has an attribute name with *two*41// underscores: __BARYCENTRIC42// One is stripped to do the comparison here.43.add_custom_vertex_attribute("_BARYCENTRIC", ATTRIBUTE_BARYCENTRIC),44)45.set(PbrPlugin {46gltf_render_enabled: false,47..Default::default()48}),49GltfToMesh2dPlugin,50))51.add_systems(Startup, setup)52.run();53}5455fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {56commands.spawn((57SceneRoot(58asset_server59.load(GltfAssetLabel::Scene(0).from_asset("models/barycentric/barycentric.gltf")),60),61Transform::from_scale(150. * Vec3::ONE),62));63commands.spawn(Camera2d);64}6566struct GltfToMesh2dPlugin;6768impl Plugin for GltfToMesh2dPlugin {69fn build(&self, app: &mut App) {70#[cfg(target_family = "wasm")]71bevy::tasks::block_on(async {72app.world_mut()73.resource_mut::<GltfExtensionHandlers>()74.075.write()76.await77.push(Box::new(GltfExtensionHandlerToMesh2d))78});79#[cfg(not(target_family = "wasm"))]80app.world_mut()81.resource_mut::<GltfExtensionHandlers>()82.083.write_blocking()84.push(Box::new(GltfExtensionHandlerToMesh2d));8586app.add_plugins(Material2dPlugin::<CustomMaterial>::default());87}88}8990#[derive(Default, Clone)]91struct GltfExtensionHandlerToMesh2d;9293impl GltfExtensionHandler for GltfExtensionHandlerToMesh2d {94fn dyn_clone(&self) -> Box<dyn GltfExtensionHandler> {95Box::new((*self).clone())96}9798fn on_spawn_mesh_and_material(99&mut self,100load_context: &mut LoadContext<'_>,101_primitive: &gltf::Primitive,102_mesh: &gltf::Mesh,103_material: &gltf::Material,104entity: &mut EntityWorldMut,105_material_label: &str,106) {107if let Some(mesh3d) = entity.get::<Mesh3d>() {108let material_handle =109load_context.add_labeled_asset("AColorMaterial".to_string(), CustomMaterial {});110let mesh_handle = mesh3d.0.clone();111entity112.remove::<Mesh3d>()113.insert((Mesh2d(mesh_handle), MeshMaterial2d(material_handle.clone())));114}115}116}117118/// This custom material uses barycentric coordinates from119/// `ATTRIBUTE_BARYCENTRIC` to shade a white border around each triangle. The120/// thickness of the border is animated using the global time shader uniform.121#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]122struct CustomMaterial {}123124impl Material2d for CustomMaterial {125fn vertex_shader() -> ShaderRef {126SHADER_ASSET_PATH.into()127}128fn fragment_shader() -> ShaderRef {129SHADER_ASSET_PATH.into()130}131132fn specialize(133descriptor: &mut RenderPipelineDescriptor,134layout: &MeshVertexBufferLayoutRef,135_key: Material2dKey<Self>,136) -> Result<(), SpecializedMeshPipelineError> {137let vertex_layout = layout.0.get_layout(&[138Mesh::ATTRIBUTE_POSITION.at_shader_location(0),139Mesh::ATTRIBUTE_COLOR.at_shader_location(1),140ATTRIBUTE_BARYCENTRIC.at_shader_location(2),141])?;142descriptor.vertex.buffers = vec![vertex_layout];143Ok(())144}145}146147148