Added Mesh::ATTRIBUTE_POSITION_2D (VertexFormat::Float32x2)

This commit is contained in:
Brian Reavis 2024-09-18 13:50:25 -07:00
parent 2ae5a21009
commit 5e1f2e9f14
3 changed files with 55 additions and 8 deletions

View file

@ -202,6 +202,15 @@ impl Mesh {
pub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_JointIndex", 7, VertexFormat::Uint16x4);
/// Where the vertex is located in 2D space. Use in conjunction with [`Mesh::insert_attribute`]
/// or [`Mesh::with_inserted_attribute`].
///
/// *This attribute should only be used on meshes intended for rendering with 2D cameras (in lieu of `ATTRIBUTE_POSITION`).*
///
/// The format of this attribute is [`VertexFormat::Float32x2`].
pub const ATTRIBUTE_POSITION_2D: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Position_2d", 8, VertexFormat::Float32x2);
/// Construct a new mesh. You need to provide a [`PrimitiveTopology`] so that the
/// renderer knows how to treat the vertex data. Most of the time this will be
/// [`PrimitiveTopology::TriangleList`].
@ -946,6 +955,14 @@ impl Mesh {
positions
.iter_mut()
.for_each(|pos| *pos = (Vec3::from_slice(pos) + translation).to_array());
} else if let Some(VertexAttributeValues::Float32x2(ref mut positions)) =
self.attribute_mut(Mesh::ATTRIBUTE_POSITION_2D)
{
// Apply translation to vertex positions
let translation_2d = translation.xy();
positions
.iter_mut()
.for_each(|pos| *pos = (Vec2::from_slice(pos) + translation_2d).to_array());
}
}
@ -968,6 +985,13 @@ impl Mesh {
positions
.iter_mut()
.for_each(|pos| *pos = (rotation * Vec3::from_slice(pos)).to_array());
} else if let Some(VertexAttributeValues::Float32x2(ref mut positions)) =
self.attribute_mut(Mesh::ATTRIBUTE_POSITION_2D)
{
// Apply rotation to vertex positions
positions
.iter_mut()
.for_each(|pos| *pos = (rotation * Vec3::new(pos[0], pos[1], 0.0)).xy().to_array());
}
// No need to transform normals or tangents if rotation is near identity
@ -1020,6 +1044,14 @@ impl Mesh {
positions
.iter_mut()
.for_each(|pos| *pos = (scale * Vec3::from_slice(pos)).to_array());
} else if let Some(VertexAttributeValues::Float32x2(ref mut positions)) =
self.attribute_mut(Mesh::ATTRIBUTE_POSITION_2D)
{
// Apply scale to vertex positions
let scale_xy = scale.xy();
positions
.iter_mut()
.for_each(|pos| *pos = (scale_xy * Vec2::from_slice(pos)).to_array());
}
// No need to transform normals or tangents if scale is uniform
@ -1052,13 +1084,17 @@ impl Mesh {
/// Returns `None` if `self` doesn't have [`Mesh::ATTRIBUTE_POSITION`] of
/// type [`VertexAttributeValues::Float32x3`], or if `self` doesn't have any vertices.
pub fn compute_aabb(&self) -> Option<Aabb> {
let Some(VertexAttributeValues::Float32x3(values)) =
if let Some(VertexAttributeValues::Float32x3(values)) =
self.attribute(Mesh::ATTRIBUTE_POSITION)
else {
return None;
};
Aabb::enclosing(values.iter().map(|p| Vec3::from_slice(p)))
{
Aabb::enclosing(values.iter().map(|p| Vec3::from_slice(p)))
} else if let Some(VertexAttributeValues::Float32x2(values)) =
self.attribute(Mesh::ATTRIBUTE_POSITION_2D)
{
Aabb::enclosing(values.iter().map(|p| Vec3::new(p[0], p[1], 0.0)))
} else {
None
}
}
/// Whether this mesh has morph targets.

View file

@ -556,6 +556,10 @@ impl SpecializedMeshPipeline for Mesh2dPipeline {
if layout.0.contains(Mesh::ATTRIBUTE_POSITION) {
shader_defs.push("VERTEX_POSITIONS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
} else if layout.0.contains(Mesh::ATTRIBUTE_POSITION_2D) {
shader_defs.push("VERTEX_POSITIONS".into());
shader_defs.push("VERTEX_POSITIONS_2D".into());
vertex_attributes.push(Mesh::ATTRIBUTE_POSITION_2D.at_shader_location(0));
}
if layout.0.contains(Mesh::ATTRIBUTE_NORMAL) {

View file

@ -10,7 +10,9 @@
struct Vertex {
@builtin(instance_index) instance_index: u32,
#ifdef VERTEX_POSITIONS
#ifdef VERTEX_POSITIONS_2D
@location(0) position: vec2<f32>,
#else ifdef VERTEX_POSITIONS
@location(0) position: vec3<f32>,
#endif
#ifdef VERTEX_NORMALS
@ -35,10 +37,15 @@ fn vertex(vertex: Vertex) -> VertexOutput {
#endif
#ifdef VERTEX_POSITIONS
#ifdef VERTEX_POSITIONS_2D
let vertex_position = vec4<f32>(vertex.position, 0.0, 1.0);
#else
let vertex_position = vec4<f32>(vertex.position, 1.0);
#endif
var world_from_local = mesh_functions::get_world_from_local(vertex.instance_index);
out.world_position = mesh_functions::mesh2d_position_local_to_world(
world_from_local,
vec4<f32>(vertex.position, 1.0)
vertex_position
);
out.position = mesh_functions::mesh2d_position_world_to_clip(out.world_position);
#endif