KhronosGroup / KhronosGroup/glTF
Mesh representation change suggestions, to allow subdivision surfaces, more efficient storage and more clarity
- Dominant language
- HTML
- Stars
- 7.8k
- Forks
- 1.2k
- Avg merge
- 17h 26m
- Merged PRs (30d)
- 5
Description
Hello. My name is Gabor Nagy. I was one of the original 2 designers of Collada, and I started using glTF2.0 a few months ago, in EQUINOX-3D.
As you know, we also use it at Facebook, where I'm a 3D graphics lead.
The format is great! It's super easy to parse, and the spec is nice and clear, but if I may, I'd like to make a couple of suggestions that would improve flexibility and clarity, and would allow for new features, like subdivision surfaces:
**1)** It would be awesome to support separate index arrays for POSITION, NORMAL, etc.
Currently, exporters have to store multiple copies of vertex positions in many cases, producing a "disconnected polygon soup", rather than a clean, connected mesh.
In addition to increasing file sizes, it doesn't allow easy mesh vertex identity checks that are needed for subdivision surfaces / mesh edge data saving, closedness tests, etc.
Instead of just comparing integer indices, import tools have to compare float triplets for equality (kind of a dirty business, with epsilons and sign checks :)), to determine vertex identity.
E.g. if 12 polygons share a vertex (position), but the normals are different, the vertex position (3 floats) must be replicated 12 times. That's a 144 bytes, instead of 12, for the same mesh vertex.
While this is how current GPUs need the data, and it's usually ok to waste RAM on potentially thousands of duplicated vertex positions, it can be a problem when the data is transmitted over the internet, especially on mobile platforms with bandwidth caps and extra fees.
Often, vertices need to be split or otherwise rearranged on input (e.g. if normals are missing, and hard normals must be generated), so the vertex array will change anyway, before it gets to the GPU.
Also, future generations of GPUs may allow separate index lists for vertex positions, normals, etc.
The current format:
```"primitives"
[
{
"attributes"
{
"POSITION":0,
"NORMAL":1
}
"indices":2, // This is outside the "attributes" scope, so only one index array can be specified for all attributes!
}
]
```
This alternative would be the "best of both worlds", it would allow a separate position index array, while still allowing the use a single index array, as well:
```"primitives"
[
{
"attributes"
{
{
"POSITION":0,
"indices":1, // Position has its own index array, so no need to duplicate vertex positions, and mesh vertices can be easily checked for identity, by comparing integer indices
}
{
"NORMAL":2
"indices":4, // We can use a separate index array for normals, or we can use the same as for position, by using the same value here.
}
}
}
]
```
Non-repeating vertex positions would allow us to store mesh edge attributes, like "hardness", which is needed for (creased) Catmull-Clark subdivision.
**2)** It would be great to have a clear separation between texture-space tangents (used for normal mapping) vs. geometric tangents (used for anisotropic shaders).
There are 2 texcoord sets (TEXCOORD_0 and 1), but there's only one TANGENT semantic, which would imply that it's for geometric tangents, but all the examples I've seen, use those for texture-space tangents.
Ideally, texture-space tangents should be packed with their corresponding texcoords. Texcoords could be either VEC2 (S, T) or VEC5 (S, T, TgX, TgY, TgZ), which should be indicated in the accessor.
The current system seems a bit confusing and incomplete.
For example, what if a model uses as anisotropic shader with a normalmap, and thus it needs *both* geometric tangents, and texture-space tangents that are different?
Or, if there are two normalmaps (e.g. a low-frequency + detail). An anisotropic shader + 2 normal maps would need 3 tangent sets.
It's not clear which tangents should be stored in the single TANGENT semantic. And what about the other two tangent sets? There doesn't seem to be a way to store them, at all.
This is why Collada had different semantics for geometric tangents and texture-space tangents.
**3)** I couldn't find a way to specify which texcoord set should be used for a particular texture, when rendering a mesh.
The PBR material allows up to 5 textures (baseColorTexture, metallicRoughnessTexture, emissiveTexture, occlusionTexture, normalTexture), but there are only up to 2 texcoord sets.
Do all 5 textures have to use the same texcoord set, via TEXCOORDS_0? But, then what is TEXCOORDS_1 for?
I see that textures refer to samplers, but samplers only specify filter and wrapping options, but not the texcoord set to be used.
**4)** A minor thing. texcoords are referred to as "UV", but the proper names for texture coordinates in OpenGL are S and T.
U and V are generic, "natural surface parameters" that may or may not be used for texture mapping.
An unfortunate confusion in the industry, like some folks calling mesh bitangents "binormals" :)
Thank you, and please keep up the great work on this awesome new standard!
Contributor guide
Research direction
No repository file or test is named. Start with the glTF 2.0 sections for mesh primitives, attributes and indices, tangents, and material texture coordinates described in the issue; assess each of the four proposals against the current specification. Done would require a maintainer decision on the proposed format changes and corresponding specification updates if accepted.
Written by the indexing model from the issue text.
Assessment
- Domain
- computer-graphics
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100