> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Meshlets

> Meshlets

Um *meshlet* é simplesmente um subconjunto de uma malha: um número fixo de primitivos e vértices. Uma *malha* pode ser completamente definida por um conjunto de meshlets, e cada um consiste em um conjunto exclusivo de primitivos da malha. Chamaremos uma malha que foi convertida em uma estrutura de meshlets de *meshletizada*.

O número fixo de primitivos e vértices usado para construir a malha meshletizada é consistente em toda a lista de meshlets e define o tamanho máximo de cada meshlet. Idealmente, cada meshlet fica o mais próximo possível desse tamanho, mas não necessariamente o preenche. O index buffer tradicional é substituído por três novas estruturas de dados: uma lista de meshlets, uma lista de índices de vértices exclusivos e uma lista de primitivos.

**Figura 1.  Renderização de uma malha meshletizada colorida por meshlet (um dragão). Observe que os meshlets consistem em primitivos com coerência espacial razoável.**

<img src="https://mintcdn.com/microsoft-4404708b/6hkHc7s12mHcTMCE/images/gdk/features/graphics/ms_dragon_meshlets.png?fit=max&auto=format&n=6hkHc7s12mHcTMCE&q=85&s=dc30dfff622025378255edbf728ba775" alt="Dragão" width="519" height="500" data-path="images/gdk/features/graphics/ms_dragon_meshlets.png" />

O exemplo de código a seguir é uma implementação em C++ de uma estrutura de meshlet em runtime. Esses dados descrevem completamente uma malha renderizável.

```
struct Meshlet
{
    // Meshlet data.
    uint VertexOffset;
    uint VertexCount;
    uint PrimitiveOffset;
    uint PrimitiveCount;

    // Culling data.
    ...
};

std::vector<MyVertex> Vertices;
std::vector<Meshlet>  Meshlets;
std::vector<uint16_t> UniqueVertexIndices;
std::vector<uint8_t>  PrimitiveIndices;
```

Essa estrutura de meshlets tem várias vantagens para a renderização com Mesh Shader. Cada meshlet tem um tamanho máximo fixo, o que é ideal para mapear um grupo de threads de tamanho fixo para um único meshlet e fornece um mapeamento intuitivo de thread para vértice/primitivo. As contagens de vértices e primitivos são conhecidas antecipadamente, o que elimina a necessidade de calculá-las no código do shader. Os índices de vértices já estão sem duplicatas, o que elimina transformações e exportações redundantes de vértices. Os índices de primitivos são localizados na lista de vértices do meshlet. Os meshlets também fornecem uma granularidade adicional para culling com informações espaciais e de orientação.

O exemplo de código anterior mostra a inter-relação entre os novos buffers de meshlets. A lista de meshlets é uma lista simples da estrutura "meshlet" de runtime, que é, no mínimo, um deslocamento e uma contagem nas listas de índices de vértices exclusivos e de primitivos. A lista de índices de vértices exclusivos é uma lista sem duplicatas de índices no buffer de dados de vértices. A lista de primitivos define os primitivos da malha e consiste em índices na lista de índices de vértices exclusivos, localizados no deslocamento de vértices do meshlet.

**Figura 2.  Diagrama que mostra a relação entre os buffers de meshlets.**

<img src="https://mintcdn.com/microsoft-4404708b/6hkHc7s12mHcTMCE/images/gdk/features/graphics/ms_meshlet_data.png?fit=max&auto=format&n=6hkHc7s12mHcTMCE&q=85&s=e8e9587e2ed7cde69d6bb91adb78971f" alt="Diagrama que mostra a relação entre os buffers de meshlets" width="1000" height="283" data-path="images/gdk/features/graphics/ms_meshlet_data.png" />

## Conversão em meshlets

Meshletizar uma malha com index buffer tradicional não exige nenhuma alteração no fluxo de trabalho dos artistas: é uma etapa procedural de pós-processamento após a criação do modelo. O index buffer tradicional também pode ser regenerado rapidamente em runtime, eliminando a necessidade de distribuir tanto index buffers tradicionais quanto buffers de meshlets. A meshletização pode ser computacionalmente complexa, por isso recomendamos que você a pré-processe offline.

Um projeto de exemplo de conversor de meshlets, composto por uma biblioteca C++ e uma ferramenta de linha de comando, é fornecido pelo ATG para realizar essa conversão, junto com nossos outros exemplos, na [página de downloads para desenvolvedores do XBOX](https://aka.ms/xgddl). Essa ferramenta não modifica os dados de vértices em si, por isso recomendamos que você execute um otimizador de cache de vértices, como o algoritmo de Forsyth, nos dados da malha antes de meshletizá-la. Os otimizadores tendem a criar malhas mais coerentes espacialmente do que se pode esperar universalmente das ferramentas de criação de conteúdo. Heurísticas adicionais podem ser acrescentadas para equilibrar a reutilização de vértices com propriedades benéficas de culling da estrutura de malha resultante.

## Renderização com meshlets

A estrutura do meshlet torna a renderização muito fácil com Mesh Shaders. Declare o tamanho do grupo de threads como o tamanho máximo do meshlet e despache um grupo de threads para cada meshlet da malha. Cada thread é responsável por processar e exportar um vértice e um primitivo.

A seguir, é mostrado um exemplo simples de código de Mesh Shader que renderiza uma malha meshletizada. Primeiro, o meshlet do grupo de threads é carregado e as contagens de saída podem ser declaradas imediatamente. Por fim, PrimitiveCount threads são responsáveis por carregar e gravar os dados de índices de primitivos, e VertexCount threads carregam o índice de vértice usado para acessar os dados de vértices, fazem o sombreamento e os gravam na matriz de saída.

O exemplo completo pode ser encontrado na [página de downloads para desenvolvedores do XBOX](https://aka.ms/xgddl).

O exemplo de código a seguir é uma implementação de exemplo de um meshlet sendo renderizado por um Mesh Shader.

```
#define MAX_MESHLET_SIZE 128

StructureBuffer<MyVertex>   Vertices;
StructureBuffer<Meshlet>    Meshlets;
StructuredBuffer<uint>      UniqueVertexIndices;
StructureBuffer<uint3>      PrimitiveIndices;

VertexOut TransformVertex(MyVertex v) { ... }

[NumThreads(MAX_MESHLET_SIZE, 1, 1)]
[OutputTopology("triangle")]
void main(
    uint groupThreadId : SV_GroupIndex,
    uint groupId : SV_GroupID,
    out vertices VertexOut verts[MAX_MESHLET_SIZE],
    out indices uint3 tris[MAX_MESHLET_SIZE])
{
    Meshlet m = Meshlets[groupId];

    SetMeshOutputCounts(m.VertCount, m.PrimCount);

    if (groupThreadId < m.PrimCount) 
    {
        tris[groupThreadId] = PrimitiveIndices[m.PrimOffset + groupThreadId];
    }

    if (groupThreadId < m.VertCount) 
    {
        uint index = UniqueVertexIndices[m.VertOffset + groupThreadId];
        MyVertex vin = Vertices[index];

        verts[groupThreadId] = TransformVertex(vin);
    }
}
```

## Confira também

[Visão geral do pipeline de Mesh Shader](/pt-BR/build/core-features/graphics/newfeatures/ms/ms-overview)

[Visão geral da API de Mesh Shader](/pt-BR/build/core-features/graphics/newfeatures/ms/ms-api-design)

[Uso de Mesh Shader](/pt-BR/build/core-features/graphics/newfeatures/ms/ms-usage)

[Culling de meshlets](/pt-BR/build/core-features/graphics/newfeatures/ms/ms-meshlet-culling)


## Related topics

- [Exemplo de culling de meshlets](/pt-BR/build/core-features/graphics/newfeatures/ms/ms-meshlet-culling.md)
- [Mesh shaders e meshlets no XBOX Series X|S](/pt-BR/build/core-features/graphics/newfeatures/ms/index.md)
- [Por que usar Mesh Shaders?](/pt-BR/build/core-features/graphics/newfeatures/ms/ms-why.md)
- [Índice de tópicos sob NDA para desenvolvimento de console com o XBOX GDK](/pt-BR/nda/nda-overview.md)
