Skip to content

Commit 6280fd6

Browse files
authored
Update README.md
Add `meshtopt_generateShadowIndexBuffer` documentation in a new "shadow indexing" section.
1 parent 5719e0a commit 6280fd6

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ When optimizing a mesh, you should typically feed it through a set of optimizati
4141
4. Overdraw optimization
4242
5. Vertex fetch optimization
4343
6. Vertex quantization
44-
7. (optional) Vertex/index buffer compression
44+
7. Shadow indexing
45+
8. (optional) Vertex/index buffer compression
4546

4647
## Indexing
4748

@@ -124,6 +125,29 @@ unsigned short pz = meshopt_quantizeHalf(v.z);
124125

125126
Since quantized vertex attributes often need to remain in their compact representations for efficient transfer and storage, they are usually dequantized during vertex processing by configuring the GPU vertex input correctly to expect normalized integers or half precision floats, which often needs no or minimal changes to the shader code. When CPU dequantization is required instead, `meshopt_dequantizeHalf` can be used to convert half precision values back to single precision; for normalized integer formats, the dequantization just requires dividing by 2^N-1 for unorm and 2^(N-1)-1 for snorm variants, for example manually reversing `meshopt_quantizeUnorm(v, 10)` can be done by dividing by 1023.
126127

128+
## Shadow indexing
129+
130+
Many rendering pipelines require meshes to be rendered to depth-only targets, such as shadow maps or during a depth pre-pass, in addition to color/G-buffer targets. While using the same geometry data for both cases is possible, reducing the number of unique vertices for depth-only rendering can be beneficial, especially when the source geometry has many attribute seams due to faceted shading or lightmap texture seams.
131+
To achieve this, this library provides the `meshopt_generateShadowIndexBuffer` algorithm, which generates a second (shadow) index buffer that can be used with the original vertex data:
132+
133+
134+
135+
This is possible to achieve using `meshopt_generateShadowIndexBuffer` algorithm, which will generate a second (shadow) index buffer that can be used with the original vertex data. Because the vertex data is shared, this should be done after other optimizations of the vertex/index data, but it is possible (and recommended) to optimize the resulting index buffer for vertex cache at the end:
136+
137+
```c++
138+
std::vector<unsigned int> shadow_indices(index_count);
139+
// note: this assumes Vertex starts with float3 positions and should be adjusted accordingly for quantized positions
140+
meshopt_generateShadowIndexBuffer(&shadow_indices[0], indices, index_count, &vertices[0].x, vertex_count, sizeof(float) * 3, sizeof(Vertex));
141+
```
142+
143+
Because the vertex data is shared, shadow indexing should be done after other optimizations of the vertex/index data. However, it's possible (and recommended) to optimize the resulting shadow index buffer for vertex cache:
144+
145+
```c++
146+
meshopt_optimizeVertexCache(&shadow_indices[0], &shadow_indices[0], index_count, vertex_count);
147+
```
148+
149+
In some cases, it may be beneficial to split the vertex positions into a separate buffer to maximize efficiency for depth-only rendering. Note that the example above assumes only positions are relevant for shadow rendering, but more complex materials may require adding texture coordinates (for alpha testing) or skinning data to the vertex portion used as a key. `meshopt_generateShadowIndexBufferMulti` can be useful for these cases if the relevant data is not contiguous.
150+
127151
## Vertex/index buffer compression
128152

129153
In case storage size or transmission bandwidth is of importance, you might want to additionally compress vertex and index data. While several mesh compression libraries, like Google Draco, are available, they typically are designed to maximize the compression ratio at the cost of disturbing the vertex/index order (which makes the meshes inefficient to render on GPU) or decompression performance. They also frequently don't support custom game-ready quantized vertex formats and thus require to re-quantize the data after loading it, introducing extra quantization errors and making decoding slower.
@@ -233,7 +257,7 @@ std::vector<unsigned int> remap(index_count);
233257
size_t vertex_count = meshopt_generateVertexRemapMulti(&remap[0], NULL, index_count, index_count, streams, sizeof(streams) / sizeof(streams[0]));
234258
```
235259
236-
After this `meshopt_remapVertexBuffer` needs to be called once for each vertex stream to produce the correctly reindexed stream.
260+
After this `meshopt_remapVertexBuffer` needs to be called once for each vertex stream to produce the correctly reindexed stream. For shadow indexing, similarly `meshopt_generateShadowIndexBufferMulti` is available as a replacement.
237261
238262
Instead of calling `meshopt_optimizeVertexFetch` for reordering vertices in a single vertex buffer for efficiency, calling `meshopt_optimizeVertexFetchRemap` and then calling `meshopt_remapVertexBuffer` for each stream again is recommended.
239263

0 commit comments

Comments
 (0)