-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add KHR_materials_retroreflection extension #2610
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
Open
mklefrancois
wants to merge
4
commits into
KhronosGroup:main
Choose a base branch
from
mklefrancois:khr-materials-retroreflection
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+167
−0
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
b38036b
Add KHR_materials_retroreflection extension
mklefrancois 7dbb2e4
Edits from last week's extension review
NBickford-NV 49bd486
Merge pull request #2 from NBickford-NV/nbickford/retroreflection-edi…
mklefrancois aae24ac
Merge branch 'KhronosGroup:main' into khr-materials-retroreflection
mklefrancois File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
142 changes: 142 additions & 0 deletions
142
extensions/2.0/Khronos/KHR_materials_retroreflection/README.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| # KHR_materials_retroreflection | ||
|
|
||
| ## Contributors | ||
|
|
||
| * Martin-Karl Lefrançois, NVIDIA, [@mklefrancois](https://github.com/mklefrancois) | ||
| * Nia Bickford, NVIDIA, [@NBickford-NV](https://github.com/NBickford-NV) | ||
| * Bastian Sdorra, Dassault Systèmes, [@bsdorra](https://github.com/bsdorra) | ||
| * Alexey Knyazev, Individual Contributor, [@lexaknyazev](https://github.com/lexaknyazev) | ||
|
|
||
| ## Status | ||
|
|
||
| Draft | ||
|
|
||
| ## Dependencies | ||
|
|
||
| Written against the glTF 2.0 spec. | ||
|
|
||
| ## Exclusions | ||
| - This extension must not be used on a material that also uses `KHR_materials_pbrSpecularGlossiness`. | ||
| - This extension must not be used on a material that also uses `KHR_materials_unlit`. | ||
|
|
||
| ## Overview | ||
|
|
||
| This extension adds a physically-plausible retroreflective response to the metallic and dielectric BRDFs of the glTF metallic-roughness material model. | ||
| It is based on the Minimal Retroreflective Microfacet (MRM) model of [Portsmouth et al. (JCGT 15(1), 2026)](http://jcgt.org/published/0015/01/04/), | ||
| which turns a BRDF into a retroreflective one by substituting the outgoing view direction $V$ with its reflection about the surface normal, $V_\text{retro} = 2 N (V \cdot N) - V$, before evaluation and sampling. | ||
| This redirects the specular peak into the back-scatter direction, producing the bright | ||
| retroreflective highlight seen on high-visibility clothing, | ||
| glass-bead road markings, many safety signs, and other materials. | ||
| In addition, MRM preserves reciprocity and energy conservation under reflection-symmetric NDFs (including GGX, Beckmann, and Phong). | ||
|
|
||
| A *retroreflection weight* then linearly blends between the regular metallic and dielectric BRDFs (at a factor of 0) and their retroreflective variants (at a factor of 1). This matches the OpenPBR `specular_retroreflectivity` parameter. | ||
|
|
||
| <figure> | ||
| <img src="./figures/retroreflection.png"/> | ||
| <figcaption><em>Left: A traffic cone with <code>KHR_materials_retroreflection</code> on both sleeves (using a <code>retroreflectionFactor</code> of 1, masked by <code>retroreflectionTexture</code>). The lower sleeve appears brighter than the top sleeve because the light and camera are more closely aligned there. Right: The same traffic cone model and material without the extension. Rendered in <a href="https://github.com/nvpro-samples/vk_gltf_renderer">vk_gltf_renderer</a>.</em></figcaption> | ||
| </figure> | ||
|
|
||
| ## Extending Materials | ||
|
|
||
| `KHR_materials_retroreflection` can be added to a material's `extensions`, like this: | ||
|
|
||
| ```json | ||
| { | ||
| "materials": [ | ||
| { | ||
| "name": "TrafficConeBaseMat", | ||
| "pbrMetallicRoughness": { | ||
| "baseColorTexture": { "index": 0 }, | ||
| "metallicFactor": 0.0, | ||
| "roughnessFactor": 0.35 | ||
| }, | ||
| "extensions": { | ||
| "KHR_materials_retroreflection": { | ||
| "retroreflectionFactor": 1.0, | ||
| "retroreflectionTexture": { "index": 2 } | ||
| } | ||
| } | ||
| } | ||
| ], | ||
| "extensionsUsed": [ "KHR_materials_retroreflection" ] | ||
| } | ||
| ``` | ||
|
|
||
| The extension object contains the following properties: | ||
|
|
||
| | | Type | Description | Required | | ||
| | -------------------------- | -------- | ----------- | ------------------ | | ||
| | **retroreflectionFactor** | `number` | Linear blend between forward microfacet (0.0) and retroreflective microfacet (1.0). Range [0, 1]. | No, default: `0.0` | | ||
| | **retroreflectionTexture** | [`textureInfo`](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-textureinfo) | Per-texel multiplier for `retroreflectionFactor`, sampled from the **R** channel. | No | | ||
|
|
||
| The final per-shading-point retroreflection weight $w$ is: | ||
|
|
||
| ``` | ||
| retroreflectionFactor * retroreflectionTexture.r | ||
| ``` | ||
|
|
||
| if `retroreflectionTexture` is present and | ||
|
|
||
| ``` | ||
| retroreflectionFactor | ||
| ``` | ||
|
|
||
| otherwise. | ||
|
|
||
| ## Retroreflection | ||
|
|
||
| If this extension is present on a material, then it replaces the metallic BRDF and dielectric BRDF of the glTF metallic-roughness material, as defined in [Appendix B](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#appendix-b-brdf-implementation), with blends between the original BRDFs and retroreflective variants. | ||
|
|
||
| More specifically, let `metal_brdf_retro` and `dielectric_brdf_retro` be retroreflective variants of `metal_brdf` and `dielectric_brdf`, respectively, which have an increased response in the back-scatter direction relative to their normal variants. Then the blends between the original BRDFs are | ||
|
|
||
| ``` | ||
| metal_brdf_blended = mix(metal_brdf, metal_brdf_retro, w) | ||
|
|
||
| dielectric_brdf_blended = mix(dielectric_brdf, dielectric_brdf_retro, w) | ||
| ``` | ||
|
|
||
| where `w` is the per-shading-point weight from the [Extending Materials](#extending-materials) section. | ||
|
|
||
| The final material is evaluated as defined in Appendix B, with each BRDF replaced by its blended variant: | ||
|
|
||
| ``` | ||
| material = mix(dielectric_brdf_blended, metal_brdf_blended, metallic) | ||
| ``` | ||
|
|
||
| ## Implementation | ||
|
|
||
| *This section is non-normative.* | ||
|
|
||
| The Minimal Retroreflective Microfacet (MRM) model of [Portsmouth et al. (JCGT 15(1), 2026)](http://jcgt.org/published/0015/01/04/) provides a straightforward method for producing the retroreflective variants. Using the notation from Appendix B, MRM uses the reflected view direction `V_retro` instead of `V` when evaluating or sampling either affected BRDF: | ||
|
|
||
| `V_retro = reflect(-V, N) = 2 * N * dot(V, N) - V`. | ||
|
|
||
| All intermediate quantities derived from `V`, including the half vector `H` and Fresnel terms, are evaluated using `V_retro` for the retroreflective variants. In other words, if the regular BRDF is a function `f(L, V)` taking the light direction `L` and reflected view direction `V` at a point, then the MRM BRDF is `f(L, reflect(-V, N))`. | ||
|
|
||
| The same `V` to `V_retro` substitution is used when sampling the retroreflective BRDF and evaluating its PDF; see Listing 1 of Portsmouth et al. 2026. | ||
|
|
||
| ## Excluding Other Lobes | ||
|
|
||
| *This section is non-normative.* | ||
|
|
||
| While it is possible to apply the MRM model transformation to any BSDF, this extension intentionally does not apply retroreflectivity to the additional BSDFs introduced by other extensions. This matches the behavior of retroreflection within OpenPBR and MaterialX's implementations. | ||
|
|
||
| This extension's choice can also be motivated by physical and visual reasons. For transmission, Section 5 of Portsmouth et al. 2026 describes how applying the MRM model transformation to transmissive lobes produces nonintuitive results, especially when the index of refraction $\eta$ is near 1. Although KHR_materials_clearcoat and KHR_materials_sheen add BRDFs and not BTDFs to the glTF material model, clearcoats of retroreflective objects are typically not themselves retroreflective, and applying the MRM model transformation to the sheen BRDF has little effect as its scattering is nearly symmetric in the view and reflected view directions. | ||
|
|
||
| ## Optional vs. Required | ||
|
|
||
| This extension should not be listed in the `extensionsRequired` list, as retroreflectivity is generally not significant enough to justify blocking the entire scene from loading. We use "should not" instead of "must not" here, though, because there are some cases where retroreflectivity is so important to an object that it justifies listing this extension under `extensionsRequired`. | ||
|
|
||
| ## Schema | ||
|
|
||
| * [material.KHR_materials_retroreflection.schema.json](schema/material.KHR_materials_retroreflection.schema.json) | ||
|
|
||
| ## Known Implementations | ||
|
|
||
| * [NVIDIA DesignWorks Samples' vk_gltf_renderer](https://github.com/nvpro-samples/vk_gltf_renderer) | ||
|
|
||
| ## Resources | ||
|
|
||
| * [Jamie Portsmouth, Matthias Raab, Laurent Belcour, and Francis Liu, The Minimal Retroreflective Microfacet Model, *Journal of Computer Graphics Techniques (JCGT)*, vol. 15, no. 1, 60-75, 2026](http://jcgt.org/published/0015/01/04/) | ||
| * [Retroreflection in MaterialX](https://github.com/AcademySoftwareFoundation/MaterialX/pull/2783) | ||
| * [Retroreflection in the OpenPBR 1.2 draft](https://github.com/AcademySoftwareFoundation/OpenPBR/blob/475bd90d5211d1a4bfb3227d147c692cbd9bc958/index.html#retroreflectivity) | ||
Binary file added
BIN
+166 KB
extensions/2.0/Khronos/KHR_materials_retroreflection/figures/retroreflection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions
25
...s/KHR_materials_retroreflection/schema/material.KHR_materials_retroreflection.schema.json
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-04/schema", | ||
| "$id": "material.KHR_materials_retroreflection.schema.json", | ||
| "title": "KHR_materials_retroreflection glTF Material Extension", | ||
| "type": "object", | ||
| "description": "glTF extension that adds a retroreflective microfacet lobe to metallic-roughness materials.", | ||
| "allOf": [ { "$ref": "glTFProperty.schema.json" } ], | ||
| "properties": { | ||
| "retroreflectionFactor": { | ||
| "type": "number", | ||
| "description": "Linear blend between forward microfacet and retroreflective microfacet.", | ||
| "default": 0.0, | ||
| "minimum": 0.0, | ||
| "maximum": 1.0, | ||
| "gltf_detailedDescription": "Linear blend between the regular forward microfacet (0.0) and the retroreflective microfacet (1.0). This will be multiplied by the retroreflection texture when present." | ||
| }, | ||
| "retroreflectionTexture": { | ||
| "allOf": [ { "$ref": "textureInfo.schema.json" } ], | ||
| "description": "A texture that defines the retroreflection factor in the red channel.", | ||
| "gltf_detailedDescription": "A texture that defines a per-texel multiplier for retroreflectionFactor, stored in the red (R) channel with a linear transfer function. This will be multiplied by retroreflectionFactor." | ||
| }, | ||
| "extensions": { }, | ||
| "extras": { } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.