mirror of
https://github.com/bevyengine/bevy
synced 2024-12-03 09:59:15 +00:00
12a2f83edd
# Objective - This PR aims to make creating meshes a little bit more ergonomic, specifically by removing the need for intermediate mutable variables. ## Solution - We add methods that consume the `Mesh` and return a mesh with the specified changes, so that meshes can be entirely constructed via builder-style calls, without intermediate variables; - Methods are flagged with `#[must_use]` to ensure proper use; - Examples are updated to use the new methods where applicable. Some examples are kept with the mutating methods so that users can still easily discover them, and also where the new methods wouldn't really be an improvement. ## Examples Before: ```rust let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, vs); mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vns); mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vts); mesh.set_indices(Some(Indices::U32(tris))); mesh ``` After: ```rust Mesh::new(PrimitiveTopology::TriangleList) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vs) .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vns) .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vts) .with_indices(Some(Indices::U32(tris))) ``` Before: ```rust let mut cube = Mesh::from(shape::Cube { size: 1.0 }); cube.generate_tangents().unwrap(); PbrBundle { mesh: meshes.add(cube), ..default() } ``` After: ```rust PbrBundle { mesh: meshes.add( Mesh::from(shape::Cube { size: 1.0 }) .with_generated_tangents() .unwrap(), ), ..default() } ``` --- ## Changelog - Added consuming builder methods for more ergonomic `Mesh` creation: `with_inserted_attribute()`, `with_removed_attribute()`, `with_indices()`, `with_duplicated_vertices()`, `with_computed_flat_normals()`, `with_generated_tangents()`, `with_morph_targets()`, `with_morph_target_names()`.
87 lines
2.7 KiB
Rust
87 lines
2.7 KiB
Rust
//! A shader that reads a mesh's custom vertex attribute.
|
|
|
|
use bevy::{
|
|
pbr::{MaterialPipeline, MaterialPipelineKey},
|
|
prelude::*,
|
|
reflect::TypePath,
|
|
render::{
|
|
mesh::{MeshVertexAttribute, MeshVertexBufferLayout},
|
|
render_resource::{
|
|
AsBindGroup, RenderPipelineDescriptor, ShaderRef, SpecializedMeshPipelineError,
|
|
VertexFormat,
|
|
},
|
|
},
|
|
};
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins((DefaultPlugins, MaterialPlugin::<CustomMaterial>::default()))
|
|
.add_systems(Startup, setup)
|
|
.run();
|
|
}
|
|
|
|
// A "high" random id should be used for custom attributes to ensure consistent sorting and avoid collisions with other attributes.
|
|
// See the MeshVertexAttribute docs for more info.
|
|
const ATTRIBUTE_BLEND_COLOR: MeshVertexAttribute =
|
|
MeshVertexAttribute::new("BlendColor", 988540917, VertexFormat::Float32x4);
|
|
|
|
/// set up a simple 3D scene
|
|
fn setup(
|
|
mut commands: Commands,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut materials: ResMut<Assets<CustomMaterial>>,
|
|
) {
|
|
let mesh = Mesh::from(shape::Cube { size: 1.0 })
|
|
// Sets the custom attribute
|
|
.with_inserted_attribute(
|
|
ATTRIBUTE_BLEND_COLOR,
|
|
// The cube mesh has 24 vertices (6 faces, 4 vertices per face), so we insert one BlendColor for each
|
|
vec![[1.0, 0.0, 0.0, 1.0]; 24],
|
|
);
|
|
|
|
// cube
|
|
commands.spawn(MaterialMeshBundle {
|
|
mesh: meshes.add(mesh),
|
|
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
|
material: materials.add(CustomMaterial {
|
|
color: Color::WHITE,
|
|
}),
|
|
..default()
|
|
});
|
|
|
|
// camera
|
|
commands.spawn(Camera3dBundle {
|
|
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
|
..default()
|
|
});
|
|
}
|
|
|
|
// This is the struct that will be passed to your shader
|
|
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
|
|
pub struct CustomMaterial {
|
|
#[uniform(0)]
|
|
color: Color,
|
|
}
|
|
|
|
impl Material for CustomMaterial {
|
|
fn vertex_shader() -> ShaderRef {
|
|
"shaders/custom_vertex_attribute.wgsl".into()
|
|
}
|
|
fn fragment_shader() -> ShaderRef {
|
|
"shaders/custom_vertex_attribute.wgsl".into()
|
|
}
|
|
|
|
fn specialize(
|
|
_pipeline: &MaterialPipeline<Self>,
|
|
descriptor: &mut RenderPipelineDescriptor,
|
|
layout: &MeshVertexBufferLayout,
|
|
_key: MaterialPipelineKey<Self>,
|
|
) -> Result<(), SpecializedMeshPipelineError> {
|
|
let vertex_layout = layout.get_layout(&[
|
|
Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
|
|
ATTRIBUTE_BLEND_COLOR.at_shader_location(1),
|
|
])?;
|
|
descriptor.vertex.buffers = vec![vertex_layout];
|
|
Ok(())
|
|
}
|
|
}
|