FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[PROPOSAL] Khronos Avatar Extensions - Phase 1 by Kjakubzak · Pull Request #2512 · KhronosGroup/glTF · GitHub

[PROPOSAL] Khronos Avatar Extensions - Phase 1 - #2512

Draft
Kjakubzak wants to merge 71 commits into
KhronosGroup:mainfrom
Kjakubzak:kjakubzak/avatar_ext
Draft

Kjakubzak wants to merge 71 commits into
KhronosGroup:mainfrom
Kjakubzak:kjakubzak/avatar_ext

Conversation

Kjakubzak commented Jul 28, 2025
edited
Loading

Copy link
Copy Markdown

Pull Request Draft: KHR Character and Avatar Extension Set – Phase 1

Summary

This PR introduces the initial suite of KHR_character and KHR_character_avatar extensions, a collaborative effort between the Khronos 3D Formats Working Group and the VRM Consortium (VRMC). These extensions aim to provide a structured and interoperable foundation for representing character and avatar models in the glTF ecosystem across platforms, runtimes, and tooling pipelines.

Motivation

Characters and Avatars have emerged as a core content primitive in real-time applications including gaming, virtual reality, social communication, streaming, and telepresence. Yet, there has been a lack of standards around them to express key character/avatar-specific behaviors such as:

  • Denoting a model is, in fact, a Character or Avatar.
  • Facial expressions/visemes
  • Skeleton/Rig utilities
  • Per-mesh metadata annotations
  • Model runtime rendering characteristics (e.g. first person versus third person)

To address this, the Khronos 3D Formats Working Group and VRMC have collaboratively designed a modular set of extensions for avatar assets. With these, we aim to provide creators and developers with a standard representing an expectation in data and functionality per-avatar that can be used across platforms; like building blocks.

Characters
A 3D model representing a potentially interactable, controllable, and/or generally animatable entity.

Examples include user avatars, characters in animated entertainment, NPCs in games controlled by behavior systems, virtual agents embodying a character, etc.

Avatars
A type of Character which is embodied and controlled by a user, representing that user’s identity.

Examples include user-driven characters in third-and-first person experiences, VR scenarios with full-body embodied avatars, 2D telecommunication scenarios with embodied characters representing other users, etc.

Phase 1 Scope

The extensions in this PR represent the Phase 1 Extensions (and more); as outlined in the Khronos Avatar Extensions Working Document.

Core Extensions

  • KHR_character – Root-level flag denoting a character model glTF asset.

Update 12/12 - The below was delayed to a future extension set proposal

  • KHR_character_avatar – Extension built on top of KHR_character denoting a model is intended for use as an avatar.

Expression Extensions

Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent.

For examples of relevant types of expressions, you can reference concepts such as:

  • Visemes (visual representations of mouth movements for parts of speech)
  • FACS (Facial Action Coding System; which is a system intended to describe visually distinguishable facial movements)
  • VRM's Expression presets [reference here] (which express larger "emotion-driven" facial units)

Expression Extensions - Core

All rely on standard glTF animations, and target different control domains:

  • KHR_character_expression_morphtarget
  • KHR_character_expression_joint
  • KHR_character_expression_texture

Character expressions conform to 0-to-1 float values on top-level as ‘drivers’ in a similar way to how morph targets are typically used.

Any key-framed animation (whether joint, morph target, or animation_pointer) still relies on the 0.0-to-1.0 float property; which then interpolates between the N keyframes (e.g. For N keyframes, treating the 0-index keyframe as 0.0, and the Nth keyframe as the 1.0 state. For 1 keyframe, it interpolates between the target model property at rest and that keyframe).

Regardless of the above, we still want to respect creator-defined default values for the morph targets. This may result in some clipping/mesh weirdness when being driven in an experience, but it’s the trade that an avatar creator makes.

For properties represented in the animations not covered by the animation expression extension type:

For each expression-mapped animation; it checks what extensions are present to inform what channels are expected to be animated or not.

As an example, if an animation contains a weight channel, but there’s no *expression_morphtarget extension; the expectation would be that it won’t animate that channel.

Expression Extensions - Metadata-adjacent

  • KHR_character_expression_mask – Defines how one expression masks or blends with another (e.g. keeping emotional expressions from conflicting with lip-sync phonemes), so expression conflicts resolve deterministically from the asset
  • KHR_character_expression_mapping – Common expression vocabulary normalization

Skeleton/Rig Extensions

  • KHR_character_reference_pose – Tags a single-frame glTF animation as a canonical reference pose (local-space TRS) for retargeting and cross-tool consistency
  • KHR_character_skeleton_mapping – Maps joints between arbitrary rigs (1:1), referencing joints by node index (glTFid) rather than by name.

Update 12/12 - The below was delayed to a future extension set proposal

  • KHR_character_skeleton_biped – Declarative semantic labeling of a bipedal skeleton

General Extensions

The below are added as part of this as they provide value to characters and avatars, but are not tied enough to be in the direct namespace. We are still presenting them as part of phase 1 due to our belief they are a net-positive add.

Mesh Annotation Extensions

Update 12/12 - The below were delayed to a future extension set proposal

  • KHR_mesh_annotation – General-purpose semantic tags per mesh primitive
  • KHR_mesh_annotation_renderview – Describes render-time visibility for first and third person view modes

Transform Extensions

**Update 04/20 - KHR_virtual_transform (originally proposed) has been decomposed into focused, single-purpose node extensions:

  • KHR_node_lookat_target – Declares a node as a gaze/look-at target so runtimes (and other extensions) can drive eye/head aim toward it. Includes example diagrams (layered gaze targets, target-constraint architecture, VRM integration pipeline) and additional usage examples for character-related constructs.
  • KHR_node_camera_hint – Declares recommended camera framing for a character or scene element (e.g. preferred portrait/full-body framing). Updated with concrete recommendations and schema refinements.

Visibility Extensions

Added in response to VRM feedback that, without a portable first-person/third-person visibility mechanism, the set felt incomplete — VRM's firstPerson mesh annotations had no glTF equivalent. These generalize that intent, one builds on KHR_node_visibility, and share view-context tokens with KHR_node_camera_hint. Roles are always / first_person / third_person, and 'custom'; which is similar to how we structured KHR_node_camera_hint (enabling custom properties that are runtime-specific/targeted).
.

  • KHR_node_visibility_hint – Annotates a node (and its subtree) with a view-context role — e.g. hide the head/hair when the camera is inside the head in first person.
  • KHR_mesh_primitive_visibility_hint – The same role vocabulary at single-primitive granularity, for view-context geometry baked into a shared mesh that has no node to hide. Kept as a separate extension so a model that depends on per-primitive hiding can list it in extensionsRequired independently. For game engines and implementations without this support, the recommendation is to leverage material swapping for this purpose on a per-primitive basis.

These address the first/third-person visibility need (previously explored via the now-deferred KHR_mesh_annotation_renderview) in a focused, node/primitive-level form.

Design Principles/Philosophies

  • Modular and layered: Aiming for extensions in similar categories to be built on each other where it makes sense, and independent of one another where it doesn’t. Layering on top of the baseplate extensions (KHR_character for character specific and KHR_character_avatar for avatar-specific functionality) where possible when the functionality makes sense only in the context of a character and/or avatar.

  • Aiming to be compatible with VRM and other avatar ecosystems, with an overall goal in this phase to not unnaturally force existing avatar systems to conform to vocabularies and hierarchies.

  • Enabling a self-describing character/avatar - extensions indicate what data types are contained and need to be driven to animate/embody/power the character upon being loaded. Additionally, mapping extensions and other proposed metadata extensions are used to assist in enabling the character’s general compatibility with a loaded-into runtime.

  • Recurring patterns - For example, with the expressions extensions the goal was to create a recurring expectation as to how to access the animation channels/fields. With these extensions (and future ones), all expression channels utilize glTF’s animation model (weights, rotation, translation, scale, and KHR_animation_pointer for other properties).

  • Enabling VRM to adopt these extensions out of the gate. We have a longer-term convergence plan, and VRM utilizing the proposed extensions here as needed is part of it.

Delayed to a Future Proposal

After working group discussion and per-thread feedback, the following originally proposed extensions have been deferred to a follow-up extension set so Phase 1 can land on the most polished, well-scoped surface:

  • KHR_character_avatar – Delayed pending more specific avatar-only use cases.
  • KHR_character_skeleton_biped – Delayed pending further alignment with industry rig vocabularies (see Open Questions).
  • KHR_mesh_annotation – Delayed while we evaluate whether EXT_structural_metadata should be recommended for this purpose.
  • KHR_mesh_annotation_renderview – Folded into a future LOD / Renderview extension set proposal (context).
  • KHR_node_attach_point – Briefly drafted as part of the KHR_virtual_transform decomposition, but removed after working group discussion as not yet sufficiently fleshed out.
  • KHR_virtual_transform – Replaced by the decomposed KHR_node_lookat_target and KHR_node_camera_hint extensions above.

Future Work

Phase 2 will contain more sets of functionality that the community will help inform! Right now, here are some topic areas we're thinking of:

  • LOD management and assignment for mesh and skeleton data
  • Camera position recommendations
  • Runtime clothing customization / mesh switching
  • Introducing a new Material Model for Toon-like avatars
  • Working out the physically-driven secondary motion story with VRMC and the upcoming physics extensions.
  • Material-based Expressions
  • Animations/Emotes
  • Exploring additional runtime functionality-informing extensions, such as sitting (e.g. https://github.com/omigroup/gltf-extensions/tree/main/extensions/2.0/OMI_seat)

In parallel to Phase 1 and Phase 2, we’re currently engaging with the Metaverse Standards Forum and AOUSD in order to start conversations around potential standards for rigs/expressions (around vocabularies). These are, by nature, longer conversations.

Because of that, we’re going to continue to make progress on this set of extensions (in phase 1 and 2), and keep in mind the design that it should be able to support any future standards around vocabularies and rigs.

Open Questions to the Community

We would love feedback on several topic areas!

Expression-Based Mesh Activation

Should activation/deactivation of nodes or submeshes based on expressions (e.g., switching between open/closed eyes or toggling glasses) be included in the expression extension family, or separated into a visibility/scene control extension?

Ideally, we'd then be utilizing the in-progress EXT_node_visibility proposal.


Fallback Skeleton Mappings

**TL;DR - We're going to be working with AOUSD and the Metaverse Standards Forum and foster discussion on industry rig/expression vocabularies. Because of this, we don't believe we should enforce this in this phase.

Discussion Link 1 Discussion Link 2**

Should we fallback to any known skeleton mappings when the skeleton_mapping extension is used on the DCC/Content Tooling side? Is VRM's Humanoid something the community feels okay with ratifying, or is the Unity origin something that makes that less desirable? Should we fall back to the OpenXR Skeleton definition?

VRM 1.0 Humanoid

OpenXR Skeleton

LookAt Implementation: Separate or Virtual Transform?

Should a standardized LookAt construct (like VRM’s LookAt extension) be:

  • Modeled as a standalone extension, or
  • Encoded through a virtual transform?

Both options are currently viable.


Avatar vs Character Namespaces

With feedback from the community, we’ve made the decision to transition to having KHR_character be the base namespace, with KHR_character_avatar denoting a model is an avatar!


Are we missing anything obvious for our V1 set of Extensions proposed here?

We'd love to hear back as to whether we should consider adding more extensions overall to this proposal; or if any changes are needed!


References

License

All extensions in this PR are licensed under the Khronos Group glTF Extension License.

Updated skeleton_biped

Updated mapping README

updates

Fixing contributors list as well as some logical errors in the extension schemas
Kjakubzak marked this pull request as draft July 28, 2025 17:47

DRx3D commented Jul 29, 2025

Copy link
Copy Markdown

In the Summary section where VRM Consortium is used add " (VRMC)" so usage later in the document is clear.

aaronfranke left a comment
edited
Loading

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Where are the schemas and example files? They are missing from this PR.

I was under the impression that the Khronos avatar extensions were going to be a superset of the features provided by the VRMC extensions, but most of the good stuff from VRMC is missing here, such as spring bones and constraints.

This extension defines a 1-to-1 mapping between avatars and scenes. Most glTF implementations will only load a single scene per file. This definition explicitly prohibits having 2 avatars in a scene, and glTF does not provide a mechanism for one scene to be used in another scene. Now, in practice, people using glTF for interchange of 3D models will typically only have one avatar per file, and load multiple glTF files for multiple avatars - but I was under the impression that Khronos wants to allow single glTF files to be used as a last-mile delivery format, where the whole scene, including potentially multiple avatars, is all represented in one file. So, the question that need answering: Is it a stated goal of KHR_avatar to only allow one avatar per glTF scene/file, and is this goal isolated from the goals of KHR_interactivity and such?

Also, see #1542 - support for multiple scenes in a glTF file is extremely rare, and folks like @donmccurdy have mentioned that this could be removed if there was another compatibility breakage. Even if that won't ever happen, I would recommend avoiding building atop this "feature". Khronos's own implementations do not handle multiple scenes per file correctly - such as the Blender importer, which imports multiple scenes as collections, even though Blender itself has a multiple scenes feature.

fire commented Jul 29, 2025

Copy link
Copy Markdown

but I was under the impression that Khronos wants to allow single glTF files to be used as a last-mile delivery format, where the whole scene, including potentially multiple avatars, is all represented in one file. So, the question that need answering: Is it a stated goal of KHR_avatar to only allow one avatar per glTF scene/file, and is this goal isolated from the goals of KHR_interactivity and such?

This is a point of contention as I want to be able to export an entire scene with let's say 15 avatars.

fire commented Jul 29, 2025
edited
Loading

Copy link
Copy Markdown

Where are the schemas and example files? They are missing from this PR.

Incorrect formatting. I recommend installing an IDE extension to automatically format, so these problems can be automatically solved without thinking about it.

For openness and collaboration, I and others have encouraged the early publishing of this draft pull request despite its incompleteness.

I hope that you understand that reaching for the better design is better done early, and together rather than avoiding superficial errors.

Edited:

There are parts of the story that are personal information. It is also not cool to ask for more interaction and then complain about the work's lower quality that is tradeoff for rapid response. Note that some of the contributors to Khronos Group aren't paid and/or volunteering time and effort.

Kjakubzak commented Jul 29, 2025
edited
Loading

Copy link
Copy Markdown
Author

Where are the schemas and example files? They are missing from this PR.
Incorrect formatting. I recommend installing an IDE extension to automatically format, so these problems can be automatically solved without thinking about it.

For openness and collaboration, I and others have encouraged the early publishing of this draft pull request despite its incompleteness.

I hope that you understand that reaching for the better design is better done early, and together rather than avoiding superficial errors.

Edited:

There are parts of the story that are personal information. It is also not cool to ask for more interaction and then complain about the work's lower quality that is tradeoff for rapid response. Note that some of the contributors to Khronos Group aren't paid and/or volunteering time and effort.

Yeah, frankly I just quickly installed VSCode on my personal computer to crunch this out while recovering from a recent procedure. You're not wrong; I should have been more diligent with formatting. Let me get to that in the next day, apologies.

Copy link
Copy Markdown
Contributor

Avatar vs Character Namespaces

Many extensions—such as bind poses, skeleton mapping, and procedural expressions—are useful for general character models, not just avatars.

I agree with @fire's comment above about it being useful for some use cases to have multiple characters in a single glTF scene. There could be 1, 2, 15, 317, or any other amount. These characters don't necessarily need to all be human-controlled "avatars", they could be NPCs in a scene. Such NPCs have similar requirements, like retargeting, as mentioned. Or, they could be characters that human players switch between. In either case, "character" seems fitting to me.

- Added Nick Burkard to the list of contributors
- Changed Verbiage where needed to ensure there's no implication of a vocabulary definition as part of the phase 1 set of extensions.
- Resolved as many formatting concerns as possible

Copy link
Copy Markdown
Author

Avatar vs Character Namespaces

Many extensions—such as bind poses, skeleton mapping, and procedural expressions—are useful for general character models, not just avatars.

I agree with @fire's comment above about it being useful for some use cases to have multiple characters in a single glTF scene. There could be 1, 2, 15, 317, or any other amount. These characters don't necessarily need to all be human-controlled "avatars", they could be NPCs in a scene. Such NPCs have similar requirements, like retargeting, as mentioned. Or, they could be characters that human players switch between. In either case, "character" seems fitting to me.

I think a discussion around scene usage is probably due; especially given your concerns around it initially. I was a bit hesitant around its usage; I suspect this will be something that we need to get takes from the wider community on.

I agree I can see the use-case here; but if it's going to cause problems for adoption or tooling it might end up being a non-starter.

Frankly, I've been out of practice with git for far too long, and have forgotten that git commits for a PR are more...eternal than my current active workflow.

0b5vr commented Jul 29, 2025

Copy link
Copy Markdown

I was under the impression that the Khronos avatar extensions were going to be a superset of the features provided by the VRMC extensions, but most of the good stuff from VRMC is missing here, such as spring bones and constraints.

I believe we are currently defining feature sets that can be specified with a basis. Features like spring bones or toon materials need more discussion.


## Overview

The `KHR_avatar_mesh_annotation` extension enables arbitrary per-mesh metadata annotations for avatar models. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I'm yet to grasp the intention of the extension, in contrast with KHR_avatar_mesh_annotation_rendering which has a clear behavior purpose. We probably need more real-world examples.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I can add more examples here in the near future. I've seen specific runtime needs across numerous implementations where things like mesh annotations would have assisted. It's not a top-priority extension by all means, but this does assist where runtime logic would benefit from mesh annotations/tagging.

Top-of-the-head example around accessories; there may be experiences or sub-instances within an experience that changes how the user/character/avatar interacts or perceives the experience. More specifically, say you have a character or avatar in a desert experience where the developers, for some reason, adjust shader parameters based on whether the character has sunglasses. With a metadata label denoting what a submesh or given mesh is (in this case, sunglasses), it removes a few steps for avatar creators and developers to enable scenarios like this.

That being said; this then of course leads to a "Not every experience shares a vocabulary" scenario; but at least this helps start that conversation in terms of asset labeling.

Comment on lines +95 to +99
"source": "myRig_leftFoot",
"targets": [
{ "joint": "leftFoot", "weight": 0.8 },
{ "joint": "leftToeBase", "weight": 0.2 }
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I'm afraid such one-to-many mapping might not be supported by the humanoid skeleton system in Unity. I feel like it needs a component like constraints or custom scripts, and it probably overcomplicates the implementation. I want to check the demand volume before having this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I agree, we should only have one-to-one mapping.

As an example use case, digitigrade legs on a furry character have 3 segments, but humanoid rigs have legs with 2 segments. There is a simple solution commonly used for this case: having a separate set of bones with no mesh attached, use those for the humanoid skeleton, and then use constraints to copy the transforms of the humanoid bones to the real bones, with the upper and lower leg segments both copying the humanoid thigh, where the humanoid thigh's bone length is the sum of the upper and lower leg segments. You might look at this and think that it would be nice to be able to semantically map both leg segments as the humanoid thigh, but in practice that doesn't add value. IK systems expect to work with 2-segmented humanoid legs, and full body tracking systems use real human legs as their input data, which are 2-segmented. I don't know if more complexity in the specification could improve upon what already works as a general solution. Adding the fake bones as glTF nodes and adding the constraints would only be a few hundred bytes of JSON in the glTF, and keeps implementations simple.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@0b5vr Agree that we should identify the demand volume. Let me add it to the open questions in the next day or so.

I don't think we should necessarily limit ourselves based on whether engines support this natively or not at the time of publishing. Agreed that it then leads to custom scripts/constraints; but if we provide utility that then leads to adoption, we hopefully can generate enough interest to get native support for it added.

Right now, there are several platforms where getting a custom/bespoke avatar to adhere to platform expectations typically requires switching to the rig hierarchy of that platform. This is also the case in many smaller experiences. If a given character/avatar was designed with a reduced rig in mind, this then means that the creator has to redo a large amount of work for platform compatibility.

In the case of one-to-many; spine and neck joint mappings immediately come to mind. If a creator has 3 spine bones initially, and a platform expects 5; this extension can provide the mapping to the expected 5 and enable distribution of the animation values across the target 3 (creating a smoother animation for the reduced rig set)

Perhaps part of this extension should also indicate what portion of the joint movement is desired (translation, rotation, scale). That level of granularity would likely assist in a variety of scenarios.

@aaronfranke; while that's definitely a solution, it sounds like it's orthogonal to what's being proposed here; both could exist. If anything, it sounds like the extension could actually assist with your scenario, as you could then leverage it with the scripts you're using for the retargeting for the initial mapping step (Unless I'm missing something).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I agree with the opinion that, from the perspective of glTF portability, this extension should support only 1:1 mapping.

If my understanding is correct, glTF places importance on portability, meaning that it is desirable to obtain the same results in any environment. In other words, it is preferable that any platform can handle the specification smoothly and easily.

When considering the glTF specification, I saw many discussions from the perspective of whether major platforms and engines would be able to process it without problems, and in some cases, even for features that seemed to have high demand, adoption was postponed if there were engines for which processing seemed difficult.

If it is an extension, those portability requirements may be somewhat relaxed, but if we aim for a standard KHR extension, it would be desirable to aim for the same level of portability.

I don't think we should necessarily limit ourselves based on whether engines support this natively or not at the time of publishing. Agreed that it then leads to custom scripts/constraints; but if we provide utility that then leads to adoption, we hopefully can generate enough interest to get native support for it added.

For the above reasons, I have a different view. If there are definitions that are not easy to process, support for the extension itself may not progress and its spread may be hindered, and I think that self-imposed limitations are in fact an important element for glTF. The fact that processing expected on a particular platform may no longer be reproducible in glTF, or that creators may have to redo their work, is, to some extent, an unavoidable sacrifice for standardization. Striking the right balance is the key element.

If we want to generate interest, I think there is the option of defining it as an EXT or vendor extension with a lower degree of standardization. The KHR extension would support only 1:1 mapping, the EXT/vendor extension would extend the KHR extension to also support one-to-many mapping, and on platforms that do not support the EXT/vendor extension, the KHR extension would be the fallback. This scenario would keep the problem small while providing engines, etc., an opportunity to try one-to-many mapping.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I think the discussion would go more smoothly if the rules, or at least clearer guidelines or policies, on what these extension suite does and does not cover were made more concrete. This includes not only the 1:1 mapping but also the discussion around auto.

Personally, since these are standard KHR extension suite that many engines are likely to implement and use for various purposes, I think anything that is hard to implement or becomes complex on certain platforms (especially major ones), or is likely to cause performance issues in real-time runtimes, should be considered out of scope. If needed, we could consider a separate, lower-standard extension.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I think it's going smoothly, all things considered. Honestly, the discussion around this proposal is what I'd expect the back-and-forth on extensions such as this to be.

I believe the extensions are pretty self-contained in terms of what they do and don't do; and the discussion up until now has improved the overall documentation and proposal as you've all asked for more clarity (which I appreciate). What other items are not clear; do you have any other examples that I can try to address?

In the case of 'auto', it currently is not present in the extensions (and hasn't been in any iteration).

In the case of 1-to-1 mapping versus 1-to-many; I've removed the latter for now as it's more appropriate to introduce it in a later phase (as part of the longer-term character extensions), with additional accompanying extensions for remapping/retargeting and informing motion systems. You're correct that there are potential performance issues in rare edge cases (like mapping every joint to every other joint). Do you see other performance concerns, and can you go into more details around the difficulties of implementing support for this?


| Property | Type | Description |
|------------------|-------------|-----------------------------------------------------------------------------|
| `renderVisibility` | string | Controls camera-based visibility. Enum: `"always"` | `"firstPersonOnly"` | `"thirdPersonOnly"` | `"never"` |

0b5vr Aug 1, 2025
edited
Loading

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

auto exists in the VRM FirstPerson spec. Its behavior is to remove vertices that have a weight associated with the humanoid head at runtime.
https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/firstPerson.md

There are several challenges to introducing auto in the KHR_avatar spec:

  • We must associate the skeleton extensions with the mesh annotations extension to define which bone is head.
  • We must recommend or define how the runtime should hide the head polygons.
  • Having a separate mesh before exporting would be more efficient than hiding polygons at runtime, and this might be the recommended way as a standard.

However, it's true that many VRM avatars already depend on auto.

I believe that VRChat users also don't specify first-person mesh annotations by themselves. There is a component called VRCHeadChop that specifies which mesh should be hidden in addition to the head in the first-person view.
https://creators.vrchat.com/avatars/avatar-dynamics/vrc-headchop/

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I'm a little afraid of introducing Auto, as it introduces platform-to-platform differentiations (which perhaps is fine, but needs to at least be noted), even with recommendations. There's also then the challenge of runtimes then meeting creator expectations. That being said; I can see how this then makes the user workflow easier.

Totally understand that they don't denote it themselves for VRChat; that being said, I think having a component being added for this is functionally the same as them annotating the mesh (albeit on a higher level given it then happens in-engine).

Do we feel as though VRM could continue to have Auto as part of an VRM-specific extension on top of this one, or do we absolutely need to have it in this extension?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I checked the spec of auto in VRM FirstPerson, and I think it would be better not to include it in this extension. The implementation seems a bit too complex.

If my understanding is correct, there are issues such as:

  • Heavy per‑vertex processing, which raises performance concerns in runtime environments like viewers.
  • Potential complexity from mesh splitting, which could complicate other extensions as well as core glTF Mesh/Node processing.
  • Cross‑extension dependencies (even within the KHR_avatar extension suite). Extensions without dependencies and higher independence are simpler and preferable.

Since this avatar/character extension suite seems to be aiming for standard KHR extension, I personally think it’s better to define a low‑complexity and easy‑to‑implement specification. As a result, the extensions can be more likely to be supported across many environments and see broader adoption.

If auto is desired, I personally feel it would be more appropriate as a vendor extension maybe that extends this one.

{ "target": "spine", "weight": 0.5 },
{ "target": "chest", "weight": 0.5 }
],
"JawJoint": [{ "target": "jaw", "weight": 1.0 }]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

One of the VRMC members points out that the jaw should no longer be included in the humanoid skeletons since it should rather be controlled by expressions.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I think that depends on the implementation/use-case. I think it's totally fair to have a bone in the skeletal hierarchy (and an understanding as to how it maps) even with an expression that potentially powers it.

Copy link
Copy Markdown
Contributor

Thank you for the important proposal. I’ve long wanted a standardized and reusable humanoid skeletal definition in glTF, so this is a very interesting proposal for me.

Since the proposal covers a lot and the discussion has already grown quite long, I may have missed some parts of the conversation, but I’d like to start by sharing a few of my thoughts. Apologies if any of this has already been outdated.

This may tie into the topic of Avatar vs Character, but I’m wondering whether functionality that is not specific to avatars could be actively separated from the Avatar extension and defined as its own general-purpose extensions. Then those could serve as foundational extensions, with the Avatar extension built on top of them.

If we first focus discussion and review on those foundational extensions, then move on to the Avatar-specific ones afterward, I believe we could progress through the specification process more smoothly. While the proposal is divided into phases, I personally feel that with so many extensions being proposed at once for Phase 1, it has become difficult to keep the discussion focused. I understand the intent was to gather broad feedback by sharing the proposal early, but for those who join later, the volume of information makes it quite hard to catch up with the ongoing discussion. Would it be possible to treat the general-purpose foundational extensions as a sort of “Phase 0”?

0b5vr commented Aug 1, 2025

Copy link
Copy Markdown

If we first focus discussion and review on those foundational extensions, then move on to the Avatar-specific ones afterward, I believe we could progress through the specification process more smoothly.

While I generally agree with the idea that we should consider each component step by step, there seem to be cases where we should think about the final imagery that multiple extensions cooperate to prevent overlooking features essential to our purpose, like the mesh annotation: "auto" discussion:
#2512 (comment)

Copy link
Copy Markdown
Author

Thank you for the important proposal. I’ve long wanted a standardized and reusable humanoid skeletal definition in glTF, so this is a very interesting proposal for me.

Since the proposal covers a lot and the discussion has already grown quite long, I may have missed some parts of the conversation, but I’d like to start by sharing a few of my thoughts. Apologies if any of this has already been outdated.

Absolutely no worries; we really have just started this conversation! Feel free to jump in with your concerns, even if they echo the concerns that have already been stated by others. Hearing back from the community will help us make informed decision/changes to the spec as it evolves!

This may tie into the topic of Avatar vs Character, but I’m wondering whether functionality that is not specific to avatars could be actively separated from the Avatar extension and defined as its own general-purpose extensions. Then those could serve as foundational extensions, with the Avatar extension built on top of them.

I agree with this conceptually, but we'd need to have consensus that the extensions themselves are general purpose enough to be separated from the avatar extension set. Right now I'm not entirely sure what could be considered general purpose enough (other than perhaps the KHR_avatar_mesh_annotation extension).

What portions of these would you consider as a general-use phase 0 set of extensions?

While I generally agree with the idea that we should consider each component step by step, there seem to be cases where we should think about the final imagery that multiple extensions cooperate to prevent overlooking features essential to our purpose, like the mesh annotation: "auto" discussion:

+1 to this; given the composition it might become harder to separate out than initially thought.

"jointBindPoses": [
{
"joint": 0,
"matrix": [

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

There's likely a better way to represent this via an additional skin object with a different skeleton and InverseBindMatrices reference for the A/T/Custom Pose.

Kjakubzak and others added 6 commits April 6, 2026 10:28
After discussion with the working group, this has been punted due to not being as fleshed out as desired.
We've decomposed it into two focused extensions for look_at and camera_hint.
Merging decomposed extensions into avatar extension branch; deleting KHR_virtual_transform and replacing it with KHR_node_camera_hint and KHR_node_lookat_target extensions.

0b5vr commented Jun 9, 2026

Copy link
Copy Markdown

@Kjakubzak When I was discussing about KHR_character_skeleton_mapping at my work, my coworker pointed out that glTF node might have duplicated name. His recommendation is to explicitly note that the first appeared node will take precedance when there are two or more nodes with the same name.

Kjakubzak commented Jun 25, 2026
edited
Loading

Copy link
Copy Markdown
Author

@Kjakubzak When I was discussing about KHR_character_skeleton_mapping at my work, my coworker pointed out that glTF node might have duplicated name. His recommendation is to explicitly note that the first appeared node will take precedance when there are two or more nodes with the same name.

Hi @0b5vr -san! I didn't see this until now; apologies for the long turnaround. Yes, this is definitely a case that would be hit. I agree with the guidance suggestion; but wonder if it may make sense to also provide the node index in the key value being mapped.

Instead of:

"hip_bone": "myRig_hips"

It'd be:

"hip_bone": { "node": 0, "name": "myRig_hips"}

(exact field names tbd)

0b5vr commented Jun 26, 2026

Copy link
Copy Markdown

@Kjakubzak I should've reminded in the meeting, my bad!

Instead of:

"hip_bone": "myRig_hips"

It'd be:

"hip_bone": { "node": 0, "name": "myRig_hips"}

(exact field names tbd)

That would solve the duplicated name issue for sure but, if we do this to disambiguate the node reference, I think it would be simpler to use indices in the first place, considering the existing glTF conventions to reference things.

Kjakubzak added 4 commits July 6, 2026 16:36
…de name

Change the asset-relative mapping value from a node-name string to a glTF node index (glTFid), mirroring KHR_character.rootNode. Updates the schema (innermost value string -> glTFid \) and the README (example, structure table, implementation notes).
Merging extension iterations into PR branch

Kjakubzak commented Jul 14, 2026
edited
Loading

Copy link
Copy Markdown
Author

A few updates in this iteration:

Added two view-context visibility extensions:

  • KHR_node_visibility_hint — a role (always / first_person / third_person) on a node and its subtree.
  • KHR_mesh_primitive_visibility_hint — the same roles at single-primitive granularity, for hiding individual primitives of a multi-primitive mesh without having to split the mesh into separate primitives/nodes (e.g. draw-call-merged meshes, shared skinning, or anywhere splitting isn't desirable).

KHR_node_visibility_hint builds on KHR_node_visibility and both share view-context tokens with KHR_node_camera_hint (so activating a first-person camera hint knows to hide third_person geometry). They were added in direct response to VRMC feedback that, without a portable first-/third-person visibility mechanism, the set felt incomplete — VRM's firstPerson mesh annotations had no glTF equivalent.

FWIW, the node implementation was the immediate ask from VRMC, and the primitive version is a lower-level implementation introduced for scenarios and runtimes that support more granular manipulation.

For a future step, I could see us wanting to increase the coverage of the vocab to reflect the camera-hint vocab 1:1 with these extensions (as right now it's a subset).

KHR_character_skeleton_mapping now references joints by node index (glTFid) instead of by name — unambiguous and consistent with the rest of glTF.

Kjakubzak requested a review from aaronfranke July 16, 2026 18:34
aaronfranke dismissed their stale review July 28, 2026 00:07

The unresolved things I mentioned are out-of-scope, and the rest looks good to me at a glance. I have not done a comprehensive review, so I am not giving this an approval, just dismissing my requested changes.

Copy link
Copy Markdown
Author

The following public implementations exercise the proposed KHR_character extension family:

Three.js Testbed

0b5vr/khr-character-testbed (https://github.com/0b5vr/khr-character-testbed/tree/main)

Provides:

  • Three.js loading and visualization.
  • VRM-to-KHR_character conversion.
  • Character expressions.
  • Skeleton mapping and retargeting helpers.
  • Camera-hint support.
  • Reference assets for browser-based testing.

Unity Testbed

Kjakubzak/khr_character_testbed (https://github.com/Kjakubzak/khr_character_testbed/tree/khr_character_texture_transforms)

Provides:

  • Unity sample scenes and generated test assets.
  • KHR_character metadata and root-node examples.
  • First- and third-person node visibility.
  • Mesh-primitive visibility.
  • Camera hints and look-at targets.

UnityGLTF Implementation

Kjakubzak/UnityGLTF, catsg_khr_character_testbed (https://github.com/Kjakubzak/UnityGLTF/tree/catsg_khr_character_testbed)

Provides the underlying UnityGLTF implementation used by the Unity testbed:

  • Import and export.
  • Runtime expression evaluation.
  • Authoring components.
  • Reference-pose and skeleton mapping.
  • Visibility, camera, and look-at support.
  • Automated runtime, import, export, and round-trip tests.

The Unity testbed pins the implementation to commit eff6ec3f (Kjakubzak/UnityGLTF@eff6ec3).

Together, these projects provide two independent runtime implementations, in Three.js and Unity, plus generated assets and automated tests. We'll be creating branches for glTF-Validator support next.

0b5vr added a commit to 0b5vr/khr-character-testbed that referenced this pull request Aug 3, 2026
Kjakubzak added a commit to Kjakubzak/glTF that referenced this pull request Aug 5, 2026
KhronosGroup#2512 (comment)

Delaying and will add to the above-mentioned LOD/Renderview extension set proposal we'll be iterating on in the future.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.


Back | FazBrowse Home | New Git URL