From a209c68065af7ec6ff1ffb7fc3c9ad51b7d9d5db Mon Sep 17 00:00:00 2001 From: Neil Bickford Date: Tue, 21 Mar 2023 15:51:56 -0700 Subject: [PATCH] NVIDIA Micromap extensions: NV_micromaps, NV_opacity_micromap, NV_displacement_micromap, NV_attribute_micromap, and NV_micromap_tooling --- .../Vendor/NV_attribute_micromap/README.md | 129 ++++++++++ ...rimitive.NV_attribute_micromap.schema.json | 55 +++++ .../Vendor/NV_displacement_micromap/README.md | 224 ++++++++++++++++++ ...itive.NV_displacement_micromap.schema.json | 78 ++++++ .../2.0/Vendor/NV_micromap_tooling/README.md | 77 ++++++ ....primitive.NV_micromap_tooling.schema.json | 44 ++++ extensions/2.0/Vendor/NV_micromaps/README.md | 63 +++++ .../schema/glTF.NV_micromaps.schema.json | 20 ++ .../NV_micromaps/schema/micromap.schema.json | 42 ++++ .../2.0/Vendor/NV_opacity_micromap/README.md | 174 ++++++++++++++ ....primitive.NV_opacity_micromap.schema.json | 42 ++++ 11 files changed, 948 insertions(+) create mode 100644 extensions/2.0/Vendor/NV_attribute_micromap/README.md create mode 100644 extensions/2.0/Vendor/NV_attribute_micromap/schema/mesh.primitive.NV_attribute_micromap.schema.json create mode 100644 extensions/2.0/Vendor/NV_displacement_micromap/README.md create mode 100644 extensions/2.0/Vendor/NV_displacement_micromap/schema/mesh.primitive.NV_displacement_micromap.schema.json create mode 100644 extensions/2.0/Vendor/NV_micromap_tooling/README.md create mode 100644 extensions/2.0/Vendor/NV_micromap_tooling/schema/mesh.primitive.NV_micromap_tooling.schema.json create mode 100644 extensions/2.0/Vendor/NV_micromaps/README.md create mode 100644 extensions/2.0/Vendor/NV_micromaps/schema/glTF.NV_micromaps.schema.json create mode 100644 extensions/2.0/Vendor/NV_micromaps/schema/micromap.schema.json create mode 100644 extensions/2.0/Vendor/NV_opacity_micromap/README.md create mode 100644 extensions/2.0/Vendor/NV_opacity_micromap/schema/mesh.primitive.NV_opacity_micromap.schema.json diff --git a/extensions/2.0/Vendor/NV_attribute_micromap/README.md b/extensions/2.0/Vendor/NV_attribute_micromap/README.md new file mode 100644 index 0000000000..2c69e36a5b --- /dev/null +++ b/extensions/2.0/Vendor/NV_attribute_micromap/README.md @@ -0,0 +1,129 @@ +# NV_attribute_micromap + +## Contributors + +- Neil Bickford, NVIDIA, [@NeilBickford-NV](https://github.com/NeilBickford-NV) +- Christoph Kubisch, NVIDIA, [@pixeljetstream](https://github.com/pixeljetstream) +- Martin-Karl Lefrancois, NVIDIA, [@mklefrancois](https://github.com/mklefrancois) + +## Status + +Draft + +## Dependencies + +Written against the glTF 2.0 spec. Depends on `NV_micromaps`. + +## Overview + +This extension adds support for arbitrary microtriangle attribute data in glTF micromeshes. + +Mesh vertices often contain additional vertex attributes, such as normals, tangents, and texture coordinates. By default, microvertex attributes are linearly interpolated from base vertex attributes. Material textures, such as normal maps, can often represent the difference between interpolated and high-detail shading normals. However, storing microvertex attributes for each microvertex directly or in a compressed format can have storage and performance benefits. + +*Attribute micromaps* (AMMs) **MAY** be used to store data for microvertex attributes. AMMs **MAY** also be used to store attribute data for faces of microtriangles. + +## Extending Primitives + +Here's an example (presented piece-by-piece) of how this extension extends glTF primitives. It describes a glTF scene with one attribute micromap (AMM), stored in a BARY file. + +Microtriangle attribute information is added to a primitive by adding the `NV_attribute_micromap` extension. In this example, the primitive specifies normal information from the first micromap. A renderer would load any other attributes from other extensions, or interpolate them from the base mesh vertices. + +```json +"meshes": [ + { + "primitives": [ + { + "indices": 1, + "material": 0, + "attributes": { + "POSITION": 2 + }, + "extensions": { + "NV_attribute_micromap": { + "NORMAL": 0 + } + } + } + ] + } +] +``` + +`micromap` is an index into the `micromaps` array provided by the `NV_micromaps` extension: + +```json +"extensions": { + "NV_micromaps": { + "micromaps": [ + { + "uri": "example.bary" + } + ] + } +} +``` + +## Properties + +The table below lists all properties of this extension. + +Several properties may be specified using an element offset into a property contained within the AMM, or as an accessor index (these glTF properties are named in `XOffset` and `X` pairs, where `X` is a string). When the accessor index property exists in a primitive, it overrides the AMM property. + +Within a glTF primitive, all attributes' micromaps must use the same *value layout* and yield the same subdivision levels, index mapping buffers, and primitive flags. If the primitive has a displacement micromap, these restrictions also apply in combination with the displacement micromap. + +| | Type | Description | Required | +|-|------|-------------|----------| +| **groupIndex** | `integer` | A micromap **MAY** contain multiple *groups*, much like how a scene file **MAY** contain multiple meshes. This is the index of the MM group to use. | No, default: `0` | +| **attributes** | `object` | A plain JSON object. For each key-value pair, the key corresponds to a mesh attribute semantic, and each value is the index of the micromap containing the data (using group 0) to use for microtriangles. **MUST** contain at least one key-value pair. | Yes | +| **mapIndicesOffset** | `integer` | The element offset into the AMM's index mapping buffer (in the BARY format, this is the `eMeshTriangleMappings` standard property). If the AMM has no index mapping buffer, it defaults to the identity mapping: triangle ID `i` uses mesh primitive `i`. | No, default, `0` | +| **mapIndices** | `integer` | The index of the `accessor`whose data overrides that referenced by `mapIndicesOffset`. The accessor's `type` **MUST** be `"SCALAR"`, and its `componentType` **MUST** be 5121, 5123, or 5125 (unsigned byte, short, or int). | No | +| **mapOffset** | `integer` | An offset to be added to each value of the index mapping buffer. It **MUST NOT** be negative. | No, default: `0` | +| **primitiveFlagsOffset** | `integer` | The element offset into the AMM's flags per base mesh primitive, such as adjacency bits for bridging between triangles with different subdivision levels. (In the BARY format, this is the `eMeshTriangleFlags` standard property). If the AMM has no primitive flags, the primitive flags default to all 0. | No, default: `0` | +| **primitiveFlags** | `integer` | The index of the `accessor` whose data overrides that referenced by `primitiveFlagsOffset`. The accessor's `type` **MUST** be `SCALAR`, and its `componentType` **MUST** be 5121 (unsigned byte). | No | + +## Micromap Value Lookup + +An index mapping buffer allows a block of micromap data to be used by multiple base mesh triangles. + +The following informative pseudocode illustrates how the values of a `bary::Triangle` are read from a glTF triangle when storing micromap data in BARY format. + +``` cpp +if (mapIndices) +{ + // The mapIndices glTF accessor has top priority. + baryTriangleIndex = mapIndices[ triangleIndex ]; +} +else if (bary.properties.mesh_triangle_mappings) +{ + // If the BARY eMeshTriangleMappings standard property type exists, use it. + baryTriangleIndex = bary.properties.mesh_triangle_mappings[ triangleIndex + mapIndicesOffset ]; +} +else +{ + // Otherwise, use the triangle index directly. + baryTriangleIndex = triangleIndex; +} + +// Always apply mapOffset and the group's offset. +baryTriangleIndex += mapOffset + bary.properties.groups[ groupIndex ].triangleFirst; +// Get the final primitive information. +baryTriangle = bary.properties.triangles[ baryTriangleIndex ]; + +// Get the byte offset where values for this primitive start +valuesByteOffset = baryTriangle.valueByteOffset; +// Adjust it by the group's offset: +valuesByteOffset += bary.valuesInfo.valueByteSize * bary.properties.groups[ groupIndex ].valueFirst; +// Get a pointer to this primitive's data, starting at its first value: +valuesFirst = &bary.values[ valuesByteOffset ]; + +// Then access values according to +// bary.valuesInfo.valueFrequency (this must be ePerVertex for a DMM), +// bary.valuesInfo.valueLayout (e.g. are the values in bird curve order?), +// bary.valuesInfo.valueFormat (e.g. value type size and compression), +// baryTriangle.subdivLevel (e.g. how many values are there?), and +// baryTriangle.blockFormat (if applicable) +``` + +## Known Implementations + +Currently supported in the [NVIDIA Micro-Mesh SDK](https://developer.nvidia.com/rtx/ray-tracing/micro-mesh). diff --git a/extensions/2.0/Vendor/NV_attribute_micromap/schema/mesh.primitive.NV_attribute_micromap.schema.json b/extensions/2.0/Vendor/NV_attribute_micromap/schema/mesh.primitive.NV_attribute_micromap.schema.json new file mode 100644 index 0000000000..cd4cccb705 --- /dev/null +++ b/extensions/2.0/Vendor/NV_attribute_micromap/schema/mesh.primitive.NV_attribute_micromap.schema.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "mesh.primitive.NV_attribute_micromap.schema.json", + "title": "NV_attribute_micromap", + "type": "object", + "description": "Allows glTF micromeshes to have arbitrary attribute data for vertices and/or faces of microtriangles. Micromaps are also known as *attribute micromaps* (AMMs) when used to store data for microtriangle attributes.", + "allOf": [ { "$ref": "glTFChildOfRootProperty.schema.json" } ], + "properties": { + "micromap": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the micromap in the NV_micromaps micromaps array to use for displacement information." + }, + "attributes": { + "type": "object", + "description": "A plain JSON object. For each key-value pair, the key corresponds to a mesh attribute semantic, and each value is the index of the micromap containing the data to use for microtriangles.", + "minProperties": 1, + "additionalProperties": { + "$ref": "glTFid.schema.json" + } + }, + "mapIndicesOffset": { + "type": "integer", + "description": "The element offset into the DMM's index mapping buffer.", + "gltf_detailedDescription": "The element offset into the DMM's index mapping buffer (in the BARY format, this is the `eMeshTriangleMappings` standard property). Its data can be overridden by `mapIndices`. If the DMM contains no index mapping buffer, then it defaults to the identity mapping: triangle ID `i` uses mesh primitive `i`.", + "minimum": 0, + "default": 0 + }, + "mapIndices": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the index mapping buffer. Overrides `mapIndicesOffset`.", + "gltf_detailedDescription": "The index of the `accessor`whose data overrides that referenced by `mapIndicesOffset`. The accessor's `type` **MUST** be `SCALAR`, and its `componentType` **MUST** be 5121, 5123, or 5125 (unsigned byte, unsigned short, or unsigned int)." + }, + "mapOffset": { + "type": "integer", + "description": "An offset to be added to each value of the index mapping buffer.", + "minimum": 0, + "default": 0 + }, + "primitiveFlagsOffset": { + "type": "integer", + "description": "The element offset into the DMM's flags per base mesh primitive.", + "gltf_detailedDescription": "The element offset into the DMM's flags per base mesh primitive, such as adjacency bits for bridging between triangles with different subdivision levels. (In the BARY format, this is the `eMeshTriangleFlags` standard property). Its data can be overridden by `primitiveFlags`. If the DMM does not contain primitive flags, then they default to all 0.", + "minimum": 0, + "default": 0 + }, + "primitiveFlags": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the flags per base mesh primitive. Overrides `primitiveFlagsOffset`.", + "gltf_detailedDescription": "The index of the `accessor` whose data overrides that referenced by `primitiveFlagsOffset`. The accessor's `type` **MUST** be `SCALAR`, and its `componentType` **MUST** be 5121 (unsigned byte)." + }, + "extensions": { }, + "extras": { } + }, + "required": [ "micromap", "attributes" ] +} diff --git a/extensions/2.0/Vendor/NV_displacement_micromap/README.md b/extensions/2.0/Vendor/NV_displacement_micromap/README.md new file mode 100644 index 0000000000..09372e4a1c --- /dev/null +++ b/extensions/2.0/Vendor/NV_displacement_micromap/README.md @@ -0,0 +1,224 @@ +# NV_displacement_micromap + +## Contributors + +- Neil Bickford, NVIDIA, [@NeilBickford-NV](https://github.com/NeilBickford-NV) +- Christoph Kubisch, NVIDIA, [@pixeljetstream](https://github.com/pixeljetstream) +- Martin-Karl Lefrancois, NVIDIA, [@mklefrancois](https://github.com/mklefrancois) + +## Status + +Draft + +## Dependencies + +Written against the glTF 2.0 spec. Depends on `NV_micromaps`. + +References the OpenGL `GL_HALF_FLOAT` type and the Vulkan `VK_NV_displacement_micromap` extension. + +## Overview + +This extension adds the ability for glTF primitives to define geometry in the form of a *displaced micromesh*. This allows highly detailed geometry, defined using displacements from a subdivided base mesh, to be stored in a compact format, which an implementation **MAY** efficiently render without conversion or expansion. + +Displacements are per-microvertex, and do not depend on texture coordinates. Each triangle **MAY** have a different *subdivision level*, and *primitive flags* indicate how to generate microtriangles to avoid T-junctions. This allows different parts of a base mesh to be subdivided at different levels of detail while preserving watertightness properties. + +*Directions* and *direction bounds* together define a volumetric shell around the base mesh that contains the micromesh geometry when using a bounded format. A tightly fitting shell improves quality under compression and quantization, and also enables efficient occlusion culling. + +Displaced micromesh data comes from a *displacement micromap* (DMM). This extension allows DMM data to be reused in several ways: + +* Primitives **MAY** reference different regions of DMM data using *group* indices. +* Primitives **MAY** override several DMM properties, allowing common DMM data to be reused. +* Implementations **MAY** support an *index mapping buffer* that allows individual triangles' displacements to be reused. + +This extension also introduces a *half float* accessor component type (if not provided by another extension) to efficiently store floating-point data. + +| Note | +| ------------------------------------------------------------ | +| This extension has been designed together with the BARY data format so that its micromesh data can be used directly with the Vulkan `VK_NV_displacement_micromap` extension, if the BARY data uses the `bary::Format::eDispC1_r11_unorm_block` value format. | + +## Extending Accessor Component Types + +This extension adds a *half float* accessor component type. A half float is 16 bits long, and contains data according to the binary16 format in the IEEE 754-2008 standard. + +| `componentType` | Data Type | Signed | Bits | +| --------------- | ------------ | ------ | ---- | +| 5131 | *half float* | Signed | 16 | + +| Note | +| ------------------------------------------------- | +| This corresponds to the OpenGL `HALF_FLOAT` type. | + +## Extending Primitives + +Here's an example (presented piece-by-piece) of how this extension extends glTF primitives. It describes a glTF asset with one DMM, stored in a BARY file. One glTF primitive references this DMM using the `micromap` property, selects group 1 using the `group` property, and overrides the DMM's direction bounds using the `directionBounds` property. A renderer would load the remaining displaced micromesh settings from the DMM, other accessors, or use default values as described in the Properties section. + +A displaced micromesh is defined by adding the `NV_displacement_micromap` extension to a glTF primitive. This indicates that instead of rendering each base triangle, the primitive **MUST** be rendered using micromesh geometry as defined in this spec and in `VK_NV_displacement_micromap`. + +```json +"meshes": [ + { + "primitives": [ + { + "indices": 1, + "material": 0, + "attributes": { + "POSITION": 2, + "NORMAL": 3, + "TANGENT": 4 + }, + "extensions": { + "NV_displacement_micromap": { + "micromap": 0, + "groupIndex": 1, + "directionBounds": 0 + } + } + } + ] + } +] +``` + +`micromap` is an index into the `micromaps` array provided by the `NV_micromaps` extension. + +```json +"extensions": { + "NV_micromaps": { + "micromaps": [ + { + "uri": "example-displacement.bary" + } + ] + } +} +``` + +`directionBounds` is the index of an accessor whose data overrides the DMM's direction bounds for this primitive. This example overrides it with half float data. Accessors, buffer views, and buffers other than that used by the `directionBounds` in this example are replaced with ellipses here. + +```json +"accessors": [ + { + "bufferView": 0, + "componentType": 5131, + "type": "VEC2", + "count": 1000 + }, + ... +], +"bufferViews": [ + { + "buffer": 0, + "byteLength": 4000 + }, + ... +], +"buffers": [ + { + "uri": "example.bin", + "byteLength": 4000 + }, + ... +] +``` + +## Properties + +The table below lists all properties of this extension. + +Several properties may be specified using an element offset into a property contained within a DMM, or as an accessor index (these glTF properties are named in `XOffset` and `X` pairs, where `X` is a string). When the accessor index property exists in a primitive, it overrides the DMM property. + +| | Type | Description | Required | +|-|------|-------------|----------| +| **micromap** | `integer` | The index of the `micromap` in the `NV_micromaps` `micromaps` array to use for displacement information. | Yes | +| **groupIndex** | `integer` | A micromap **MAY** contain multiple *groups*, much like how a scene file **MAY** contain multiple meshes. This is the index of the MM group to use. | No, default: `0` | +| **mapIndicesOffset** | `integer` | The element offset into the DMM's index mapping buffer (in the BARY format, this is the `eMeshTriangleMappings` standard property). If the DMM contains no index mapping buffer, then it defaults to the identity mapping: triangle ID `i` uses mesh primitive `i`. | No, default: `0` | +| **mapIndices** | `integer` | The index of the `accessor`whose data overrides that referenced by `mapIndicesOffset`. The accessor's `type` **MUST** be `"SCALAR"`, and its `componentType` **MUST** be 5121, 5123, or 5125 (unsigned byte, unsigned short, or unsigned int). | No | +| **mapOffset** | `integer` | An offset to be added to each value of the index mapping buffer. It **MUST NOT** be negative. | No, default: `0` | +| **directionsOffset** | `integer` | The element offset into the DMM's vertex displacement direction vectors (in the BARY format, this is the `eMeshDisplacementDirections` standard property). There is 1 direction per primitve vertex. If the DMM contains no directions, then they default to the vertex normals; if the primitive has no vertex normals, this property **MUST** be overridden. | No, default: `0` | +| **directions** | `integer` | The index of the `accessor` whose data overrides that referenced by `directionsOffset`. The accessor's `type` **MUST** be either `"VEC3"` with a `componentType` of 5126 (float), or it **MUST** be `"VEC4"` with a `componentType` of 5126 or 5131 (float or half float). | No | +| **directionBoundsOffset** | `integer` | The element offset into the DMM's vertex displacement direction bounds (in the BARY format, this is the `eMeshDisplacementDirectionBounds` standard property). There is 1 direction bound per primitive vertex. If the DMM contains no per-vertex displacement direction bounds, then they default to a *bias* of 0 and a *scale* of 1 for each vertex. | No, default: `0` | +| **directionBounds** | `integer` | The index of the `accessor` whose data overrides that referenced by `directionBoundsOffset`. The accessor's `type` **MUST** be `"VEC2"`, and its `componentType` **MUST** be 5126 or 5131 (float or half float). | No | +| **primitiveFlagsOffset** | `integer` | The element offset into the DMM's flags per base mesh primitive, such as adjacency bits for bridging between triangles with different subdivision levels. (In the BARY format, this is the `eMeshTriangleFlags` standard property). If the DMM does not contain primitive flags, then they default to all 0. | No, default: `0`. | +| **primitiveFlags** | `integer` | The index of the `accessor` whose data overrides that referenced by `primitiveFlagsOffset`. The accessor's `type` **MUST** be `"SCALAR"`, and its `componentType` **MUST** be 5121 (unsigned byte). | No | + +## Micromap Value Lookup + +An index mapping buffer allows a block of micromap data to be used by multiple base mesh triangles. When using the Vulkan `NV_displacement_micromap` extension, it is typically used as the `indexBuffer` field of `VkAccelerationStructureTriangleDisplacementMicromapNV`. + +The following informative pseudocode illustrates how the values of a `bary::Triangle` are read from a glTF triangle when storing micromap data in BARY format. + +``` cpp +if (mapIndices) +{ + // The mapIndices glTF accessor has top priority. + baryTriangleIndex = mapIndices[ triangleIndex ]; +} +else if (bary.properties.mesh_triangle_mappings) +{ + // If the BARY eMeshTriangleMappings standard property type exists, use it. + baryTriangleIndex = bary.properties.mesh_triangle_mappings[ triangleIndex + mapIndicesOffset ]; +} +else +{ + // Otherwise, use the triangle index directly. + baryTriangleIndex = triangleIndex; +} + +// Always apply mapOffset and the group's offset. +baryTriangleIndex += mapOffset + bary.properties.groups[ groupIndex ].triangleFirst; +// Get the final primitive information. +baryTriangle = bary.properties.triangles[ baryTriangleIndex ]; + +// Get the byte offset where values for this primitive start +valuesByteOffset = baryTriangle.valueByteOffset; +// Adjust it by the group's offset: +valuesByteOffset += bary.valuesInfo.valueByteSize * bary.properties.groups[ groupIndex ].valueFirst; +// Get a pointer to this primitive's data, starting at its first value: +valuesFirst = &bary.values[ valuesByteOffset ]; + +// Then access values according to +// bary.valuesInfo.valueFrequency (this must be ePerVertex for a DMM), +// bary.valuesInfo.valueLayout (e.g. are the values in bird curve order?), +// bary.valuesInfo.valueFormat (e.g. value type size and compression), +// baryTriangle.subdivLevel (e.g. how many values are there?), and +// baryTriangle.blockFormat (if the format uses a compressed block format) +``` + +## Direction Bounds + +Each vertex has a *direction bound* in the form of a 2-element vector, containing a *bias* and a *scale*. The scale adjusts the length of displacements, and the bias moves displacements in or out along the direction vector. + +More specifically, direction bounds apply the following adjustments to vertex `v` before displacement is computed (direction bounds are indexed using the primitive's indices): + +``` cpp +position_bounded[v] = position[v] + direction[v] * direction_bounds[v].x; +direction_bounded[v] = direction[v] * direction_bounds[v].y; +``` + +The resulting displacement is applied on the linear interpolation of the triangle's adjusted vertex values: + +``` cpp +uvec3 triangle = uvec3( indices[t * 3 + 0], + indices[t * 3 + 1], + indices[t * 3 + 2]); + +position_microvertex = linear_interpolate( position_bounded[triangle.x], + position_bounded[triangle.y], + position_bounded[triangle.z], + microvertex_wuv); + +direction_microvertex = linear_interpolate( direction_bounded[triangle.x], + direction_bounded[triangle.y], + direction_bounded[triangle.z], + microvertex_wuv); +// Final position. +position_microvertex = position_microvertex + direction_microvertex * displacement; +``` + +where `microvertex_wuv` denotes the barycentric coordinates of the microvertex relative to its base triangle. + +Note that BARY DMMs also have a *group bias* and *group scale*. These are mutually exclusive with the direction bounds: if direction bounds aren't referenced in glTF, then the group bias and scale act as a direction bound bias and scale for the entire primitive. More specifically, if the glTF primitive has `directionBounds` or the DMM has direction bounds, then the first component of the BARY group bias and scale **MUST** be 0.0 and 1.0, respectively. + +## Known Implementations + +Currently supported in the [NVIDIA Micro-Mesh SDK](https://developer.nvidia.com/rtx/ray-tracing/micro-mesh). \ No newline at end of file diff --git a/extensions/2.0/Vendor/NV_displacement_micromap/schema/mesh.primitive.NV_displacement_micromap.schema.json b/extensions/2.0/Vendor/NV_displacement_micromap/schema/mesh.primitive.NV_displacement_micromap.schema.json new file mode 100644 index 0000000000..d4e5f8471b --- /dev/null +++ b/extensions/2.0/Vendor/NV_displacement_micromap/schema/mesh.primitive.NV_displacement_micromap.schema.json @@ -0,0 +1,78 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "mesh.primitive.NV_displacement_micromap.schema.json", + "title": "NV_displacement_micromap", + "type": "object", + "description": "Defines geometry in the form of a displaced micromesh, using a micromap (called a displacement micromap [DMM] in this context).", + "allOf": [ { "$ref": "glTFChildOfRootProperty.schema.json" } ], + "properties": { + "micromap": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the micromap in the NV_micromaps micromaps array to use for displacement information." + }, + "groupIndex": { + "type": "integer", + "description": "The index of the group to use within the micromap.", + "gltf_detailedDescription": "A micromap **MAY** contain multiple *groups*, much like how a scene file **MAY** contain multiple meshes. This is the index of the MM group to use.", + "minimum": 0, + "default": 0 + }, + "mapIndicesOffset": { + "type": "integer", + "description": "The element offset into the DMM's index mapping buffer.", + "gltf_detailedDescription": "The element offset into the DMM's index mapping buffer (in the BARY format, this is the `eMeshTriangleMappings` standard property). Its data can be overridden by `mapIndices`. If the DMM contains no index mapping buffer, then it defaults to the identity mapping: triangle ID `i` uses mesh primitive `i`.", + "minimum": 0, + "default": 0 + }, + "mapIndices": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the index mapping buffer. Overrides `mapIndicesOffset`.", + "gltf_detailedDescription": "The index of the `accessor`whose data overrides that referenced by `mapIndicesOffset`. The accessor's `type` **MUST** be `SCALAR`, and its `componentType` **MUST** be 5121, 5123, or 5125 (unsigned byte, unsigned short, or unsigned int)." + }, + "mapOffset": { + "type": "integer", + "description": "An offset to be added to each value of the index mapping buffer.", + "minimum": 0, + "default": 0 + }, + "directionsOffset": { + "type": "integer", + "description": "The element offset into the DMM's vertex displacement direction vectors array.", + "gltf_detailedDescription": "The element offset into the DMM's vertex displacement direction vectors (in the BARY format, this is the `eMeshDisplacementDirections` standard property). There is 1 direction per primitive vertex. Its data can be overridden by `directions`. If the DMM contains no directions, then they default to the vertex normals; if the primitive has no vertex normals, this property **MUST** be overridden.", + "minimum": 0, + "default": 0 + }, + "directions": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the vertex displacement directions. Overrides `directionsOffset`.", + "gltf_detailedDescription": "The index of the `accessor` whose data overrides that referenced by `directionsOffset`. The accessor's `type` **MUST** be either `VEC3` and with a `componentType` of 5126 (float), or it **MUST** be `VEC4` with a `componentType` of 5126 or 5131 (float or half float)." + }, + "directionBoundsOffset": { + "type": "integer", + "description": "The element offset into the DMM's vertex displacement direction bounds array.", + "gltf_detailedDescription": "The element offset into the DMM's vertex displacement direction bounds (in the BARY format, this is the `eMeshDisplacementDirectionBounds` standard property). There is 1 direction bound per primitive vertex. Its data can be overridden by `directionBounds`. If the DMM contains no per-vertex displacement direction bounds, then they default to a *bias* of 0 and a *scale* of 1 for each vertex.", + "minimum": 0, + "default": 0 + }, + "directionBounds": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the vertex displacement bounds. Overrides `directionBoundsOffset`.", + "gltf_detailedDescription": "The index of the `accessor` whose data overrides that referenced by `directionBoundsOffset`. The accessor's `type` **MUST** be `VEC3`, and its `componentType` **MUST** be 5126 or 5131 (float or half float)." + }, + "primitiveFlagsOffset": { + "type": "integer", + "description": "The element offset into the DMM's flags per base mesh primitive.", + "gltf_detailedDescription": "The element offset into the DMM's flags per base mesh primitive, such as adjacency bits for bridging between triangles with different subdivision levels. (In the BARY format, this is the `eMeshTriangleFlags` standard property). Its data can be overridden by `primitiveFlags`. If the DMM does not contain primitive flags, then they default to all 0.", + "minimum": 0, + "default": 0 + }, + "primitiveFlags": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the flags per base mesh primitive. Overrides `primitiveFlagsOffset`.", + "gltf_detailedDescription": "The index of the `accessor` whose data overrides that referenced by `primitiveFlagsOffset`. The accessor's `type` **MUST** be `SCALAR`, and its `componentType` **MUST** be 5121 (unsigned byte)." + }, + "extensions": { }, + "extras": { } + }, + "required": [ "micromap" ] +} diff --git a/extensions/2.0/Vendor/NV_micromap_tooling/README.md b/extensions/2.0/Vendor/NV_micromap_tooling/README.md new file mode 100644 index 0000000000..dea2e43610 --- /dev/null +++ b/extensions/2.0/Vendor/NV_micromap_tooling/README.md @@ -0,0 +1,77 @@ +# NV_micromap_tooling + +## Contributors + +- Neil Bickford, NVIDIA, [@NeilBickford-NV](https://github.com/NeilBickford-NV) +- Christoph Kubisch, NVIDIA, [@pixeljetstream](https://github.com/pixeljetstream) +- Martin-Karl Lefrancois, NVIDIA, [@mklefrancois](https://github.com/mklefrancois) + +## Status + +Draft + +## Dependencies + +Written against the glTF 2.0 spec. References definitions from the `NV_displacement_micromap` specification. + +## Overview + +This extension allows tools to store and retrieve data about how to generate micromaps. + +Micromesh generation is sometimes separated into different tools: for instance, a *remesher* might generate a low-resolution mesh from a high-resolution mesh, and then call a *baker* to generate a displaced micromap (DMM) that makes the low-resolution mesh resemble the high-resolution mesh. + +Tools earlier in pipelines may generate auxiliary data that subsequent tools may use to generate results of potentially higher quality. For instance, the remesher may know what vertices in the high-resolution mesh combined to produce a vertex in the low-resolution mesh; this is information the baker cannot easily re-compute. A remesher could provide an intended subdivision level for each triangle; if the baker uses these, it could get higher-quality visual results while generating a file of equivalent size. + +| Warning | +| ------------------------------------------------------------ | +| This extension's for internal use only at the moment, because it's possible the need for it might go away if we can interchange data between tools without glTF. | + +## Example + +To tag a primitive with data subsequent tools may use, add the `NV_micromap_tooling` extension to that primitive's `extensions`, and fill it with properties. + +This extension allows adding arbitrary JSON members. In the example below, we list two *standard properties* defined in this extension: `directionBounds`, which has the same meaning as in `NV_displacement_micromap` but here does not require a `micromap` member, and `subdivisionLevels`, described in the Properties section. Implementations **MAY** add their own properties, such as `myCustomProperty` below, with implementation-defined JSON values. + +```json +"meshes": [ + { + "primitives": [ + { + "indices": 1, + "material": 0, + "attributes": { + "POSITION": 2, + "NORMAL": 3, + "TANGENT": 4 + }, + "extensions": { + "NV_micromap_baking": { + "directionBounds": 0, + "subdivisionLevels": 5, + "myCustomProperty": { + "arbitraryData": "...", + ... + } + } + } + } + ] + } +] +``` + +## Properties + +We define the following standard property strings and descriptions. All properties are optional. + +| Name | Type | Description | +| --------------------- | --------- | ------------------------------------------------------------ | +| **mapIndices** | `integer` | Same as in `NV_displacement_micromap`. | +| **mapOffset** | `integer` | Same as in `NV_displacement_micromap`. | +| **directions** | `integer` | Same as in `NV_displacement_micromap`. | +| **directionBounds** | `integer` | Same as in `NV_displacement_micromap`. This should give a shell for raycasting when baking: in other words, a tool should assume that the displaced mesh can fit between the shell defined by this mesh with all values equal to 0.0, and this mesh with all values equal to 1.0. | +| **primitiveFlags** | `integer` | Same as in `NV_displacement_micromap`. | +| **subdivisionLevels** | `integer` | The index of an `accessor`; element `i` of this accessor gives an intended subdivision level for primitive triangle `i`. Its `type` **MUST** be `"SCALAR"`, and its `componentType` **MUST** be 5121 (unsigned byte) or 5123 (unsigned short). | + +Implementations **MAY** add other properties, whose type and definition are *implementation-defined*. This extension provides no guarantee that two implementations will agree on the definitions or types of implementation-defined properties. + diff --git a/extensions/2.0/Vendor/NV_micromap_tooling/schema/mesh.primitive.NV_micromap_tooling.schema.json b/extensions/2.0/Vendor/NV_micromap_tooling/schema/mesh.primitive.NV_micromap_tooling.schema.json new file mode 100644 index 0000000000..3317427bcb --- /dev/null +++ b/extensions/2.0/Vendor/NV_micromap_tooling/schema/mesh.primitive.NV_micromap_tooling.schema.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "mesh.primitive.NV_micromap_tooling.schema.json", + "title": "NV_micromap_tooling", + "type": "object", + "description": "Allows tools to store and retrieve data about how to generate micromaps. All properties are optional.", + "allOf": [ { "$ref": "glTFChildOfRootProperty.schema.json" } ], + "properties": { + "mapIndices": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the index mapping buffer.", + "gltf_detailedDescription": "The index of the `accessor` providing the index mapping buffer. The accessor's `type` **MUST** be `SCALAR`, and its `componentType` **MUST** be 5121, 5123, or 5125 (unsigned byte, unsigned short, or unsigned int)." + }, + "mapOffset": { + "type": "integer", + "description": "An offset to be added to each value of the index mapping buffer.", + "minimum": 0, + "default": 0 + }, + "directions": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the vertex displacement directions.", + "gltf_detailedDescription": "The index of the `accessor` providing the vertex displacement directions. There is 1 direction per primitive vertex. The index of the `accessor` whose data overrides that referenced by `directionsOffset`. The accessor's `type` **MUST** be either `VEC3` with a `componentType` of 5126 (float), or it **MUST** be `VEC4` with a `componentType` of 5126 or 5131 (float or half float)." + }, + "directionBounds": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the vertex displacement bounds.", + "gltf_detailedDescription": "The index of the `accessor` providing one 2-element {bias, scale} vector of vertex displacement bounds. This should give a shell for raycasting when baking: in other words, a tool should assume that the displaced mesh can fit between the shell defined by this mesh with all micromap values equal to 0.0, and this mesh with all values equal to 1.0. The accessor's `type` **MUST** be `VEC2`, and its `componentType` **MUST** be 5126 or 5131 (float or half float)." + }, + "primitiveFlags": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the flags per base mesh primitive.", + "gltf_detailedDescription": "The index of the `accessor` providing the flags per base mesh primitive, such as adjacency bits for bridging between triangles with different subdivision levels. The accessor's `type` **MUST** be `SCALAR`, and its `componentType` **MUST** be 5121 (unsigned byte)." + }, + "subdivisionLevels": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the subdivision level per base mesh primitive.", + "gltf_detailedDescription": "The index of an `accessor`; element `i` of this accessor gives an intended subdivision level for primitive triangle `i`. Its `type` **MUST** be `SCALAR`, and its `componentType` **MUST** be 5121 (unsigned byte) or 5123 (unsigned short)." + }, + "extensions": { }, + "extras": { } + }, + "required": [ ] +} diff --git a/extensions/2.0/Vendor/NV_micromaps/README.md b/extensions/2.0/Vendor/NV_micromaps/README.md new file mode 100644 index 0000000000..a4fa16ab93 --- /dev/null +++ b/extensions/2.0/Vendor/NV_micromaps/README.md @@ -0,0 +1,63 @@ +# NV_micromaps + +## Contributors + +- Neil Bickford, NVIDIA, [@NeilBickford-NV](https://github.com/NeilBickford-NV) +- Christoph Kubisch, NVIDIA, [@pixeljetstream](https://github.com/pixeljetstream) +- Martin-Karl Lefrancois, NVIDIA, [@mklefrancois](https://github.com/mklefrancois) + +## Status + +Draft + +## Dependencies + +Written against the glTF 2.0 spec. References the BARY file format. + +## Overview + +This extension adds the ability for glTF assets to have *micromap* (MM) data stored in buffers or files. A micromap stores an array of (formatted, possibly compressed) *values*, and **MAY** store additional *micromap properties*, such as vertex displacement directions. + +Each glTF `primitive` **MAY** have extension properties that indicate how to use a micromap. The properties and the micromap together specify how to subdivide and modify a *base mesh* to produce a virtual *micromesh*. + +This asset-level extension defines a `micromaps` array. Each of the elements in the `micromaps` array is an object that contains properties, much like an element of `images`: micromap data can be embedded, or linked as an external resource. + +| Note | +| ------------------------------------------------------------ | +| Micromaps can be used in many different ways, and are typically used to store highly detailed microgeometry information in a compact format. For instance, *displacement micromaps* produce microgeometry by displacing vertices, *opacity micromaps* store per-microtriangle opacity information, and *attribute micromaps* can store microvertex attributes such as shading normals. Because applications may support a subset of micromap capabilities, this extension specifies the common interface for defining micromaps, to be used by other extensions.

Types of micromap data can be used by graphics API extensions, such as `VK_EXT_opacity_micromap` and `VK_NV_displacement_micromap`. Importantly, implementations may render micromeshes without storing a subdivided mesh in memory.

We reference the BARY file format for storing micromap data in this extension; in addition, applications may use custom micromap formats.

In many cases, micromap extensions are designed so that the glTF file defines a valid asset if the micromap extensions are ignored. | + +## Extending Assets + +The glTF asset's `extensions` array **MAY** contain an `NV_micromaps` object, which in turn **MAY** contain a `micromaps` array. The term *micromap* refers interchangeably to an element of the `micromaps` array, or the data within a micromap format referenced at some level by an element of the `micromaps` array. + +The following glTF asset snippet shows an example of such a `micromaps` array. This example array defines two micromaps: micromap 0 references a BARY file, and micromap 1 has a reference to a `bufferView`; although defined outside this snippet, this `bufferView` would reference micromap data within a buffer. + +```json +"extensions": { + "NV_micromaps": { + "micromaps": [ + { + "uri": "example-opacity.bary" + }, + { + "bufferView": 10, + "mimeType": "model/vnd.bary" + } + ] + } +} +``` + +## Properties +Each element of the `micromaps` array **MAY** contain a `mimeType`, and **MUST** contain one of +* a URI (or IRI) to an external file in one of the supported micromap formats, or +* a Data URI with embedded data, or +* a reference to a `bufferView`; in that case `mimeType` **MUST** be defined. + +BARY micromaps **SHOULD** use the `model/vnd.bary` Media Type, and/or the `.bary` file extension. The format of the micromap data **MUST** match the `mimeType` property when the latter is defined. + +Implementations **MAY** need to manually determine the media type of a micromap. In such a case, the 6 pattern bytes `0xAB 0x42 0x41 0x52 0x59 0x20` **SHOULD** be used to determine whether the media type is `model/vnd.bary`. + +## Known Implementations + +Currently supported in the [NVIDIA Micro-Mesh SDK](https://developer.nvidia.com/rtx/ray-tracing/micro-mesh). diff --git a/extensions/2.0/Vendor/NV_micromaps/schema/glTF.NV_micromaps.schema.json b/extensions/2.0/Vendor/NV_micromaps/schema/glTF.NV_micromaps.schema.json new file mode 100644 index 0000000000..d51a6a2db1 --- /dev/null +++ b/extensions/2.0/Vendor/NV_micromaps/schema/glTF.NV_micromaps.schema.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "NV_micromaps glTF extension", + "type": "object", + "description": "glTF Extension that adds a list of micromaps for other extensions to reference. These are used, for instance, to define micro-triangle displacement or opacity.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "micromaps": { + "type": "array", + "description": "An array of micromaps.", + "items": { + "$ref": "micromap.schema.json" + }, + "minItems": 1, + "gltf_detailedDescription": "An array of micromaps. A micromap contains an array of (formatted, possibly compressed) *values*, and **MAY** store additional *micromap properties*, such as vertex displacement directions." + }, + "extensions": { }, + "extras": { } + } +} diff --git a/extensions/2.0/Vendor/NV_micromaps/schema/micromap.schema.json b/extensions/2.0/Vendor/NV_micromaps/schema/micromap.schema.json new file mode 100644 index 0000000000..9d17603c6a --- /dev/null +++ b/extensions/2.0/Vendor/NV_micromaps/schema/micromap.schema.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "micromap.schema.json", + "title": "Micromap", + "type": "object", + "description": "Specifies where to find a micromap (e.g. a .bary file or another format). A micromap stores an array of (formatted, possibly compressed) *values*, and **MAY** store additional *micromap properties*, such as vertex displacement directions. Like an image, it may be referenced by an URI (or IRI) or a buffer view index.", + "allOf": [ { "$ref": "glTFChildOfRootProperty.schema.json" } ], + "properties": { + "uri": { + "type": "string", + "description": "The URI (or IRI) of the micromap.", + "format": "iri-reference", + "gltf_detailedDescription": "The URI (or IRI) of the micromap. Relative paths are relative to the current glTF asset. Instead of referencing an external file, this field **MAY** contain a `data:`-URI. This field **MUST NOT** be defined when `bufferView` is defined.", + "gltf_uriType": "model" + }, + "mimeType": { + "anyOf": [ + { + "const": "model/vnd.bary" + }, + { + "type": "string" + } + ], + "description": "The micromap's media type. This field **MUST** be defined when `bufferView` is defined." + }, + "bufferView": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the bufferView that contains the micromap. This field **MUST NOT** be defined when `uri` is defined." + }, + "name": { }, + "extensions": { }, + "extras": { } + }, + "dependencies": { + "bufferView": [ "mimeType" ] + }, + "oneOf": [ + { "required": [ "uri" ] }, + { "required": [ "bufferView" ] } + ] +} diff --git a/extensions/2.0/Vendor/NV_opacity_micromap/README.md b/extensions/2.0/Vendor/NV_opacity_micromap/README.md new file mode 100644 index 0000000000..736429c52a --- /dev/null +++ b/extensions/2.0/Vendor/NV_opacity_micromap/README.md @@ -0,0 +1,174 @@ +# NV_opacity_micromap + +## Contributors + +- Neil Bickford, NVIDIA, [@NeilBickford-NV](https://github.com/NeilBickford-NV) +- Christoph Kubisch, NVIDIA, [@pixeljetstream](https://github.com/pixeljetstream) +- Martin-Karl Lefrancois, NVIDIA, [@mklefrancois](https://github.com/mklefrancois) + +## Status + +Draft + +## Dependencies + +Written against the glTF 2.0 spec. Depends on `NV_micromaps`. + +References the Vulkan `VK_EXT_opacity_micromap` extension. + +## Overview + +This extension adds the ability for glTF primitives to express *opacity micromeshes*. These efficiently encode the opacity of microtriangles from a subdivided base mesh. In particular, using OMMs allows implementations of graphics API extensions such as `VK_EXT_opacity_micromap` to reduce any-hit shader invocations when ray tracing alpha-tested objects, such as foliage. + +Opacity micromesh data comes from an *opacity micromesh* (OMM). This extension allows OMM data to be reused in several ways: + +* Primitives **MAY** reference different regions of OMM data using *group* indices. +* Primitives **MAY** override several OMM properties, allowing common OMM data to be reused. +* Implementations **MAY** support an *index mapping buffer* that allows individual triangles' opacities to be reused. + +## Extending Primitives + +Here's an example (presented piece-by-piece) of how this extension extends glTF primitives. It describes a glTF asset with one opacity micromap (OMM) file. One glTF primitive references this OMM, and overrides the mesh-to-micromap-triangle mapping through the `mapIndices` accessors. A renderer would load the remaining settings from the OMM, other accessors, or use default values as described in the Properties section. + +An opacity micromesh is defined by adding the `NV_opacity_micromap` extension to a glTF primitive. This indicates that instead of rendering each base triangle, the primitive **MUST** be rendered using an opacity micromap as defined in this spec and in `VK_EXT_opacity_micromap`. + +```json +"meshes": [ + { + "primitives": [ + { + "indices": 0, + "material": 0, + "attributes": { + "POSITION": 1, + "NORMAL": 2, + "TEXCOORD_0": 3, + "TANGENT": 4 + }, + "extensions": { + "NV_opacity_micromap": { + "micromap": 0, + "mapIndices": 5 + } + } + ] + } +] +``` + +`micromap` is an index into the `micromaps` array provided by the `NV_micromaps` extension. + +```json +"extensions": { + "NV_micromaps": { + "micromaps": [ + { + "uri": "example-opacity.bary" + } + ] + } +} +``` + +`mapIndices` is the index of the accessor whose data overrides the OMM's index mapping buffer. In this example, we override it with unsigned short data; if we had 1000 triangles in the primitive, this accessor would contain 1000 elements, 2000 bytes of data. Accessors, buffer views, and buffers other than that used by the `mapIndices` in this example are replaced with ellipses here. + +```json +"accessors": [ + { + "bufferView": 0, + "componentType": 5123, + "type": "SCALAR", + "count": 1000 + }, + ... +], +"bufferViews": [ + { + "buffer": 0, + "byteLength": 2000 + }, + ... +], +"buffers": [ + { + "uri": "example.bin", + "byteLength": 2000 + }, + ... +] +``` + +## Properties + +The table below lists all properties of this extension. + +The index mapping buffer may be specified in the OMM or using `mapIndices`. If both are specified, `mapIndices` takes precedence; if no index mapping buffer is specified, triangle `i` uses micromap primitive `i`. + +| | Type | Description | Required | +|-|------|-------------|----------| +| **micromap** | `integer` | The index of the `micromap` in the `NV_micromaps` `micromaps` array to use for opacity information. | Yes | +| **groupIndex** | `integer` | A micromap **MAY** contain multiple *groups*, much like how a scene file **MAY** contain multiple meshes. This is the index of the MM group to use. | No, default: `0`. | +| **mapIndicesOffset** | `integer` | The element offset into the OMM's index mapping buffer (in the BARY format, this is the `eMeshTriangleMappings` standard property). If the OMM contains no index mapping buffer, then it defaults to the identity mapping: triangle ID `i` uses mesh primitive `i`. | No, default: `0`. | +| **mapIndices** | `integer` | The index of the `accessor` whose data overrides that referenced by `mapIndicesOffset`. The accessor's `type` **MUST** be `"SCALAR"`, and its `componentType` **MUST** be 5121, 5123, or 5125 (unsigned byte, short, or int). | No | +| **mapOffset** | `integer` | An offset to be added to each value of the index mapping buffer. It **MUST NOT** be negative. | No, default: `0`. | + +## Micromap Value Lookup + +An index mapping buffer allows a block of micromap data to be used by multiple base mesh triangles. When using the Vulkan `NV_displacement_micromap` extension, it is typically used as the `indexBuffer` field of `VkAccelerationStructureTrianglesOpacityMicromapEXT`. + +The following informative pseudocode illustrates how the values of a `bary::Triangle` are read from a glTF triangle when storing micromap data in BARY format. + +``` cpp +if (mapIndices) +{ + // The mapIndices glTF accessor has top priority. + baryTriangleIndex = mapIndices[ triangleIndex ]; +} +else if (bary.properties.mesh_triangle_mappings) +{ + // If the BARY eMeshTriangleMappings standard property type exists, use it. + baryTriangleIndex = bary.properties.mesh_triangle_mappings[ triangleIndex + mapIndicesOffset ]; +} +else +{ + // Otherwise, use the triangle index directly. + baryTriangleIndex = triangleIndex; +} + +switch(baryTriangleIndex) +{ +case VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT: +case VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT: +case VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT: +case VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT: + // All microtriangles in this triangle have the same opacity. + // Handle special behavior, then exit. + return; +default: + // Proceed with fetching micromap data. + break; +} + +// Always apply mapOffset and the group's offset. +baryTriangleIndex += mapOffset + bary.properties.groups[ groupIndex ].triangleFirst; +// Get the final primitive information. +baryTriangle = bary.properties.triangles[ baryTriangleIndex ]; + +// Get the byte offset where values for this primitive start. +valuesByteOffset = baryTriangle.valueByteOffset; +// Adjust it by the group's offset: +valuesByteOffset += bary.valuesInfo.valueByteSize * bary.properties.groups[ groupIndex ].valueFirst; +// Get a pointer to this primitive's data, starting at its first value: +valuesFirst = &bary.values[ valuesByteOffset ]; + +// Then access values according to +// bary.valuesInfo.valueFrequency (this must be ePerTriangle for an OMM), +// bary.valuesInfo.valueLayout (e.g. are the values in bird curve order?, +// bary.valuesInfo.valueFormat (e.g. value type size and compression), +// baryTriangle.subdivLevel (e.g. how many values are there?), and +// baryTriangle.blockFormat (if the format uses a compressed block format) +``` + +## Known Implementations + +Currently supported in the [NVIDIA Micro-Mesh SDK](https://developer.nvidia.com/rtx/ray-tracing/micro-mesh). \ No newline at end of file diff --git a/extensions/2.0/Vendor/NV_opacity_micromap/schema/mesh.primitive.NV_opacity_micromap.schema.json b/extensions/2.0/Vendor/NV_opacity_micromap/schema/mesh.primitive.NV_opacity_micromap.schema.json new file mode 100644 index 0000000000..798c8c5197 --- /dev/null +++ b/extensions/2.0/Vendor/NV_opacity_micromap/schema/mesh.primitive.NV_opacity_micromap.schema.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "mesh.primitive.NV_opacity_micromap.schema.json", + "title": "NV_opacity_micromap", + "type": "object", + "description": "Allows geometry to express *opacity micromeshes*, which encode the opacity of microtriangles from a subdivided base mesh. Micromaps used in this context are also called *opacity micromaps* (OMMs).", + "allOf": [ { "$ref": "glTFChildOfRootProperty.schema.json" } ], + "properties": { + "micromap": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the micromap in the NV_micromaps micromaps array to use for opacity information." + }, + "groupIndex": { + "type": "integer", + "description": "The index of the group to use within the micromap.", + "gltf_detailedDescription": "A micromap **MAY** contain multiple *groups*, much like how a scene file **MAY** contain multiple meshes. This is the index of the MM group to use.", + "minimum": 0, + "default": 0 + }, + "mapIndicesOffset": { + "type": "integer", + "description": "The element offset into the OMM's index mapping buffer.", + "gltf_detailedDescription": "The element offset into the OMM's index mapping buffer (in the BARY format, this is the `eMeshTriangleMappings` standard property). Its data can be overridden by `mapIndices`. If the OMM contains no index mapping buffer, then it defaults to the identity mapping: triangle ID `i` uses mesh primitive `i`.", + "minimum": 0, + "default": 0 + }, + "mapIndices": { + "allOf": [ { "$ref": "glTFid.schema.json" } ], + "description": "The index of the accessor providing the index mapping buffer. Overrides `mapIndicesOffset`.", + "gltf_detailedDescription": "The index of the `accessor` whose data overrides that referenced by `mapIndicesOffset`. The accessor's `type` **MUST** be `SCALAR`, and its `componentType` **MUST** be 5121, 5123, or 5125 (unsigned byte, unsigned short, or unsigned int)." + }, + "mapOffset": { + "type": "integer", + "description": "An offset to be added to each value of the index mapping buffer.", + "minimum": 0, + "default": 0 + }, + "extensions": { }, + "extras": { } + }, + "required": [ "micromap" ] +}