diff --git a/README.md b/README.md index fa6c8287ff..e5941f5579 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,12 @@ Please provide spec feedback by submitting [issues](https://github.com/KhronosGr Khronos reference cards
- Japanese translation by Takuto Takahashi + Japanese translation | + PDF | + by Takuto Takahashi
+ Chinese translation | + PDF | + by @leeyeel

diff --git a/extensions/2.0/Khronos/KHR_gaussian_splatting/README.md b/extensions/2.0/Khronos/KHR_gaussian_splatting/README.md new file mode 100644 index 0000000000..ca9a80c1ee --- /dev/null +++ b/extensions/2.0/Khronos/KHR_gaussian_splatting/README.md @@ -0,0 +1,380 @@ +# KHR\_gaussian\_splatting + +## Contributors + +- Jason Sobotka, Cesium +- Renaud Keriven, Cesium +- Adam Morris, Cesium +- Sean Lilley, Cesium +- Projit Bandyopadhyay, Niantic Spatial +- Daniel Knoblauch, Niantic Spatial +- Ronald Poirrier, Esri +- Jean-Philippe Pons, Esri + +## Status + +Draft + +## Dependencies + +Written against the glTF 2.0 spec. + +## Table of Contents + +- [Overview](#overview) +- [Adding 3D Gaussian Splats to Primitives](#adding-3d-gaussian-splats-to-primitives) + - [Geometry Type](#geometry-type) + - [Schema Example](#schema-example) + - [Extension Properties](#extension-properties) + - [Attributes](#attributes) + - [Accessors](#accessors) +- [Implementation](#implementation) +- [Known Implementations](#known-implementations) +- [Resources](#resources) + +## Overview + +This extension defines support for storing 3D Gaussian splats in glTF, bringing structure and conformity to the 3D Gaussian splatting space. 3D Gaussian splats are effectively fields of 3D Gaussian splats that can be treated as a point cloud for the purposes of storage. 3D Gaussian splats are defined by their position, rotation, scale, and spherical harmonics which provide both diffuse and specular color. These values are stored as values on a point primitive. Since we treat the 3D Gaussian splats as points primitives, a graceful fallback to treating the data as a sparse point cloud is possible. + +## Adding 3D Gaussian Splats to Primitives + +When a primitive contains an `extension` property defining `KHR_gaussian_splatting`, this indicates to the client that the primitive should be treated as a 3D Gaussian splatting field. + +The extension must be listed in `extensionsUsed`: + +```json + "extensionsUsed" : [ + "KHR_gaussian_splatting" + ] +``` + +Other extensions that depend on this extension such as 3D Gaussian splatting compression extensions may require that this extension be included in `extensionsRequired`. + +### Geometry Type + +The `mode` of the `primitive` must be `POINTS`. + +### Schema Example + +Example shown below. This extension only affects any `primitive` nodes containting 3D Gaussian splat data. + +```json + "meshes": [{ + "primitives": [{ + "attributes": { + "POSITION": 0, + "COLOR_0": 1, + "_SCALE": 2, + "_ROTATION": 3, + "_SH_DEGREE_1_COEF_0": 4, + "_SH_DEGREE_1_COEF_1": 5, + "_SH_DEGREE_1_COEF_2": 6 + }, + "mode": 0, + "indices": 7, + "extensions": { + "KHR_gaussian_splatting": {} + } + }] + }], +``` + +### Extension Properties + +The extension specifies no additional properties but must be included on a point primitive with an empty body to indicate that the primitive should be treated as a 3D Gaussian splatting field. + +#### attributes + +Each 3D Gaussian splat has the following attributes. At minimum the attributes must contain `POSITION`, `COLOR_0`, `_ROTATION`, and `_SCALE`. `_SH_DEGREE_ℓ_COEF_n` attributes hold the spherical harmonics data and are not required. If higher degrees of Spherical Harmonics are used then lower degrees are required implicitly. + +| Splat Data | glTF Attribute | Accessor Type | Component Type | Required | Notes | +| --- | --- | --- | --- | --- | --- | +| Position | POSITION | VEC3 | float | yes | | +| Color (Spherical Harmonic degree 0 (Diffuse) and alpha) | COLOR_0 | VEC4 | unsigned byte normalized or float | yes | | +| Rotation | _ROTATION | VEC4 | float | yes | Rotation is a quaternion. | +| Scale | _SCALE | VEC3 | float | yes | | +| Spherical Harmonics degree 1 | _SH_DEGREE_1_COEF_n (n = 0 to 2) | VEC3 | float | no (yes if degree 2 or 3 are used) | | +| Spherical Harmonics degree 2 | _SH_DEGREE_2_COEF_n (n = 0 to 4) | VEC3 | float | no (yes if degree 3 is used) | | +| Spherical Harmonics degree 3 | _SH_DEGREE_3_COEF_n (n = 0 to 6) | VEC3 | float | no | | + +The value of `COLOR_0` is derived by multiplying the 3 diffuse color components of the 3D Gaussian splat with the constant zeroth-order Spherical Harmonic (ℓ = 0). + +Each increasing degree of spherical harmonics requires more coeffecients. At the 1st degree, 3 sets of coeffcients are required, increasing to 5 sets for the 2nd degree, and increasing to 7 sets at the 3rd degree. With all 3 degrees, this results in 45 spherical harmonic coefficients stored in the `_SH_DEGREE_ℓ_COEF_n` attributes. + +### Accessors + +Required `accessors` for `POSITION`, `COLOR_0`, `_SCALE`, and `_ROTATION`: + +```json + "accessors": [{ + "bufferView": 0, + "componentType": 5126, + "count": 590392, + "type": "VEC3", + "max": [ + 1, + 1, + 1, + ], + "min": [ + -1, + -1, + -1, + ] + }, { + "bufferView": 1, + "componentType": 5121, + "count": 590392, + "type": "VEC4", + "normalized": true + }, { + "bufferView": 2, + "componentType": 5126, + "count": 590392, + "type": "VEC3" + }, { + "bufferView": 3, + "componentType": 5126, + "count": 590392, + "type": "VEC4" + }], +``` + +Spherical harmonics `accessors` all follow the pattern: + +```json + "accessors": [{ + "bufferView": 4, + "componentType": 5126, + "count": 590392, + "type": "VEC3" + }] +``` + +Accessors must be defined for all in-use `attributes`. + +## Implementation + +*This section is non-normative.* + +Rendering is broadly two phases: Pre-rasterization sorting and rasterization. + +### Splat Sorting + +Given that splatting uses many layered Gaussians blended to create complex effects, splat ordering is view dependent and must be sorted based on the splat's distance from the current camera position. The details are largely dependent on the platform targeted. + +In the seminal paper, the authors took a hardware accelerated approach using CUDA. The scene is broken down into tiles with each tile processed in parallel. The splats within each tile are sorted via a GPU accelerated Radix sort. The details are beyond the scope of this document, but it can be found on [their GitHub repository](https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/59f5f77e3ddbac3ed9db93ec2cfe99ed6c5d121d/cuda_rasterizer/rasterizer_impl.cu). + +The approach outlined here differs in that it operates within the browser with WebGL, so direct GPU access is unavailable. + +Regardless of how the data is stored and structured, sorting visible Gaussians is a similar process whether using the CPU or GPU. + +First, obtain the model view matrix by multiplying the model matrix of the asset being viewed with the camera view matrix: + +```javascript + const modelViewMatrix = new Matrix4(); + const modelMatrix = renderResources.model.modelMatrix; + Matrix4.multiply(cam.viewMatrix, modelMatrix, modelViewMatrix); +``` + +Second, calculate Z-depth of each splat (median point, this does not factor in volume) for our depth sort. +This can be accomplished by taking the dot product of the splat position (x, y, z) with the view z-direction. + +```javascript + const zDepthCalc = (index) => + splatPositions[index * 3] * modelViewMatrix[2] + + splatPositions[index * 3 + 1] * modelViewMatrix[6] + + splatPositions[index * 3 + 2] * modelViewMatrix[10] +``` + +No particular sorting method is required, but count and Radix sorts are generally performant. Between the two, the authors have found Radix to be consistently faster (10-15%) while using less memory. + +### Rasterizing + +In the vertex shader, first compute the covariance in 3D and then 2D space. In optimizing implementations, 3D covariance can be computed ahead of time. + +The 3D covariance matrix can be represented as: +$$\Sigma = RSS^TR^T$$ + +Where `S` is the scaling matrix and `R` is the rotation matrix. + +```glsl +//https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/59f5f77e3ddbac3ed9db93ec2cfe99ed6c5d121d/cuda_rasterizer/forward.cu#L118 +void calculateCovariance3D(vec4 rotation, vec3 scale, out float[6] covariance3D) +{ + mat3 S = mat3( + scale[0], 0, 0, + 0, scale[1], 0, + 0, 0, scale[2] + ); + + float r = rot.w; + float x = rot.x; + float y = rot.y; + float z = rot.z; + + mat3 R = mat3( + 1. - 2. * (y * y + z * z), 2. * (x * y - r * z), 2. * (x * z + r * y), + 2. * (x * y + r * z), 1. - 2. * (x * x + z * z), 2. * (y * z - r * x), + 2. * (x * z - r * y), 2. * (y * z + r * x), 1. - 2. * (x * x + y * y) + ); + + mat3 M = S * R; + mat3 Sigma = transpose(M) * M; + + covariance3D = float[6]( + Sigma[0][0], Sigma[0][1], Sigma[0][2], + Sigma[1][1], Sigma[1][2], Sigma[2][2] + ); +} +``` + +3D Gaussians are then projected into 2D space for rendering. Algorithm Zwicker et al. [2001a] + +$$\Sigma' = JW\Sigma W^TJ^T$$ + +- `W` is the view transformation +- `J` is the Jacobian of the affine approximation of the projective transformation +- $\Sigma$ is the 3D covariance matrix derived above (as `Vrk` below) + +```glsl +//https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/59f5f77e3ddbac3ed9db93ec2cfe99ed6c5d121d/cuda_rasterizer/forward.cu#L74 +vec3 calculateCovariance2D(vec3 worldPosition, float cameraFocal_X, float cameraFocal_Y, float tan_fovX, float tan_fovY, float[6] covariance3D, mat4 viewMatrix) +{ + vec4 t = viewmatrix * vec4(worldPos, 1.0); + + float limx = 1.3 * tan_fovx; + float limy = 1.3 * tan_fovy; + float txtz = t.x / t.z; + float tytz = t.y / t.z; + t.x = min(limx, max(-limx, txtz)) * t.z; + t.y = min(limy, max(-limy, tytz)) * t.z; + + mat3 J = mat3( + focal_x / t.z, 0, -(focal_x * t.x) / (t.z * t.z), + 0, focal_y / t.z, -(focal_y * t.y) / (t.z * t.z), + 0, 0, 0 + ); + + mat3 W = mat3( + viewmatrix[0][0], viewmatrix[1][0], viewmatrix[2][0], + viewmatrix[0][1], viewmatrix[1][1], viewmatrix[2][1], + viewmatrix[0][2], viewmatrix[1][2], viewmatrix[2][2] + ); + mat3 T = W * J; + mat3 Vrk = mat3( + covariance3D[0], covariance3D[1], covariance3D[2], + covariance3D[1], covariance3D[3], covariance3D[4], + covariance3D[2], covariance3D[4], covariance3D[5] + ); + + mat3 cov = transpose(T) * transpose(Vrk) * T; + + cov[0][0] += .3; + cov[1][1] += .3; + return vec3(cov[0][0], cov[0][1], cov[1][1]); +} +``` + +The conic is the inverse of the covariance matrix: + +```glsl +vec3 calculateConic(vec3 covariance2D) +{ + float det = covariance2D.x * covariance2D.z - covariance2D.y * covariance2D.y; + return vec3(covariance2D.z, -covariance2D.y, covariance2D.x) * (1. / det); +} +``` + +The Gaussian is finally rendered using the conic matrix applying its alpha derived from the Gaussian opacity multiplied by its exponential falloff. + +```glsl +//https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/59f5f77e3ddbac3ed9db93ec2cfe99ed6c5d121d/cuda_rasterizer/forward.cu#L330 + +in vec2 vertexPosition; +in vec2 screenPosition; +in vec3 conic; +in vec4 color; + +out vec4 splatColor; + +vec2 d = screenPosition - vertexPosition; +float power = -0.5 * (conic.x * d.x * d.x + conic.z * d.y * d.y) - conic.y * d.x * d.y); + +if(power > 0.) + discard; + +float alpha = min(.99f, color.a * exp(power)); + +if(alpha < 1./255.) + discard; + +splatColor = vec4(color * alpha, alpha); +``` + +### Rendering from a Texture + +Instead of rendering directly from attribute vertex buffers, Gaussian splats can be packed into a texture. This approach offers a few benefits: single source of data on the gpu, smaller size, pre-computed 3D covariance, and most importantly instead of sorting all vertex buffers we only have to update a single index buffer. + +The texture format is `RGBA32UI`. + +Gaussian splats are packed into 32 bytes with the following format: + +| Data | Type | Size (bytes) | Byte Offset | +| --- | --- | --- | --- | +| POSITION | float | 12 | 0 | +| (UNUSED) | none | 4 | 12 | +| 3D Covariance | half float | 12 | 16 | +| COLOR_0 (RGBA) | unsigned byte | 4 | 28 | + +`_SCALE` and `_ROTATION` are used to compute the 3D covariance ahead of time. This part of computation is not view-dependent. It's computed as it is above in the vertex shader code. Once computed, take the 6 unique values of the 3D covariance matrix and convert them to half-float for compactness. Each Gaussian splat occupies 2 pixels of the texture. + +[See packing implementation here](https://github.com/CesiumGS/cesium-wasm-utils/blob/main/wasm-splats/src/texture_gen.rs) + +Accessed via `usampler2D`: + +```glsl + highp usampler2D u_gsplatAttributeTexture; +``` + +#### Sorting and Indexes + +With the Gaussian splat attributes packed into a texture the sorting only has to act upon a separate `_INDEX` attribute created at runtime. Gaussian splats are sorted as above, but instead of sorting each vertex buffer only sort the index values. When the glTF is loaded, Gaussian splats can be indexed in the order read. + +#### Extracting Data in the Vertex Shader + +Given a texture with a width of 2048 pixels, access it: + +```glsl + uint texIdx = uint(a_splatIndex); //_INDEX + ivec2 posCoord = ivec2((texIdx & 0x3ffu) << 1, texIdx >> 10); //wrap every 2048 pixels +``` + +Extract the position data: + +```glsl + vec4 splatPosition = vec4( uintBitsToFloat(uvec4(texelFetch(u_splatAttributeTexture, posCoord, 0))) ); +``` + +Then covariance and color data are extracted together: + +```glsl + uvec4 covariance = uvec4(texelFetch(u_splatAttributeTexture, covCoord, 0)); + + //reconstruct matrix + vec2 u1 = unpackHalf2x16(covariance.x) ; + vec2 u2 = unpackHalf2x16(covariance.y); + vec2 u3 = unpackHalf2x16(covariance.z); + mat3 Vrk = mat3(u1.x, u1.y, u2.x, u1.y, u2.y, u3.x, u2.x, u3.x, u3.y); + + //reconstruct color + v_splatColor = vec4(covariance.w & 0xffu, (covariance.w >> 8) & 0xffu, (covariance.w >> 16) & 0xffu, (covariance.w >> 24) & 0xffu) / 255.0; +``` + +## Known Implementations + +This is currently implemented within [3D Tiles and CesiumJS as an experimental feature](https://cesium.com/learn/cesiumjs/ref-doc/Cesium3DTileset.html?classFilter=3D). + +## Resources + +// TODO diff --git a/extensions/2.0/Khronos/KHR_gaussian_splatting/schema/mesh.primitive.KHR_gaussian_splatting.schema.json b/extensions/2.0/Khronos/KHR_gaussian_splatting/schema/mesh.primitive.KHR_gaussian_splatting.schema.json new file mode 100644 index 0000000000..1e6e6405cb --- /dev/null +++ b/extensions/2.0/Khronos/KHR_gaussian_splatting/schema/mesh.primitive.KHR_gaussian_splatting.schema.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_gaussian_splatting glTF Mesh Primitive Extension", + "type": "object", + "description": "Data for a 3D Gaussian Splat primitive.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "extensions": { }, + "extras": { } + } +} diff --git a/extensions/2.0/Khronos/KHR_lights_punctual/README.md b/extensions/2.0/Khronos/KHR_lights_punctual/README.md index f1e15f3fed..e9dd88077f 100644 --- a/extensions/2.0/Khronos/KHR_lights_punctual/README.md +++ b/extensions/2.0/Khronos/KHR_lights_punctual/README.md @@ -79,21 +79,23 @@ For light types that have a direction (`directional` and `spot` lights), the lig ## Light Types -All light types share the common set of properties listed below. - ### Light Shared Properties +All light types share the common set of properties listed below. + | Property | Description | Required | |:-----------------------|:------------------------------------------| :--------------------------| | `name` | Name of the light. | No, Default: `""` | -| `color` | RGB value for light's color in linear space. | No, Default: `[1.0, 1.0, 1.0]` | -| `intensity` | Brightness of light in. The units that this is defined in depend on the type of light. `point` and `spot` lights use luminous intensity in candela (lm/sr) while `directional` lights use illuminance in lux (lm/m2) | No, Default: `1.0` | +| `color` | RGB value for the light's color in linear space. | No, Default: `[1.0, 1.0, 1.0]` | +| `intensity` | Brightness of the light. The units that this is defined in depend on the type of light. `point` and `spot` lights use luminous intensity in candela (lm/sr) while `directional` lights use illuminance in lux (lm/m2) | No, Default: `1.0` | | `type` | Declares the type of the light. | :white_check_mark: Yes | | `range` | Hint defining a distance cutoff at which the light's intensity may be considered to have reached zero. Supported only for `point` and `spot` lights. Must be > 0. When undefined, range is assumed to be infinite. | No | Light properties are unaffected by node transforms — for example, `range` and `intensity` do not change with scale. -## Range Property +The `intensity` represents the luminous intensity that the light would emit if it were colored pure white (`[1.0, 1.0, 1.0]`). The `color` property acts as a wavelength-specific multiplier. + +#### Range Property The range property (allowed only on point and spot lights) defines a distance cutoff at which the light's intensity must be considered zero, meaning the light no longer affects the surrounding area. This can be useful to cull geometry that a light may not visibly affect, potentially having a significant positive impact on rendering performance. It is required that, when given a non-zero value, rendering engines ignore the light beyond this range. @@ -105,7 +107,7 @@ A recommended implementation for this attenuation with a cutoff range is as foll ### Directional -Directional lights are light sources that act as though they are infinitely far away and emit light in the direction of the local -z axis. This light type inherits the orientation of the node that it belongs to; position and scale are ignored except for their effect on the inherited node orientation. Because it is at an infinite distance, the light is not attenuated. Its intensity is defined in lumens per metre squared, or lux (lm/m2). +Directional lights are light sources that act as though they are infinitely far away and emit light in the direction of the local -z axis. This light type inherits the orientation of the node that it belongs to; position and scale are ignored except for their effect on the inherited node orientation. Because it is at an infinite distance, the light is not attenuated. Directional light intensity is defined in lumens per metre squared, or lux (lm/m2). ### Point diff --git a/extensions/2.0/Khronos/KHR_materials_anisotropy/README.md b/extensions/2.0/Khronos/KHR_materials_anisotropy/README.md index 80ae5e996e..5adb68e16d 100644 --- a/extensions/2.0/Khronos/KHR_materials_anisotropy/README.md +++ b/extensions/2.0/Khronos/KHR_materials_anisotropy/README.md @@ -4,7 +4,7 @@ - Mike Bond, Adobe, [@miibond](https://github.com/MiiBond) - Ed Mackey, AGI [@emackey](https://github.com/emackey) -- Alex Wood, AGI [@abwood](https://twitter.com/abwood) +- Alex Wood, AGI [@abwood](https://github.com/abwood) - Nicolas Savva, Autodesk, [@nicolassavva-autodesk](https://github.com/nicolassavva-autodesk) - Tobias Haeussler, Dassault Systemes [@proog128](https://github.com/proog128) - Bastian Sdorra, Dassault Systemes [@bsdorra](https://github.com/bsdorra) diff --git a/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md b/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md index 532bd6360e..a5184c932e 100644 --- a/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md +++ b/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md @@ -13,8 +13,8 @@ SPDX-License-Identifier: LicenseRef-KhronosSpecCopyright - Don McCurdy, Google [@donrmccurdy](https://twitter.com/donrmccurdy) - Sebastien Vandenberghe, Microsoft [@sebavanjs](https://twitter.com/sebavanjs) - Romain Guy, Google [@romainguy](https://twitter.com/romainguy) -- Ed Mackey, AGI [@emackey](https://twitter.com/emackey) -- Alex Wood, AGI [@abwood](https://twitter.com/abwood) +- Ed Mackey, AGI [@emackey](https://github.com/emackey) +- Alex Wood, AGI [@abwood](https://github.com/abwood) Copyright 2018-2020 The Khronos Group Inc. All Rights Reserved. glTF is a trademark of The Khronos Group Inc. See [Appendix](#appendix-full-khronos-copyright-statement) for full Khronos Copyright Statement. diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/README.md b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/README.md new file mode 100644 index 0000000000..38b7b9d186 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/README.md @@ -0,0 +1,480 @@ +# KHR\_materials\_diffuse_transmission + +## Contributors + +- Tobias Haeussler, Dassault Systèmes [@proog128](https://github.com/proog128) +- Bastian Sdorra, Dassault Systèmes [@bsdorra](https://github.com/bsdorra) +- Mike Bond, Adobe [@miibond](https://github.com/MiiBond) +- Eric Chadwick, DGG, [@echadwick-artist](https://github.com/echadwick-artist) +- Alexey Knyazev, Individual Contributor, [@lexaknyazev](https://github.com/lexaknyazev) +- Emmett Lalish, Google [@elalish](https://github.com/elalish) +- Alex Wood, AGI [@abwood](https://github.com/abwood) +- Ed Mackey, AGI [@emackey](https://github.com/emackey) + +Copyright 2024 The Khronos Group Inc. All Rights Reserved. glTF is a trademark of The Khronos Group Inc. +See [Appendix](#appendix-full-khronos-copyright-statement) for full Khronos Copyright Statement. + +## Status + +Release Candidate + +## 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 models the physical phenomenon of light being diffusely transmitted through an infinitely thin material. Thin dielectric objects like leaves or paper diffusely transmit light due to dense volumetric scattering within the object. In 3D graphics, it is common to approximate thin volumetric objects as non-volumetric surfaces. The KHR_materials_diffuse_transmission extension models the diffuse transmission of light through such infinitely thin surfaces. For optically thick media (volumes) with short scattering distances and dense scattering behavior, i.e. candles, KHR_materials_diffuse_transmission provides a phenomenologically plausible and cost-effective approximation. + +
+
+

+ + +

+
+

(Left: Diffuse Transmission Plant by Eric Chadwick CC-BY 4.0 and Rico Cilliers CC0 1.0, showing a small firefly emitting light that transmits diffusely through the back of a leaf.)

+

(Right: Candle model by lucatorcigliani with modifications by @emackey, showing diffuse transmission through the surface of wax paired with volumetric attenuation of light within the wax. Original source CC-BY 4.0)

+

+
+
+ + +## Extending Materials + +The effect is activated by adding the `KHR_materials_diffuse_transmission` extension to any glTF material. + +```json +{ + "materials": [ + { + "extensions": { + "KHR_materials_diffuse_transmission": { + "diffuseTransmissionFactor": 0.25, + "diffuseTransmissionTexture": { + "index": 0 + }, + "diffuseTransmissionColorFactor": [ + 1.0, + 0.9, + 0.85 + ] + } + } + } + ] +} +``` + +## Properties + +| | Type | Description | Required | +|-------------------------------------|---------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------| +| **diffuseTransmissionFactor** | `number` | The percentage of non-specularly reflected light that is diffusely transmitted through the surface. | No, default: `0` | +| **diffuseTransmissionTexture** | [`textureInfo`](/specification/2.0/README.md#reference-textureInfo) | A texture that defines the percentage of non-specularly reflected light that is diffusely transmitted through the surface. Stored in the alpha (`A`) channel. Will be multiplied by the diffuseTransmissionFactor. | No | +| **diffuseTransmissionColorFactor** | `number[3]` | The color that modulates the transmitted light. | No, default: `[1, 1, 1]` | +| **diffuseTransmissionColorTexture** | [`textureInfo`](/specification/2.0/README.md#reference-textureInfo) | A texture that defines the color that modulates the diffusely transmitted light, stored in the `RGB` channels and encoded in sRGB. This texture will be multiplied by diffuseTransmissionColorFactor. | No | + +### diffuseTransmissionFactor + +The proportion of light that is diffusely transmitted through a surface, rather than being diffusely re-emitted. This is expressed as a percentage of the light that penetrates the surface (i.e., not specularly reflected), rather than a percentage of the total light incident on the surface. A value of 1.0 indicates that 100% of the light that penetrates the surface is transmitted through it. + + + + + + + + + + + + + + + + + + + +
0.00.250.50.751.0
+ Backlit, occluded plane with blue baseColorFactor for varying diffuseTransmissionFactor. +
+ +### diffuseTransmissionColorFactor + +The proportion of light at each color channel that is not attenuated by the surface transmission. Attenuation is usually defined as an amount of light at each frequency that is reduced over a given distance through a medium by absorption and scattering interactions. However, since this extension deals exclusively with infinitely thin surfaces, attenuation is constant and equal to 1.0 - `diffuseTransmissionColorFactor`. + + + + + + + + + + + + + + + + + + + +
0.00.250.50.751.0
+ Backlit, occluded plane with blue baseColorFactor and red diffuseTransmissionColorFactor for varying diffuseTransmissionFactor. +
+ +### diffuseTransmissionTexture + +The `A` channel of this texture defines proportion of light that is diffusely transmitted through a surface, rather than being diffusely re-emitted. This is expressed as a percentage of the light that penetrates the surface (i.e., not specularly reflected), rather than a percentage of the total light incident on the surface. A value of 1.0 indicates that 100% of the light that penetrates the surface is transmitted through it. + +The value is linear and is multiplied by the `diffuseTransmissionFactor` to determine the total diffuse transmission value. + +``` +diffuseTransmission = diffuseTransmissionFactor * diffuseTransmissionTexture.a +``` + + + + + + + + +
+ Backlit, occluded plane with blue baseColorFactor and a striped diffuseTransmissionTexture.
(Input texture shown in the top-left).
+
+ + +### diffuseTransmissionColorTexture + +The `RGB` channels of this texture define the proportion of light at each color channel that is not attenuated by the surface transmission. +The values are multiplied by the `diffuseTransmissionColorFactor` to determine the total diffuse transmission color. +``` +diffuseTransmissionColor = diffuseTransmissionColorFactor * diffuseTransmissionColorTexture.rgb +``` + + + + + + + + + + + + + + + + + + + +
0.00.250.50.751.0
+ + Single-sided plane in a symmetric light setup. baseColorTexture and diffuseTransmissionColorTexture use textures that represent the different sides of the one-dollar bill. Series shows the setup at varying values of diffuseTransmissionFactor.
+

(dollar bill texture from ResourceBoy.com ) +

+ +

+ +## Material Structure Updates + +*This section is normative.* + +This extension changes the `dielectric_brdf` defined in [Appendix B](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#material-structure) +``` +dielectric_brdf = + fresnel_mix( + ior = 1.5, + base = diffuse_brdf(color = baseColor), + layer = specular_brdf(α = roughness ^ 2) + ) +``` + to the following: +``` +dielectric_brdf = + fresnel_mix( + ior = 1.5, + base = mix( + diffuse_brdf(color = baseColor), + diffuse_btdf(color = diffuseTransmissionColor), + diffuseTransmission), + layer = specular_brdf(α = roughness ^ 2) + ) +``` +Increasing the strength of the diffuse transmission effect using the `diffuseTransmissionFactor` parameter takes away energy from the diffuse reflection BSDF and passes it to the diffuse transmission BSDF. The specular reflection BSDF and Fresnel weighting are not affected. + +## Implementation +*This section is non-normative.* + +With a simple Lambert BRDF model, `diffuse_brdf` and `diffuse_btdf` may be implemented as follows +``` +function diffuse_brdf(color) { + if (view and light on same hemisphere) { + return (1/pi) * color + } else { + return 0 + } +} + +function diffuse_btdf(color) { + if (view and light on opposite hemispheres) { + return (1/pi) * color + } else { + return 0 + } +} + +function mix(bsdf0, bsdf1, factor) { + return (1-factor) * bsdf0 + factor * bsdf1 +} +``` + +
+ + + + + + + + +
+ Diffuse BRDF + + Diffuse BTDF +
+
+ +## Combining Diffuse Transmission with other Extensions +### KHR_materials_transmission +Both `KHR_materials_diffuse_transmission` and `KHR_materials_transmission` replace the diffuse BRDF with a mix of diffuse BRDF and a BTDF that transmits light onto the opposite side of the surface. In case of `KHR_materials_transmission`, this is a microfacet BTDF that shares its roughness with the microfacet BRDF. In case of `KHR_materials_diffuse_transmission`, on the other hand, this is a diffuse BTDF. + +Let's recall the `dielectric_brdf` for `KHR_materials_diffuse_transmission` as defined above +``` +dielectric_brdf = + fresnel_mix( + ior = 1.5, + base = mix( + diffuse_brdf(color = baseColor), + diffuse_btdf(color = diffuseTransmissionColor), + diffuseTransmission, + layer = specular_brdf(α = roughness ^ 2) + ) +``` + +and compare it to the `dielectric_brdf` defined in `KHR_materials_transmission` +``` +dielectric_brdf = + fresnel_mix( + ior = 1.5, + base = mix( + diffuse_brdf(baseColor), + specular_btdf(α = roughness^2) * baseColor, + transmission), + layer = specular_brdf(α = roughness^2) + ) +``` + +Since the diffuse BTDF does not have controls for roughness, the roughness parameter acts only on the reflective part of the surface. By decoupling the reflection and transmission parts it is possible to configure materials which have a smooth reflection and a diffuse transmission, as shown in images below. + + + + + + + + + +
+ Emissive sphere behind material sample.
Left: Opaque diffuse. Middle: Rough transmission. Right: Diffuse transmission.
+
+ + + + + + + + + + + + + +
0.00.20.4
+ Translucent sphere with varying roughness. +
+ + + + + + + + + + + + + +
0.00.20.4
+ Transmissive sphere with varying roughness. +
+ +If `KHR_materials_transmission` is used in combination with `KHR_materials_diffuse_transmission`, the transmission effect overrides the diffuse transmission effect. + +We can formalize this behavior by combining the two cases from above +``` +dielectric_brdf = + fresnel_mix( + ior = 1.5, + base = mix( + diffuse_bsdf, + specular_btdf(α = roughness^2) * baseColor, + transmission), + layer = specular_brdf(α = roughness^2) + ) + +diffuse_bsdf = mix( + diffuse_brdf(color = baseColor), + diffuse_btdf(color = diffuseTransmissionColor), + diffuseTransmission) +``` + + + + + + + + + + + + + + + + + + +
1.00.750.50.250.0
+ Dragon with fixed diffuseTransmissionFactor of 1.0 and varying transmissionFactor.
+

+ (dragon model from Stanford 3D Scanning Repository) + +

+ +### KHR_materials_volume +When `KHR_materials_diffuse_transmission` is combined with `KHR_materials_volume`, a diffuse transmission BTDF describes the transmission of light through the volume boundary. The object becomes translucent. The light transport inside the volume is solely handled by `KHR_materials_volume` and is not affected by the surface BSDF. + + + + + + + + + + + + + + + +
0.00.51.0
+ + Dragon with white base color, colored volume attenuation and varying diffuseTransmissionFactor.
+
+
+ + + + + + + + + + + + + + + +
0.00.250.5
+ + Candle with off-white base color, colored volume attenuation and varying diffuseTransmissionFactor.
+

(candle model by lucatorcigliani with modifications by @emackey. Original source CC-BY 4.0)

+ +

+ + +## Schema + +- [glTF.KHR_materials_diffuse_transmission.schema.json](schema/glTF.KHR_materials_diffuse_transmission.schema.json) + +## Appendix: Full Khronos Copyright Statement + +Copyright 2024 The Khronos Group Inc. + +Some parts of this Specification are purely informative and do not define requirements +necessary for compliance and so are outside the Scope of this Specification. These +parts of the Specification are marked as being non-normative, or identified as +**Implementation Notes**. + +Where this Specification includes normative references to external documents, only the +specifically identified sections and functionality of those external documents are in +Scope. Requirements defined by external documents not created by Khronos may contain +contributions from non-members of Khronos not covered by the Khronos Intellectual +Property Rights Policy. + +This specification is protected by copyright laws and contains material proprietary +to Khronos. Except as described by these terms, it or any components +may not be reproduced, republished, distributed, transmitted, displayed, broadcast +or otherwise exploited in any manner without the express prior written permission +of Khronos. + +This specification has been created under the Khronos Intellectual Property Rights +Policy, which is Attachment A of the Khronos Group Membership Agreement available at +www.khronos.org/files/member_agreement.pdf. Khronos grants a conditional +copyright license to use and reproduce the unmodified specification for any purpose, +without fee or royalty, EXCEPT no licenses to any patent, trademark or other +intellectual property rights are granted under these terms. Parties desiring to +implement the specification and make use of Khronos trademarks in relation to that +implementation, and receive reciprocal patent license protection under the Khronos +IP Policy must become Adopters and confirm the implementation as conformant under +the process defined by Khronos for this specification; +see https://www.khronos.org/adopters. + +Khronos makes no, and expressly disclaims any, representations or warranties, +express or implied, regarding this specification, including, without limitation: +merchantability, fitness for a particular purpose, non-infringement of any +intellectual property, correctness, accuracy, completeness, timeliness, and +reliability. Under no circumstances will Khronos, or any of its Promoters, +Contributors or Members, or their respective partners, officers, directors, +employees, agents or representatives be liable for any damages, whether direct, +indirect, special or consequential damages for lost revenues, lost profits, or +otherwise, arising from or in connection with these materials. + +Vulkan is a registered trademark and Khronos, OpenXR, SPIR, SPIR-V, SYCL, WebGL, +WebCL, OpenVX, OpenVG, EGL, COLLADA, glTF, NNEF, OpenKODE, OpenKCAM, StreamInput, +OpenWF, OpenSL ES, OpenMAX, OpenMAX AL, OpenMAX IL, OpenMAX DL, OpenML and DevU are +trademarks of The Khronos Group Inc. ASTC is a trademark of ARM Holdings PLC, +OpenCL is a trademark of Apple Inc. and OpenGL and OpenML are registered trademarks +and the OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics +International used under license by Khronos. All other product names, trademarks, +and/or company names are used solely for identification and belong to their +respective owners. diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/attenuation_dt_0.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/attenuation_dt_0.0.jpg new file mode 100644 index 0000000000..ffa936157a Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/attenuation_dt_0.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/attenuation_dt_0.5.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/attenuation_dt_0.5.jpg new file mode 100644 index 0000000000..8f5a995089 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/attenuation_dt_0.5.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/attenuation_dt_1.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/attenuation_dt_1.0.jpg new file mode 100644 index 0000000000..676ad9ad14 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/attenuation_dt_1.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/bsdf.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/bsdf.jpg new file mode 100644 index 0000000000..51cd13ebbc Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/bsdf.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/bsdf.svg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/bsdf.svg new file mode 100644 index 0000000000..a179cab681 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/bsdf.svg @@ -0,0 +1,933 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + V + L + + N + + + + V + L + + N + + + + + + + + + + + + diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/candle_0.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/candle_0.0.jpg new file mode 100644 index 0000000000..2bb211e9e6 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/candle_0.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/candle_0.25.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/candle_0.25.jpg new file mode 100644 index 0000000000..949a5a3886 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/candle_0.25.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/candle_0.5.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/candle_0.5.jpg new file mode 100644 index 0000000000..771a61c131 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/candle_0.5.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.0.jpg new file mode 100644 index 0000000000..060aee5a17 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.25.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.25.jpg new file mode 100644 index 0000000000..d8990c12f8 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.25.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.5.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.5.jpg new file mode 100644 index 0000000000..9cc22d71aa Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.5.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.75.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.75.jpg new file mode 100644 index 0000000000..21f885bb38 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_0.75.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_1.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_1.0.jpg new file mode 100644 index 0000000000..58f2d04b53 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_1.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.0.jpg new file mode 100644 index 0000000000..fa006b4a40 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.25.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.25.jpg new file mode 100644 index 0000000000..8a0914043a Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.25.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.5.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.5.jpg new file mode 100644 index 0000000000..2a88620f20 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.5.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.75.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.75.jpg new file mode 100644 index 0000000000..668c92bbff Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_0.75.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_1.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_1.0.jpg new file mode 100644 index 0000000000..80fe7719f3 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/color_tex_1.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.0.jpg new file mode 100644 index 0000000000..e453e302ca Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.25.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.25.jpg new file mode 100644 index 0000000000..39ae70cc16 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.25.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.5.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.5.jpg new file mode 100644 index 0000000000..f44d7b978d Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.5.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.75.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.75.jpg new file mode 100644 index 0000000000..e8b7e6a70d Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_0.75.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_1.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_1.0.jpg new file mode 100644 index 0000000000..97abeeeea6 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/dt_transmission_1.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.0.jpg new file mode 100644 index 0000000000..79864911ed Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.25.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.25.jpg new file mode 100644 index 0000000000..44e6851ed2 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.25.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.5.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.5.jpg new file mode 100644 index 0000000000..3db3441a81 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.5.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.75.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.75.jpg new file mode 100644 index 0000000000..9b2197cd73 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_0.75.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_1.0.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_1.0.jpg new file mode 100644 index 0000000000..b8397b9d14 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_1.0.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_tex.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_tex.jpg new file mode 100644 index 0000000000..8d1398d775 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_tex.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_tex_inlay.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_tex_inlay.jpg new file mode 100644 index 0000000000..8293d924f4 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/factor_tex_inlay.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/leaves.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/leaves.jpg new file mode 100644 index 0000000000..16cb51e90f Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/leaves.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/translucent-roughness.png b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/translucent-roughness.png new file mode 100644 index 0000000000..7e148b59aa Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/translucent-roughness.png differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/transmission-translucency_thin.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/transmission-translucency_thin.jpg new file mode 100644 index 0000000000..3861940a2c Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/transmission-translucency_thin.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/transmission-translucency_thin_angle.jpg b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/transmission-translucency_thin_angle.jpg new file mode 100644 index 0000000000..1660091a37 Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/transmission-translucency_thin_angle.jpg differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/transmissive-roughness.png b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/transmissive-roughness.png new file mode 100644 index 0000000000..fce6882f3d Binary files /dev/null and b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/figures/transmissive-roughness.png differ diff --git a/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/schema/glTF.KHR_materials_diffuse_transmission.schema.json b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/schema/glTF.KHR_materials_diffuse_transmission.schema.json new file mode 100644 index 0000000000..38e69464c8 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_materials_diffuse_transmission/schema/glTF.KHR_materials_diffuse_transmission.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_materials_diffuse_transmission glTF extension", + "type": "object", + "description": "glTF extension that defines the diffuse transmission of the material.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "diffuseTransmissionFactor": { + "type": "number", + "description": "The percentage of light that is diffusely transmitted through the surface.", + "default": 0.0, + "minimum": 0.0, + "maximum": 1.0, + "gltf_detailedDescription": "The percentage of non-specularly reflected light that is transmitted through the surface via a Lambertian diffuse transmission." + }, + "diffuseTransmissionTexture": { + "allOf": [ { "$ref": "textureInfo.schema.json" } ], + "description": "A texture that defines the percentage of light transmitted through the surface.", + "gltf_detailedDescription": "A texture that defines the strength of the diffuse transmission effect, stored in the alpha (A) channel. Will be multiplied by the diffuseTransmissionFactor." + }, + "diffuseTransmissionColorFactor": { + "type": "array", + "items": { + "type": "number", + "minimum": 0.0 + }, + "description": "The color of the transmitted light.", + "default": [ 1.0, 1.0, 1.0 ], + "minItems": 3, + "maxItems": 3, + "gltf_detailedDescription": "The color of the transmitted light." + }, + "diffuseTransmissionColorTexture": { + "allOf": [ { "$ref": "textureInfo.schema.json" } ], + "description": "A texture that defines the color of the transmitted light", + "gltf_detailedDescription": "A texture that defines the color of the transmitted light, stored in the RGB channels and encoded in sRGB. This texture will be multiplied by diffuseTransmissionColorFactor." + }, + "extensions": { }, + "extras": { } + } +} diff --git a/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md b/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md index d5611906ec..9b6265da4e 100644 --- a/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md +++ b/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md @@ -5,8 +5,8 @@ - Mike Bond, Adobe, [@miibond](https://github.com/MiiBond) - Alex Jamerson, Amazon - Thomas Dideriksen, Amazon -- Alex Wood, AGI, [@abwood](https://twitter.com/abwood) -- Ed Mackey, AGI, [@emackey](https://twitter.com/emackey) +- Alex Wood, AGI, [@abwood](https://github.com/abwood) +- Ed Mackey, AGI, [@emackey](https://github.com/emackey) - Nicolas Savva, Autodesk, [@nicolassavva-autodesk](https://github.com/nicolassavva-autodesk) - Henrik Edstrom, Autodesk - Tobias Haeussler, Dassault Systemes, [@proog128](https://github.com/proog128) diff --git a/extensions/2.0/Khronos/KHR_materials_ior/README.md b/extensions/2.0/Khronos/KHR_materials_ior/README.md index db820d9b12..b8c69fb8ff 100644 --- a/extensions/2.0/Khronos/KHR_materials_ior/README.md +++ b/extensions/2.0/Khronos/KHR_materials_ior/README.md @@ -26,8 +26,8 @@ SPDX-License-Identifier: LicenseRef-KhronosSpecCopyright - Sandra Voelker, Target - Alex Jamerson, Amazon - Thomas Dideriksen, Amazon -- Alex Wood, AGI [@abwood](https://twitter.com/abwood) -- Ed Mackey, AGI [@emackey](https://twitter.com/emackey) +- Alex Wood, AGI [@abwood](https://github.com/abwood) +- Ed Mackey, AGI [@emackey](https://github.com/emackey) Copyright 2018-2021 The Khronos Group Inc. All Rights Reserved. glTF is a trademark of The Khronos Group Inc. See [Appendix](#appendix-full-khronos-copyright-statement) for full Khronos Copyright Statement. diff --git a/extensions/2.0/Khronos/KHR_materials_iridescence/README.md b/extensions/2.0/Khronos/KHR_materials_iridescence/README.md index cf1f1f5354..fa3bd65190 100644 --- a/extensions/2.0/Khronos/KHR_materials_iridescence/README.md +++ b/extensions/2.0/Khronos/KHR_materials_iridescence/README.md @@ -10,8 +10,8 @@ - Jim Eckerlein, UX3D - Alexey Knyazev, Individual Contributor, [@lexaknyazev](https://github.com/lexaknyazev) - Eric Chadwick, Wayfair, [echadwick-wayfair](https://github.com/echadwick-wayfair) -- Alex Wood, AGI [@abwood](https://twitter.com/abwood) -- Ed Mackey, AGI [@emackey](https://twitter.com/emackey) +- Alex Wood, AGI [@abwood](https://github.com/abwood) +- Ed Mackey, AGI [@emackey](https://github.com/emackey) Copyright (C) 2018-2022 The Khronos Group Inc. All Rights Reserved. glTF is a trademark of The Khronos Group Inc. See [Appendix](#appendix-full-khronos-copyright-statement) for full Khronos Copyright Statement. diff --git a/extensions/2.0/Khronos/KHR_materials_specular/README.md b/extensions/2.0/Khronos/KHR_materials_specular/README.md index bb855fdcec..c6c4a55fc9 100644 --- a/extensions/2.0/Khronos/KHR_materials_specular/README.md +++ b/extensions/2.0/Khronos/KHR_materials_specular/README.md @@ -26,8 +26,8 @@ SPDX-License-Identifier: LicenseRef-KhronosSpecCopyright - Sandra Voelker, Target - Alex Jamerson, Amazon - Thomas Dideriksen, Amazon -- Alex Wood, AGI [@abwood](https://twitter.com/abwood) -- Ed Mackey, AGI [@emackey](https://twitter.com/emackey) +- Alex Wood, AGI [@abwood](https://github.com/abwood) +- Ed Mackey, AGI [@emackey](https://github.com/emackey) - Alexey Knyazev [@lexaknyazev](https://github.com/lexaknyazev) Copyright 2018-2021 The Khronos Group Inc. All Rights Reserved. glTF is a trademark of The Khronos Group Inc. diff --git a/extensions/2.0/Khronos/KHR_materials_transmission/README.md b/extensions/2.0/Khronos/KHR_materials_transmission/README.md index fd94cda12e..3fa0e48dc4 100644 --- a/extensions/2.0/Khronos/KHR_materials_transmission/README.md +++ b/extensions/2.0/Khronos/KHR_materials_transmission/README.md @@ -12,8 +12,8 @@ SPDX-License-Identifier: LicenseRef-KhronosSpecCopyright - Bastian Sdorra, Dassault Systemes [@bsdorra](https://github.com/bsdorra) - Don McCurdy, Google [@donrmccurdy](https://twitter.com/donrmccurdy) - Emmett Lalish, Google [@elalish](https://github.com/elalish) -- Ed Mackey, AGI [@emackey](https://twitter.com/emackey) -- Alex Wood, AGI [@abwood](https://twitter.com/abwood) +- Ed Mackey, AGI [@emackey](https://github.com/emackey) +- Alex Wood, AGI [@abwood](https://github.com/abwood) - Richard Sahlin, IKEA [@rsahlin](https://github.com/rsahlin) - Norbert Nopper, UX3D [@UX3DGpuSoftware](https://twitter.com/UX3DGpuSoftware) diff --git a/extensions/2.0/Khronos/KHR_materials_volume/README.md b/extensions/2.0/Khronos/KHR_materials_volume/README.md index e31ebdb96a..513b58116f 100644 --- a/extensions/2.0/Khronos/KHR_materials_volume/README.md +++ b/extensions/2.0/Khronos/KHR_materials_volume/README.md @@ -26,8 +26,8 @@ SPDX-License-Identifier: LicenseRef-KhronosSpecCopyright - Sandra Voelker, Target - Alex Jamerson, Amazon - Thomas Dideriksen, Amazon -- Alex Wood, AGI [@abwood](https://twitter.com/abwood) -- Ed Mackey, AGI [@emackey](https://twitter.com/emackey) +- Alex Wood, AGI [@abwood](https://github.com/abwood) +- Ed Mackey, AGI [@emackey](https://github.com/emackey) Copyright 2018-2021 The Khronos Group Inc. All Rights Reserved. glTF is a trademark of The Khronos Group Inc. See [Appendix](#appendix-full-khronos-copyright-statement) for full Khronos Copyright Statement. diff --git a/extensions/2.0/Khronos/KHR_spz_gaussian_splats_compression/README.md b/extensions/2.0/Khronos/KHR_spz_gaussian_splats_compression/README.md new file mode 100644 index 0000000000..b403400bb9 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_spz_gaussian_splats_compression/README.md @@ -0,0 +1,144 @@ +# KHR\_spz\_gaussian\_splats\_compression + +## Contributors + +- Jason Sobotka, Cesium +- Renaud Keriven, Cesium +- Adam Morris, Cesium +- Sean Lilley, Cesium +- Projit Bandyopadhyay, Niantic Spatial +- Daniel Knoblauch, Niantic Spatial +- Ronald Poirrier, Esri +- Jean-Philippe Pons, Esri + +## Status + +Draft + +## Dependencies + +Written against the glTF 2.0 spec. + +Depends on the `KHR_gaussian_splatting` extension specification for attribute definitions. + +## Table of Contents + +- [Overview](#overview) +- [Compressing 3D Gaussian splats using SPZ](#compressing-3d-gaussian-splats-using-spz) + - [Geometry Type](#geometry-type) + - [Schema Example](#schema-example) + - [Extension Properties](#extension-properties) + - [Accessors](#accessors) +- [Conformance](#conformance) +- [Schema](#schema) +- [Known Implementations](#known-implementations) +- [Resources](#resources) + +## Overview + +This extension defines support for compressing 3D Gaussian splats stored within in glTF using the SPZ compression format for efficient streaming and storage. + +SPZ is a compression format from Niantic Spatial designed for Gaussian splats. Currently, it is open sourced under the MIT license. The SPZ format is primarily used in the Niantic Spatial Scaniverse app. It was purpose built for Gaussian splats and offers a balance of high compression with minimal visual fidelity loss, and allows for storing some or all of the 3D Gaussian's spherical harmonics. + +At rest, the 3D Gaussian splats are stored within the SPZ compression format. Upon being decompressed, values are mapped to the glTF attributes defined by `KHR_gaussian_splatting` for rendering. The [conformance](#conformance) section defines what an implementation must do when encountering this extension, and how the extension interacts with the base specification. + +## Compressing 3D Gaussian splats using SPZ + +If a primitive contains an `extension` property which defines both `KHR_gaussian_splatting` and `KHR_spz_gaussian_splats_compression` then support for SPZ compression is required. There is no requirement for a backup uncompressed buffer. + +The extension must be listed in `extensionsUsed` alongside `KHR_gaussian_splatting`. + +```json + "extensionsUsed" : [ + "KHR_gaussian_splatting", + "KHR_spz_gaussian_splats_compression" + ] +``` + +It must also be listed in `extensionsRequired`. When `KHR_spz_gaussian_splats_compression` is in use, the `KHR_gaussian_splatting` extension must also be listed as required. + +```json + "extensionsRequired" : [ + "KHR_gaussian_splatting", + "KHR_spz_gaussian_splats_compression" + ] +``` + +### Inheritance from base extension + +As this extension extends the base extension, all components of the base extension are inherited. Any modifications to the base definition are explicitly defined in the sections below. + +### Schema Example + +Example SPZ extension shown below. This extension only affects any `primitive` nodes containting Gaussian splat data. Note that unlike the base `KHR_gaussian_splatting` extension, the `indices` property is excluded, and a `bufferView` is provided by the extension. This bufferview points to where the SPZ blob is stored. + +```json + "meshes": [{ + "primitives": [{ + "attributes": { + "POSITION": 0, + "COLOR_0": 1, + "_SCALE": 2, + "_ROTATION": 3, + "_SH_DEGREE_1_COEF_0": 4, + "_SH_DEGREE_1_COEF_1": 5, + "_SH_DEGREE_1_COEF_2": 6 + }, + "material": 0, + "mode": 0, + "extensions": { + "KHR_spz_gaussian_splats_compression": { + "bufferView": 0, + } + } + }] + }], + "buffers": [{ + "uri": "0.bin", + "byteLength": 9753142 + }], + "bufferViews": [{ + "buffer": 0, + "byteLength": 9753142 + }], +``` + +### Extension Properties + +#### bufferView + +This property points to the bufferView containing the Gaussian splat data compressed with SPZ. + +### Accessors + +Accessor requirements are modified from the base `KHR_gaussian_splatting` extension with the following adjustments to definition: + + - SPZ compressed attributes must not include `bufferView` nor `byteOffset`. (See: [Conformance](#conformance)) + - Accessor `type` is defined for the resulting type after decompression and dequantization has occurred. + - The accessor `count` must match the number of points in the compressed SPZ data. + +## Conformance + +The recommended process for handling SPZ compression is as follows: + +- If the loader does not support `KHR_gaussian_splatting` and `KHR_spz_gaussian_splats_compression`, it must fail. +- If the loader does support `KHR_gaussian_splatting` and `KHR_spz_gaussian_splats_compression` then: + + - The loader must process `KHR_spz_gaussian_splats_compression` data first. The loader must get the data from `KHR_spz_gaussian_splats_compression`'s `bufferView` property. + - SPZ compressed attributes must not include `bufferView` nor `byteOffset` in their accessor declarations. Any attributes falling outside the SPZ format, however, must be stored as regular glTF attributes and must therefore include `bufferView` (and optionally `byteOffset`) in their accessor definitions. + +When compressing or decompressing the SPZ data to be stored within the glTF, you must specify a Left-Up-Front (`LUF`) coordinate system in the SPZ `PackOptions` or `UnpackOptions` within the SPZ library. This ensures that the data is compressed and decompressed appropriately for glTF. + +## Schema + +[SPZ Compression Schema](./schema/mesh.primitive.KHR_spz_gaussian_splats_compression.schema.json) + +## Known Implementations + +This is currently implemented within [3D Tiles and CesiumJS as an experimental feature](https://cesium.com/learn/cesiumjs/ref-doc/Cesium3DTileset.html?classFilter=3D). + +## Resources + +[https://github.com/nianticlabs/spz](https://github.com/nianticlabs/spz) + +[https://github.com/drumath2237/spz-loader/tree/main](https://github.com/drumath2237/spz-loader/tree/main) diff --git a/extensions/2.0/Khronos/KHR_spz_gaussian_splats_compression/schema/mesh.primitive.KHR_spz_gaussian_splats_compression.schema.json b/extensions/2.0/Khronos/KHR_spz_gaussian_splats_compression/schema/mesh.primitive.KHR_spz_gaussian_splats_compression.schema.json new file mode 100644 index 0000000000..37246191c6 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_spz_gaussian_splats_compression/schema/mesh.primitive.KHR_spz_gaussian_splats_compression.schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_spz_gaussian_splats_compression glTF Mesh Primitive Extension", + "type": "object", + "description": "Compressed data for SPZ primitive.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "bufferView": { + "allOf": [ { "$ref" : "glTFid.schema.json" } ], + "description": "The index of the bufferView." + }, + "extensions": { }, + "extras": { } + }, + "required": [ "bufferView" ] +} diff --git a/extensions/2.0/Vendor/EXT_texture_webp/README.md b/extensions/2.0/Vendor/EXT_texture_webp/README.md index 9cf0ea5c96..f151a62be9 100644 --- a/extensions/2.0/Vendor/EXT_texture_webp/README.md +++ b/extensions/2.0/Vendor/EXT_texture_webp/README.md @@ -15,17 +15,19 @@ Written against the glTF 2.0 spec. ## Overview -This extension allows glTF models to use WebP as a valid image format. A client that does not implement this extension can ignore the provided WebP image and continue to rely on the PNG and JPG textures available in the base specification. Defining a fallback texture is optional. The [best practices](#best-practices) section describes the intended use case of this extension and the expected behavior when using it without a fallback texture. +This extension allows glTF assets to use WebP as a valid image format. -WebP is an image format developed and maintained by Google that provides superior lossless and lossy compression rates for images on the web. It is typically 26% smaller in size compared to PNGs and 25-34% smaller than comparable JPEG images - [source](https://developers.google.com/speed/webp/). +WebP is an image format developed and maintained by Google that provides superior lossless and lossy compression rates for images on the web. It is typically 26% smaller in size compared to PNGs and 25-34% smaller than comparable JPEG images. + +A client implementation that does not support this extension may be able to ignore the provided WebP image if an optional fallback PNG or JPEG image is present. The [best practices](#best-practices) section describes the use cases of this extension with and without a fallback image. ## glTF Schema Updates -The `EXT_texture_webp` extension is added to the `textures` node and specifies a `source` property that points to the index of the `images` node which in turn points to the WebP image. +The `EXT_texture_webp` extension is added to the texture object and specifies a `source` property that contains the index of the WebP image object. -The following glTF will load `image.webp` in clients that support this extension, and otherwise fall back to `image.png`. +The following glTF will load `image.webp` in client implementations that support this extension, and otherwise fall back to `image.png`. -``` +```json "textures": [ { "source": 0, @@ -46,9 +48,9 @@ The following glTF will load `image.webp` in clients that support this extension ] ``` -When used in the glTF Binary (.glb) format the `images` node that points to the WebP image uses the `mimeType` value of `image/webp`. +When an image is stored in a buffer and accessed via a buffer view, the WebP image object uses the `mimeType` value of `image/webp`. -``` +```json "textures": [ { "source": 0, @@ -77,17 +79,17 @@ When used in the glTF Binary (.glb) format the `images` node that points to the ## Best Practices -Since WebP is not as widely supported as JPEG and PNG, it is recommended to use this extension only when transmission size is a significant bottleneck. For example, in geospatial applications the total texture payload can range from gigabytes to terabytes of data. In those situations, WebP textures can be used without a fallback to improve storage and transmission. +It is recommended to use this extension when transmission size is a significant bottleneck. For example, in geospatial applications the total texture payload can range from gigabytes to terabytes of data. In those situations, WebP textures can be used without a fallback to improve storage and transmission. -When a fallback image is defined, this extension should not be present in `extensionsRequired`. This will allow all clients to render the glTF correctly, and those that support this extension can request the optimized WebP version of the textures. +When a fallback image is defined, this extension should not be present in `extensionsRequired`. This will allow all client implementations to render the glTF asset correctly, and those that support this extension can use the WebP version of the textures. -WebP images using [extended file format](https://developers.google.com/speed/webp/docs/riff_container#extended_file_format) should not contain animations or color profile information. +WebP images using extended file format (RFC 9649, Section 2.7) should not contain `ICCP`, `ANIM`, or `EXIF` chunks. ### Using Without a Fallback -To use WebP images without a fallback, define `EXT_texture_webp` in both `extensionsUsed` and `extensionsRequired`. The `texture` node will then have only an `extensions` property as shown below. +To use WebP images without a JPEG or PNG fallback, `EXT_texture_webp` must be present in both `extensionsUsed` and `extensionsRequired`. The texture object will then have only an `extensions` property as shown below. -``` +```json "textures": [ { "extensions": { @@ -99,14 +101,14 @@ To use WebP images without a fallback, define `EXT_texture_webp` in both `extens ] ``` -If a glTF contains a WebP with no fallback texture and the browser does not support WebP, the client should either display an error or decode the WebP image at runtime (see [resource](#resources) for decoding libraries). - ## Known Implementations -CesiumJS uses it to significantly cut load times for massive models that contain gigabytes of texture data (see [implementation and sample model](https://github.com/AnalyticalGraphicsInc/cesium/pull/7486)). +CesiumJS uses it to significantly cut load times for massive models that contain gigabytes of texture data (see [implementation and sample model](https://github.com/AnalyticalGraphicsInc/cesium/pull/7486)). ## Resources -Google's [WebP developer page](https://developers.google.com/speed/webp/) provides information about the format as well as [pre-compiled and source code versions](https://developers.google.com/speed/webp/download) of an encoder and a decoder. The [WebP Compression Study](https://developers.google.com/speed/webp/docs/webp_study) is a detailed comparison between JPEG and WebP. +[RFC 9649, WebP Image Format](https://www.rfc-editor.org/info/rfc9649) + +Google's [WebP developer page](https://developers.google.com/speed/webp/) provides information about the format as well as pre-compiled and source code versions of the reference codec implementation -For browsers that do not natively support WebP, [webp_js](https://chromium.googlesource.com/webm/libwebp/+/HEAD/webp_js/README.md) decodes WebP images in JavaScript. [Sharp](http://sharp.pixelplumbing.com/en/stable/) is a NodeJS library for fast encode/decode of WebP using native modules (built on top of Google's implementation above). +[Sharp](http://sharp.pixelplumbing.com/) is a Node.js library for fast encode/decode of WebP using native modules diff --git a/extensions/2.0/Vendor/EXT_texture_webp/schema/glTF.EXT_texture_webp.schema.json b/extensions/2.0/Vendor/EXT_texture_webp/schema/glTF.EXT_texture_webp.schema.json index 6bade8a981..390c8b6441 100644 --- a/extensions/2.0/Vendor/EXT_texture_webp/schema/glTF.EXT_texture_webp.schema.json +++ b/extensions/2.0/Vendor/EXT_texture_webp/schema/glTF.EXT_texture_webp.schema.json @@ -7,7 +7,7 @@ "properties": { "source": { "allOf": [ { "$ref": "glTFid.schema.json" } ], - "description": "The index of the images node which points to a WebP image." + "description": "The index of the WebP image." }, "extensions": {}, "extras": {} diff --git a/extensions/2.0/Vendor/GODOT_single_root/README.md b/extensions/2.0/Vendor/GODOT_single_root/README.md new file mode 100644 index 0000000000..8b822c73d1 --- /dev/null +++ b/extensions/2.0/Vendor/GODOT_single_root/README.md @@ -0,0 +1,89 @@ +# GODOT_single_root + +## Contributors + +- Aaron Franke, Godot Engine. + +## Status + +Complete + +## Dependencies + +Written against the glTF 2.0 spec. + +## Overview + +This extension allows flagging glTF assets as having a single root node to enable more efficient and accurate workflows with various DCC tools, such as by directly importing the asset's node hierarchy without creating additional scene nodes. This flag imposes certain constraints on glTF assets as described below. + +Many games engines import glTF files as objects with a single root node. Unity has prefabs with a single root GameObject, and Godot has scenes with a single root node. Since glTF allows defining multiple root nodes, engines will insert the glTF root nodes as children of the "real" root node, which makes it difficult for a glTF file to define the properties of the "real" root node. This is important for things like physics bodies and character controllers, which are defined on the root node, so that all child nodes are moved with the body. Aside from physics, a single root node would avoid an extra node in the tree when round-tripping between glTF and these engines. + +The `GODOT_single_root` glTF extension solves this problem by imposing additional constraints to ensure the entire glTF file can be parsed into one of these objects with a single root node. Therefore, all other nodes are either descendants of this node, or are not in the glTF scene node tree (in which case they behave the same as base glTF). Implementations can detect `GODOT_single_root` and import the single root node as the object's "real" root node in the scene/prefab/etc. The extension contains no data, it only restricts behavior. The restrictions are as follows: + +- The document `"scenes"` array MUST have exactly one scene. +- The document `"scene"` index MUST be set to 0, the index of the only scene in the `"scenes"` array. +- The scene MUST have exactly one node, the single root node. +- The scene's node index MUST be set to 0, the index of the first node in the `"nodes"` array. +- The `"translation"`, `"rotation"`, `"scale"`, and `"matrix"` properties of the single root node MUST either be not defined or have default values. + +These restrictions make the glTF `"scenes"` and `"scene"` properties fully redundant, so that implementations using `GODOT_single_root` do not need to parse the `"scenes"` or `"scene"` properties. Since there is only one root node, node index 0 is reserved as the single root node. However, the `"scenes"` and `"scene"` properties must be kept in the glTF file for compatibility with implementations that do not support this extension. This means that the glTF file must contain properties equivalent to this: + +```json + "scene": 0, + "scenes": [{ "nodes": [0] }], +``` + +Note: Other properties set on the scene JSON, such as the name etc, are allowed, but not required or expected. If the scene does not have a name, use the single root node's name as the scene name. + +The single root node acts as the root object that represents the entire glTF file, since all other nodes are either descendants or unused, and all resources such as meshes are either used by this node, by descendants, or unused. This requires the glTF file to only contain one scene, with one root node. Multiple scenes per file is not allowed, since it goes against this goal. + +Forbidding the root node to have a transform is required because: +- A glTF file does not have a transform, only its nodes do. With this extension, the single root node represents the glTF file. +- This keeps local directions such as forward consistent when orienting the scene vs orienting the single root node. +- A glTF scene's transform should be determined only by the instances of the scene, such as instances inside of a game engine. +- Without this restriction, a root node with a transform would be transformed differently in implementations with and without `GODOT_single_root` when using functions such as look at, which must not happen. + +### Example: + +This minimal example defines a node named SingleRootNode as the scene's single root node: + +```json +{ + "asset": { + "version": "2.0" + }, + "extensionsUsed": [ + "GODOT_single_root" + ], + "nodes": [ + { + "name": "SingleRootNode" + } + ], + "scene": 0, + "scenes": [{ "nodes": [0] }] +} +``` + +## glTF Schema Updates + +This extension consists of a new `"GODOT_single_root"` string which can be added to the glTF's `"extensionsUsed"` array and because it is optional, it does not need to be added to the `"extensionsRequired"` array. + +The `GODOT_single_root` extension defines no data, and should not be added to `"extensions"` anywhere. It only needs to exist in `"extensionsUsed"`. + +### glTF Object Model + +This extension defines no properties that can be read or manipulated by the glTF Object Model. + +### JSON Schema + +This glTF extension has no schema. + +## Known Implementations + +- Godot Engine 4.2 or later: https://github.com/godotengine/godot/pull/81851 + +## Resources: + +- Godot PackedScene: https://docs.godotengine.org/en/stable/classes/class_packedscene.html#class-packedscene-method-instantiate +- Unity Prefabs: https://docs.unity3d.com/Manual/Prefabs.html diff --git a/extensions/Prefixes.md b/extensions/Prefixes.md index ba01f3a614..36079e9b5e 100644 --- a/extensions/Prefixes.md +++ b/extensions/Prefixes.md @@ -59,7 +59,7 @@ To request a prefix, submit a [GitHub issue](https://github.com/KhronosGroup/glT | `MIRROR` | The Mirror Megaverse Inc. | https://www.themirror.space/
`khronos at themirror.space` | [#2230](https://github.com/KhronosGroup/glTF/issues/2230) | | `MODUPLAY` | Moduplay Group Pty Ltd. | https://moduplaygroup.com.au/
`matthew.h at moduplay.com.au` | [#2445](https://github.com/KhronosGroup/glTF/issues/2445) | | `MOZ` | Mozilla Corporation | https://www.mozilla.org/ | [#1349](https://github.com/KhronosGroup/glTF/issues/1349) | -| `MPEG` | The Moving Picture Experts Group | https://www.mpeg.org | [#1754](https://github.com/KhronosGroup/glTF/issues/1754) | +| `MPEG` | The Moving Picture Experts Group | https://www.mpeg.org/
`tsto at qti.qualcomm.com`
`young.l at samsung.com` | [#1754](https://github.com/KhronosGroup/glTF/issues/1754) | | `MSFT` | Microsoft Corporation | https://www.microsoft.com/ | [#1164](https://github.com/KhronosGroup/glTF/pull/1164) | | `MTTR` | Matterport, Inc. | https://matterport.com/ | [#2150](https://github.com/KhronosGroup/glTF/issues/2150) | | `MX` | The Matrix.org Foundation | https://matrix.org/ | [#2126](https://github.com/KhronosGroup/glTF/issues/2126) | @@ -78,6 +78,7 @@ To request a prefix, submit a [GitHub issue](https://github.com/KhronosGroup/glT | `SEIN` | Hiloteam | https://seinjs.com/ | [#1840](https://github.com/KhronosGroup/glTF/issues/1840) | | `SHAPEDIVER` | ShapeDiver GmbH | https://www.shapediver.com/ | [#2103](https://github.com/KhronosGroup/glTF/issues/2103) | | `SI` | Smithsonian Institution | https://www.si.edu/ | [#1410](https://github.com/KhronosGroup/glTF/issues/1410) | +| `SIRADEL` | Siradel | https://www.siradel.com/ | [#2469](https://github.com/KhronosGroup/glTF/issues/2469) | | `SKFB` | Sketchfab, Inc. | https://sketchfab.com/ | [#1239](https://github.com/KhronosGroup/glTF/issues/1239) | | `SKYLINE` | Skyline Software Systems, Inc. | https://www.skylinesoft.com/ | [#1704](https://github.com/KhronosGroup/glTF/issues/1704) | | `SNAP` | Snap, Inc. | https://snap.com/ | [#2125](https://github.com/KhronosGroup/glTF/issues/2125) | diff --git a/extensions/README.md b/extensions/README.md index 5952c3f272..369ccc0644 100644 --- a/extensions/README.md +++ b/extensions/README.md @@ -45,7 +45,7 @@ This section tracks the status of extensions and projects that are in developmen | KHR_audio_graph | Proposal | [PR #2421](https://github.com/KhronosGroup/glTF/pull/2421) | | KHR_collision_shapes | Review Draft | [PR #2370](https://github.com/KhronosGroup/glTF/pull/2370) | | KHR_interactivity | Review Draft | [PR #2293](https://github.com/KhronosGroup/glTF/pull/2293) | -| KHR_materials_diffuse_transmission | Review Draft | [PR #1825](https://github.com/KhronosGroup/glTF/pull/1825) | +| KHR_materials_diffuse_transmission | Release Candidate | [Specification](2.0/Khronos/KHR_materials_diffuse_transmission/README.md) | | KHR_materials_subsurface | Initial Draft | [PR #1928](https://github.com/KhronosGroup/glTF/pull/1928) | | KHR_node_hoverability | Review Draft | [PR #2426](https://github.com/KhronosGroup/glTF/pull/2426) | | KHR_node_selectability | Review Draft | [PR #2422](https://github.com/KhronosGroup/glTF/pull/2422) | @@ -96,6 +96,7 @@ Vendor extensions are not covered by the Khronos IP framework. * [AGI_stk_metadata](2.0/Vendor/AGI_stk_metadata/README.md) * [CESIUM_primitive_outline](2.0/Vendor/CESIUM_primitive_outline/README.md) * [FB_geometry_metadata](2.0/Vendor/FB_geometry_metadata/README.md) +* [GODOT_single_root](2.0/Vendor/GODOT_single_root/README.md) * [GRIFFEL_bim_data](2.0/Vendor/GRIFFEL_bim_data/README.md) * [MPEG_accessor_timed](2.0/Vendor/MPEG_accessor_timed/README.md) * [MPEG_animation_timing](2.0/Vendor/MPEG_animation_timing/README.md)