Import the second UV map if present in glTF files. (#9992)

Conventionally, the second UV map (`TEXCOORD1`, `UV1`) is used for
lightmap UVs. This commit allows Bevy to import them, so that a custom
shader that applies lightmaps can use those UVs if desired.

Note that this doesn't actually apply lightmaps to Bevy meshes; that
will be a followup. It does, however, open the door to future Bevy
plugins that implement baked global illumination.

## Changelog

### Added

The Bevy glTF loader now imports a second UV channel (`TEXCOORD1`,
`UV1`) from meshes if present. This can be used by custom shaders to
implement lightmapping.
This commit is contained in:
Patrick Walton 2023-10-02 14:07:03 -07:00 committed by GitHub
parent 019649422b
commit 44a9a4cc86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 26 additions and 11 deletions

View File

@ -263,6 +263,7 @@ pub(crate) fn convert_attribute(
gltf::Semantic::Tangents => Some((Mesh::ATTRIBUTE_TANGENT, ConversionMode::Any)), gltf::Semantic::Tangents => Some((Mesh::ATTRIBUTE_TANGENT, ConversionMode::Any)),
gltf::Semantic::Colors(0) => Some((Mesh::ATTRIBUTE_COLOR, ConversionMode::Rgba)), gltf::Semantic::Colors(0) => Some((Mesh::ATTRIBUTE_COLOR, ConversionMode::Rgba)),
gltf::Semantic::TexCoords(0) => Some((Mesh::ATTRIBUTE_UV_0, ConversionMode::TexCoord)), gltf::Semantic::TexCoords(0) => Some((Mesh::ATTRIBUTE_UV_0, ConversionMode::TexCoord)),
gltf::Semantic::TexCoords(1) => Some((Mesh::ATTRIBUTE_UV_1, ConversionMode::TexCoord)),
gltf::Semantic::Joints(0) => { gltf::Semantic::Joints(0) => {
Some((Mesh::ATTRIBUTE_JOINT_INDEX, ConversionMode::JointIndex)) Some((Mesh::ATTRIBUTE_JOINT_INDEX, ConversionMode::JointIndex))
} }

View File

@ -779,14 +779,19 @@ impl SpecializedMeshPipeline for MeshPipeline {
vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(2)); vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(2));
} }
if layout.contains(Mesh::ATTRIBUTE_UV_1) {
shader_defs.push("VERTEX_UVS_1".into());
vertex_attributes.push(Mesh::ATTRIBUTE_UV_1.at_shader_location(3));
}
if layout.contains(Mesh::ATTRIBUTE_TANGENT) { if layout.contains(Mesh::ATTRIBUTE_TANGENT) {
shader_defs.push("VERTEX_TANGENTS".into()); shader_defs.push("VERTEX_TANGENTS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(3)); vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(4));
} }
if layout.contains(Mesh::ATTRIBUTE_COLOR) { if layout.contains(Mesh::ATTRIBUTE_COLOR) {
shader_defs.push("VERTEX_COLORS".into()); shader_defs.push("VERTEX_COLORS".into());
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(4)); vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(5));
} }
let mut bind_group_layout = match key.msaa_samples() { let mut bind_group_layout = match key.msaa_samples() {
@ -800,7 +805,7 @@ impl SpecializedMeshPipeline for MeshPipeline {
bind_group_layout.push(setup_morph_and_skinning_defs( bind_group_layout.push(setup_morph_and_skinning_defs(
&self.mesh_layouts, &self.mesh_layouts,
layout, layout,
5, 6,
&key, &key,
&mut shader_defs, &mut shader_defs,
&mut vertex_attributes, &mut vertex_attributes,

View File

@ -16,15 +16,16 @@ struct Vertex {
#ifdef VERTEX_UVS #ifdef VERTEX_UVS
@location(2) uv: vec2<f32>, @location(2) uv: vec2<f32>,
#endif #endif
// (Alternate UVs are at location 3, but they're currently unused here.)
#ifdef VERTEX_TANGENTS #ifdef VERTEX_TANGENTS
@location(3) tangent: vec4<f32>, @location(4) tangent: vec4<f32>,
#endif #endif
#ifdef VERTEX_COLORS #ifdef VERTEX_COLORS
@location(4) color: vec4<f32>, @location(5) color: vec4<f32>,
#endif #endif
#ifdef SKINNED #ifdef SKINNED
@location(5) joint_indices: vec4<u32>, @location(6) joint_indices: vec4<u32>,
@location(6) joint_weights: vec4<f32>, @location(7) joint_weights: vec4<f32>,
#endif #endif
#ifdef MORPH_TARGETS #ifdef MORPH_TARGETS
@builtin(vertex_index) index: u32, @builtin(vertex_index) index: u32,

View File

@ -146,22 +146,30 @@ impl Mesh {
pub const ATTRIBUTE_UV_0: MeshVertexAttribute = pub const ATTRIBUTE_UV_0: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Uv", 2, VertexFormat::Float32x2); MeshVertexAttribute::new("Vertex_Uv", 2, VertexFormat::Float32x2);
/// Alternate texture coordinates for the vertex. Use in conjunction with
/// [`Mesh::insert_attribute`].
///
/// Typically, these are used for lightmaps, textures that provide
/// precomputed illumination.
pub const ATTRIBUTE_UV_1: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Uv_1", 3, VertexFormat::Float32x2);
/// The direction of the vertex tangent. Used for normal mapping. /// The direction of the vertex tangent. Used for normal mapping.
/// Usually generated with [`generate_tangents`](Mesh::generate_tangents). /// Usually generated with [`generate_tangents`](Mesh::generate_tangents).
pub const ATTRIBUTE_TANGENT: MeshVertexAttribute = pub const ATTRIBUTE_TANGENT: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Tangent", 3, VertexFormat::Float32x4); MeshVertexAttribute::new("Vertex_Tangent", 4, VertexFormat::Float32x4);
/// Per vertex coloring. Use in conjunction with [`Mesh::insert_attribute`]. /// Per vertex coloring. Use in conjunction with [`Mesh::insert_attribute`].
pub const ATTRIBUTE_COLOR: MeshVertexAttribute = pub const ATTRIBUTE_COLOR: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Color", 4, VertexFormat::Float32x4); MeshVertexAttribute::new("Vertex_Color", 5, VertexFormat::Float32x4);
/// Per vertex joint transform matrix weight. Use in conjunction with [`Mesh::insert_attribute`]. /// Per vertex joint transform matrix weight. Use in conjunction with [`Mesh::insert_attribute`].
pub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute = pub const ATTRIBUTE_JOINT_WEIGHT: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_JointWeight", 5, VertexFormat::Float32x4); MeshVertexAttribute::new("Vertex_JointWeight", 6, VertexFormat::Float32x4);
/// Per vertex joint transform matrix index. Use in conjunction with [`Mesh::insert_attribute`]. /// Per vertex joint transform matrix index. Use in conjunction with [`Mesh::insert_attribute`].
pub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute = pub const ATTRIBUTE_JOINT_INDEX: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_JointIndex", 6, VertexFormat::Uint16x4); MeshVertexAttribute::new("Vertex_JointIndex", 7, VertexFormat::Uint16x4);
/// Construct a new mesh. You need to provide a [`PrimitiveTopology`] so that the /// 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 /// renderer knows how to treat the vertex data. Most of the time this will be