-
Notifications
You must be signed in to change notification settings - Fork 1.2k
The KHR_materials_variants extension #1681
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 18 commits
b529179
ebe3189
9033116
ee0d8ad
b7c68e3
fd070c3
92771ff
ca97835
69b7edf
8e5d8b1
f0ab429
a9bee21
23915e9
07c109b
46b16fc
17fe9bd
910746f
b84ae8a
fc9b8d9
60be860
09a22ce
26d2629
8543426
9bc4e4e
9049ea8
8af11ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| # KHR_materials_variants | ||
|
|
||
| ## 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. | ||
|
|
||
|  | ||
|
|
||
| ## Design Goals | ||
|
|
||
| _This section is non-normative._ | ||
|
|
||
| This extension aims specifically to give asset creators and consumers a way to communicate _static configurability_. In other words, we explicitly optimize for the case of representing asset variants which are: | ||
|
|
||
| * **finite** - the list of variants is bounded; multi-dimensional variants (e.g. color + texture) are possible but must ultimately be representable as a flattened list | ||
| * **premade** - the variants are produced at asset authoring time | ||
| * **holistic** - while composable, the variants are dictated wholesale at the granularity of the glTF asset; sub-variants or hierarchical variants are not considered | ||
|
|
||
| In digital commerce, each variant may correspond to a distinct SKU or stocked product code, which naturally meet these requirements. In games or movies, each variant may represent a fixed set of curated asset skins which can be represented, moved across the wire, and loaded efficiently. | ||
|
|
||
| A non-goal of this extension is to serve _configuration authorship_ use cases (i.e. configuration builders or "configurators"), which necessarily entail a separate set of concerns, are more subject to complex application-specific business logic, and may benefit from dynamic and continuous configurability and complex builder rules. | ||
|
|
||
| While not designed around this use case, we note however that this extension does implicitly communicate at the primitive level which materials are "valid" for that primitive, for any such applications which may be interested in leveraging this information. | ||
|
|
||
| ## Variants | ||
|
|
||
| We introduce a simple variant tagging 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 variants 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: | ||
|
|
||
| | Variants | 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 designers, apologies for the dubious colour choices_) | ||
|
|
||
| Application-specific logic defines, for a given instance of a glTF asset, a single active variant. The currently active `material` for a `mesh primitive` is found by stepping through this array of mappings in order, and selecting the first one which contains somewhere in its list of variants the currently active variant. The corresponding material is assigned to the mesh. 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. | ||
|
||
|
|
||
| Implicitly, if the application has no active variant, it should also fall back on vanilla glTF behavior. For most use cases, we recommend that one of the variants always corresponds to the default vanilla glTF material for each primitive, so that there exists some one-to-one with viewers which do not support the extension, but this is not a strict requirement. The decision of whether to include a separate option to switch to the no active variant case is left as a decision to compliant applications based on their respective use cases. | ||
|
||
|
|
||
| ## 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_materials_variants" : { | ||
| "mapping": [ | ||
| { | ||
| "variants": [ "sneaker_yellow", "sneaker_orange" ], | ||
| "material": 7, | ||
| }, | ||
| { | ||
| "variants": [ "sneaker_red" ], | ||
| "material": 8, | ||
| }, | ||
| { | ||
| "variants": [ "sneaker_black" ], | ||
| "material": 9, | ||
| }, | ||
| ], | ||
| } | ||
| } | ||
| }, | ||
| // ... more primitives ... | ||
| ] | ||
| }, | ||
| // ... more meshes ... | ||
| ] | ||
| ``` | ||
| The variant tag-based approach allows for wholesale changes across diverse geometry, by reusing the same variant identifiers in switches across many distinct mesh primitives. Likewise, for a given primitive, many different variants may share the same materials. | ||
|
|
||
| Composition also works well with variants: if a scene were built from several glTFs with different variational models, each with their own set of variants, then it's easy to imagine an API call on the entire scene that takes a set of variants and passes them on to each constituent model, recursively. | ||
|
|
||
| > NOTE: Variant strings function only as identifiers. Communicating a human readable name for the variants is left to specific applications and kept outside the scope of this extension. Each mapping can optionally define a name as well, though this is strictly optional. | ||
|
|
||
| ## Interaction with existing glTF functionality | ||
|
|
||
| _This section is non-normative._ | ||
|
|
||
| The primary purpose of this extension is to simply formalise the idea of static configurability, so that members of the ecosystem can meaningfully communicate: those who produce assets and those who ingest them, and all the tooling in between. | ||
|
|
||
| As a secondary effect, material variants allow multiple assets — with shared geometry but different materials — to be stored more compactly, particularly relevant for the self-contained binary format GLB. When using external URIs as references to textures, applications may (optionally) process geometry only once and lazily request texture assets only when needed for a particular variant. | ||
|
|
||
| ## Implications for Applications and APIs | ||
emackey marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| _This section is non-normative._ | ||
|
|
||
| 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. | ||
|
|
||
| ## Examples | ||
|
|
||
| _This section is non-normative._ | ||
|
|
||
| For reference, we provide several simple examples of variants, both represented as distinct constituent GLB files without the extension and as multi-variant GLB files leveraging this extension. We also include the respective net size of the individual variant GLB files and the size of the single combined multi-variant GLB, for comparison. | ||
emackey marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| | Model | Screenshot | Description | Net Size (MB) | Combined Size (MB) | | ||
| |---------------------------|------------------------------------|---------------------------------------------------------------------------------------------------------------|---------------|--------------------| | ||
| | [Shoes](examples/shoes) |  | A simple variant commerce example with a single mesh primitive | 15 | 7.5 | | ||
| | [Chair](examples/chair) |  | A more complex commerce example, involving multi-dimensional variants - flattened into four distinct variants | 7.0 | 1.7 | | ||
| | [Helmet](examples/helmet) |  | Gaming example, with wet and dry variants of a helmet | 8.8 | 5.0 | | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Oval tufted chair | ||
|
|
||
| ## Screenshot | ||
|
|
||
|  | ||
|
|
||
| ## Description | ||
|
|
||
| ## License Information | ||
| Copyright 2020 Eric Chadwick | ||
| CC BY 4.0 https://creativecommons.org/licenses/by/4.0/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Sci Fi Helmet | ||
| ## Screenshot | ||
|
|
||
|  | ||
|
|
||
|
|
||
| ## License Information | ||
|
|
||
| ["Sci Fi Helmet" by Michael Pavlovic](http://quixel.se/usermanual/quixelsuite/doku.php?id=ddo_samples) | ||
|
|
||
| Converted by Norbert Nopper for glTF testing. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Beach, Midnight, Street shoes | ||
|
|
||
| ## Screenshot | ||
|
|
||
|  | ||
|
|
||
| ## Description | ||
|
|
||
| ## License Information | ||
| Copyright 2020 Shopify, Inc. | ||
| CC BY 4.0 https://creativecommons.org/licenses/by/4.0/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| { | ||
donmccurdy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "$schema": "http://json-schema.org/draft-04/schema", | ||
| "title": "KHR_materials_variants mesh primitive extension", | ||
| "type": "object", | ||
| "allOf": [ | ||
| { | ||
| "$ref": "glTFProperty.schema.json" | ||
| } | ||
| ], | ||
| "properties": { | ||
| "variants": { | ||
| "type": "array", | ||
| "description": "An array of variational identifiers.", | ||
| "items": { | ||
| "type": "string" | ||
| }, | ||
| "minItems": 1, | ||
| "gltf_detailedDescription": "An array of variational identifiers, 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." | ||
| }, | ||
| "name": { | ||
| "type": "string", | ||
| "description": "The user-defined name of this variant material mapping.", | ||
| "gltf_detailedDescription": "The optional user-defined name of this variant material mapping. This is not necessarily unique." | ||
| }, | ||
| "extensions": {}, | ||
| "extras": {} | ||
| }, | ||
| "required": [ | ||
| "variants", | ||
| "material" | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-04/schema", | ||
| "title": "KHR_materials_variants 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 variants with a material." | ||
| }, | ||
| "extensions": {}, | ||
| "extras": {} | ||
| }, | ||
| "required": ["mapping"] | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.