KhronosGroup / glTF

glTF – Runtime 3D Asset Delivery
Other
7.14k stars 1.14k forks source link

Max bone influences per vertex #1275

Closed donmccurdy closed 6 years ago

donmccurdy commented 6 years ago

This is a tracking issue for supported bone influences per vertex in the glTF ecosystem. We can move it somewhere more appropriate as needed.

Gist: https://gist.github.com/donmccurdy/4cad2039360fbd7cd55d18b3f0428581

donmccurdy commented 6 years ago

From @lexaknyazev's suggestion in https://github.com/KhronosGroup/glTF-Blender-Exporter/issues/167

shakesoda commented 6 years ago

Unity supports 4 bones per vertex, to the best of my knowledge.

(dunno if you're interested in obscure implementations like mine, but mine/love3d also supports 4)

edit: I'm actually not aware of any implementation of gpu skinning that supports >4, but all cpu skinning implementations seem to.

najadojo commented 6 years ago

Windows Mixed Reality supports only 4 bones per vertex.

shakesoda commented 6 years ago

per the docs, looks like Godot supports 4 bones per vertex.

lilleyse commented 6 years ago

Cesium is 4.

donmccurdy commented 6 years ago

Thanks! This is starting to look like a very consistent list. 🤔

meshula commented 6 years ago

Film and research pipelines use four to eight commonly. Film and research people want to view their assets via gltf too :) At the moment I'm expecting to use a second weight set for excess weights as discussed in other threads, but TBH it feels like a hack, and without support being front and center it'll continue to feel hacky I'm sure. In the UsdSkel spec, we decided not to impose a limit, but instead to impose that the weights have a uniform valence across a vertex group, and that they be ordered so that they can be trivially reduced to a lower valence if desired. https://graphics.pixar.com/usd/docs/api/_usd_skel__schemas.html#UsdSkel_BindingAPI_JointInfluences

lexaknyazev commented 6 years ago

@meshula glTF spec doesn't formally limit the number of influences, e.g., one can use JOINTS_0, JOINTS_1, JOINTS_2 to provide 12 joints per vertex. We just say that engines don't have to support more than 4.

they be ordered

Do you mean that they are sorted by weight? I think we can impose such restriction on assets with 8 (and more) influences.

Also related: #1213.

takahirox commented 6 years ago

(Regardless whether we impose the 'ordered' restriction or not) I suggest adding two implementation notes

  1. up to 4 influences is recommended to let the assets be loaded by most of engines without any problems

  2. how engines should handle many influences. For example, picking up largest 4 (max num for the engine) and normalize https://github.com/KhronosGroup/glTF-Blender-Exporter/issues/167#issuecomment-371212574

lexaknyazev commented 6 years ago

With proposed restriction

picking up largest 4 and normalize

will be

use JOINTS_0 and normalize

Otherwise, an engine loading an asset using 8 influences would need to manually pick largest 4 for each vertex which isn't runtime-friendly.

takahirox commented 6 years ago

Yes, the note and loader's impl will be easier if we impose the restriction.

meshula commented 6 years ago

Other associations to multiple sets are explicit, for example if there are two uv sets, a normal map texture will explicitly reference the appropriate texture coordinate set. With the JOINTS_* convention, it seems there might likewise be an explicit binding, to reference say JOINTS_0 and JOINTS_1. It is a solution to clearly state in the implementation notes that JOINTS_0 and JOINTS_1 are to be concatenated. Perhaps a more rigorous solution would be amend the mesh attributes table with that information? https://github.com/KhronosGroup/glTF/pull/901

donmccurdy commented 6 years ago

We've discussed implementing support for 8 influences in three.js, and (at the time) assumed we would do so with an additional vec4 attribute. So the JOINTS_0 ... JOINTS_N arrangement is deliberate, and won't necessarily be concatenated.

lexaknyazev commented 6 years ago

won't necessarily be concatenated.

What do you mean by that? An engine supporting 8 influences would probably use two more attributes so that JOINTS_0 and JOINTS_1 data will end up in the same vertex shader (or in subsequent passes).

donmccurdy commented 6 years ago

I thought perhaps @meshula had assumed that using JOINTS_1 "feels like a hack" because in film and research applications there might be no need to split them into two vec4 attributes, and I was just clarifying that this split actually does have a runtime purpose. If that was in fact the purpose. :) But yes they would presumably end up in the same vertex shader, or literally be concatenated for viewers that do skinning on the CPU.

meshula commented 6 years ago

@donmccurdy From the perspective of splitting the weights into vec4 attributes, and the mission of gltf of being well matched to GL, it makes perfect sense, if that was in fact the purpose :) TBH, I had not considered it from that perspective since my skinning is done on CPU as you guess.

To clarify "feels like a hack", since it sounds somewhat inflammatory :) The semantic usage of JOINTS_1 seems to be implicit, whereas the semantic usage of say TEXCOORD_1 will be explicit because the mesh attributes table will tell me that it is to be used for normal mapping or somesuch. So it feels like a hack because the knowledge of JOINTS_1 interpretation is retrieved from forum threads as opposed to the parsed file itself, or here - https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#skins

Anyway, I'm glad this thread exists to consolidate all the conversation around weights into one place!

donmccurdy commented 6 years ago

glTF spec doesn't formally limit the number of influences, e.g., one can use JOINTS_0, JOINTS_1, JOINTS_2 to provide 12 joints per vertex. We just say that engines don't have to support more than 4.

An engine supporting 8 influences would probably use two more attributes so that JOINTS_0 and JOINTS_1 data will end up in the same vertex shader (or in subsequent passes).

We've said this in threads before, but I just noticed the spec seems to say the opposite:

The number of joints that influence one vertex is limited to 4, so referenced accessors must have VEC4 type ...

lexaknyazev commented 6 years ago

We've said this in threads before, but I just noticed the spec seems to say the opposite:

I'd say that this was overlooked (probably by me) when we have changed semantic name JOINT to JOINTS_0. In the other place, the spec says

Client implementations must support at least ... one joints/weights set.

donmccurdy commented 6 years ago

Moved the data to a Gist (https://gist.github.com/donmccurdy/4cad2039360fbd7cd55d18b3f0428581), I don't think we need to keep this issue open just to record engines' limits.

dmarnel commented 4 years ago

I'm having trouble importing a skinned rig into Oculus Home. It looks like vertices with more than 1 or 2 bone influences cause the skin to deform badly.

donmccurdy commented 4 years ago

@dmarnel if the model works correctly in other glTF viewers (e.g. https://gltf-viewer.donmccurdy.com/, https://sandbox.babylonjs.com/) I think you'll probably need to report an issue to Oculus.

ninjz commented 2 years ago

Is it correct to say single a set of weights per node corresponds to 4 weight influences per node? I'm using Sceneview/sceneform-android which uses Filament under the hood. I've seen here that: "Filament supports only a single set of weights per node (this conforms to the glTF minspec)" so I'm wondering does that mean Filament supports 4 weight influences or 1.

I exported my model through blender exporting all weight influences and it runs fine on BabylonJS sandbox but fails to load/crashes inside of Filament.

donmccurdy commented 2 years ago

@ninjz I think that's correct. I'd probably phrase that as "weights per primitive" rather than "weights per node".

Realtime clients are usually constrained in how many vertex attributes they can allocate (often ≤16 in total, shared by other features the primitive needs) but are required to support at least 4 weights (2 vertex attributes, or 1 "set" of weights here) for skinning. Other implementations of skinning may not depend on vertex attributes but this is the most common situation.

fire commented 1 year ago

Godot 4.0 (beta) supports 8 bone influences.

Thebluedaredevil commented 1 month ago

Unity supports up to 32 bone influences per vertex. This is a fact. glTF is AWESOME. This is also fact.

fire commented 1 month ago

@Thebluedaredevil unity supports unlimited according to https://gist.github.com/donmccurdy/4cad2039360fbd7cd55d18b3f0428581