Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b529179
Initial draft.
Mar 14, 2019
ebe3189
Updates.
Jul 26, 2019
9033116
Consistant naming.
Jul 26, 2019
ee0d8ad
Rename back, tweak.
Sep 26, 2019
b7c68e3
Tweaks.
Oct 7, 2019
fd070c3
Some further verbiage.
Oct 7, 2019
92771ff
Add formal schema.
Oct 7, 2019
ca97835
Merge branch 'master' into ext/zell-fb-asset-variants
Oct 7, 2019
69b7edf
Merge remote-tracking branch 'upstream/master' into ext/zell-fb-asset…
Oct 7, 2019
8e5d8b1
Language tweaks, update Renee's contact info.
Oct 7, 2019
f0ab429
One more try.
Oct 7, 2019
a9bee21
Clarifications, expansion.
Oct 22, 2019
23915e9
Rename as khronos extension KHR_variant_materials
jercytryn Mar 9, 2020
07c109b
Rename extension KHR_variant_materials -> KHR_materials_variants
jercytryn Apr 14, 2020
46b16fc
Fix typos, non-normative disclaimers, and clarify tag order behavior …
jercytryn May 8, 2020
17fe9bd
Simplify extension to focus on wholesale static variant configuration…
jercytryn Jul 18, 2020
910746f
Fix example melded models
jercytryn Jul 24, 2020
b84ae8a
Clarifying note on no active variant
jercytryn Jul 31, 2020
fc9b8d9
Update README.md for alt text.
Aug 20, 2020
60be860
Apply 3D Commerce patch to schemas and spec.
Aug 21, 2020
09a22ce
Updated README, removed examples, and fixed mappings in spec along wi…
sleroux Aug 24, 2020
26d2629
Add new language defining mappings usage within viewer applications
jercytryn Aug 24, 2020
8543426
No relative paths and fix typo
jercytryn Aug 24, 2020
9bc4e4e
Bridge verb
jercytryn Aug 24, 2020
9049ea8
Change to top-down language to describe the specifics of the schema p…
jercytryn Aug 24, 2020
8af11ea
one more try
jercytryn Aug 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions extensions/2.0/Khronos/KHR_variant_materials/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# KHR_variant_materials

## Contributors

- Pär Winzell, Facebook, [@zellski](https://twitter.com/zellski)
- Renee Rashid, Facebook, [@debuggrl](https://github.com/debuggrl)

## Status

Draft

## Dependencies

Written against the glTF 2.0 spec.

## Overview

This extension allows for a compact glTF representation of multiple material variants of an asset, structured to allow low-latency switching at runtime.

A typical use case is digital commerce, where a user might be presented with e.g. a pair of sneakers and the ability to switch between different colours.

## Tagged Variants

We introduce a simple tag-based extension scheme, that allows for high-level runtime swapping between which `material` is used to shade a given `mesh primitive`: the extension root contains a mandatory `mapping` property, which is an array of objects, each one associating some set of tags with a material reference.

Imagine a sneaker with shoelace holes that are made from materials that depend on the overall shoe colour in non-obvious ways:

| Tags | Material |
| ---------------------------------- | ------------------------------- |
| `sneaker_yellow`, `sneaker_orange` | `shoelace_hole_material_brown` |
| `sneaker_red` | `shoelace_hole_material_purple` |
| `sneaker_black` | `shoelace_hole_material_yellow` |

(_the authors of this spec are not product designer, apologies for the dubious colour choices_)

The currently active `material` for a `mesh primitive` is found by stepping through this array of mappings, and selecting the first one which contains any one of the currently active tag. If none match, fall back on vanilla glTF behaviour.

In other words, **this is not a literal mapping** in its glTF form – exporters, take note.

## The variant mapping as glTF JSON

A snippet of a mesh implementing shoe holes which uses this extension might look like:

```javascript
"meshes": [
{
"name": "shoelace_hole",
"primitives": [
{
"attributes": {
"POSITION": 0,
"NORMAL": 1,
},
"indices": 2,
"material": 0,
"extensions": {
"KHR_variant_materials" : {
"mapping": [
{
"tags": [ "sneaker_yellow", "sneaker_orange" ],
"material": 7,
},
{
"tags": [ "sneaker_red" ],
"material": 8,
},
{
"tags": [ "sneaker_black" ],
"material": 9,
},
],
}
}
},
// ... more primitives ...
]
},
// ... more meshes ...
]
```

The tag-based approach allows highly selective material switching, e.g. changing the colour of shoe laces only, or wholesale changes across diverse geometry, by reusing the same tags in switches across many distinct mesh primitives.

In the typical case, many tags will be active, e.g. `['sneaker_red', 'laces_gold']`.

Composition also works well with tags: if a scene were built from several different variational models, each with their own set of tags, then it's easy to imagine an API call on the entire scene that takes a set of tags and passes them on to each constituent model, recursively.

## Interaction with existing glTF functionality

The primary purpose of this extension is to simply formalise the idea of configurability, so that members of the ecosystem can meaningfully communicate: those who produce asset and those who ingest them, and all the tooling inbetween.

Beyond that, it's also a compression scheme: a way to compactly represent multiple assets that have a lot in common (e.g. most geometry, some textures). In this respect, it's most meaningful for the self-contained binary format GLB, where the asset file contains all its data up-front, both that which is shared between variants and that which differs.

If we also allow external references, i.e. images and buffers to source from URLs,then we can additionally come up with sophisticated mechanisms where geometry and textures are loaded separately, dynamically. There's pragmatic pros and cons to going down this route, all beyond the scope of this document. Each application will make its own decisions there; meawhile, the extension proposed works well regardless.

## Implications for Applications and APIs

How does an application communicate to a glTF engine what the initial variant state should be? How does it submit a runtime request for a different configuration? It's out of scope for this extension to constrain or mandate an engine's public API, but a useful implementation will require something of the sort.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "http://json-schema.org/draft-04/schema",
"title": "KHR_variant_materials mesh primitive extension",
"type": "object",
"allOf": [
{
"$ref": "glTFProperty.schema.json"
}
],
"properties": {
"tags": {
"type": "array",
"description": "An array of variational tags.",
"items": {
"$ref": "glTFid.schema.json"
},
"minItems": 1,
"gltf_detailedDescription": "An array of variational tags, all of which map to the associated material."
},
"material": {
"allOf": [{ "$ref": "glTFid.schema.json" }],
"description": "The mapped material.",
"gltf_detailedDescription": "A reference to the material associated with the given array of tags."
},
"extensions": {},
"extras": {}
},
"required": ["tags", "material"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"$schema": "http://json-schema.org/draft-04/schema",
Copy link

@pushmatrix pushmatrix Mar 9, 2020

Choose a reason for hiding this comment

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

The filename for this file should be KHR_variant_materials.schema.json no?

Copy link
Contributor

Choose a reason for hiding this comment

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

good catch, will fix with latest rename

"title": "KHR_variant_materials mesh primitive extension",
"type": "object",
"allOf": [
{
"$ref": "glTFProperty.schema.json"
}
],
"properties": {
"mapping": {
"type": "array",
"description": "An array of mapping entries.",
"items": {
"$ref": "mapping.schema.json"
},
"minItems": 0,
"gltf_detailedDescription": "An array of mapping entries, each associating a set of tags with a material."
},
"extensions": {},
"extras": {}
},
"required": ["mapping"]
}