Rendu de Géométrie avec DirectX 12

Types de Primitives et Organisation des Données

Formes Géométriques Fnodamentales

Les géométries dans DirectX 12 sont définies par des sommets et des indices. Les sommmets contiennent des atrtibuts comme la position ou la couleur, tandis que les indices spécifient leur connectivité. Les types de primitives disponibles incluent :

Valeur Type Description
1 D3D_PRIMITIVE_TOPOLOGY_POINTLIST Liste de points
2 D3D_PRIMITIVE_TOPOLOGY_LINELIST Liste de lignes
3 D3D_PRIMITIVE_TOPOLOGY_LINESTRIP Ruban de lignes
4 D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST Liste de triangles
5 D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP Ruban de triangles
10 D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ Liste de lignes avec adjacence

Les types suffixés par _ADJ ignorent les sommets d'indice impair lors du rendu.

Structure des Sommets

struct SommetPositionLocaleCouleur
{
    float3 PositionLocale : POSITION;
    float4 Couleur : COLOR;
};
struct SommetPositionLocaleCouleur
{
    DirectX::XMFLOAT3 Position;
    DirectX::XMFLOAT4 Couleur;
};

Configuration des Entrées de Sommets

struct DescripteurElementEntree
{
    LPCSTR NomSemantique;
    UINT IndexSemantique;
    DXGI_FORMAT Format;
    UINT Emplacement;
    UINT DecalageOctets;
    D3D12_INPUT_CLASSIFICATION ClasseEntree;
    UINT TauxAvanceInstance;
};

Exemple d'initialisation :

static constexpr std::array<D3D12_INPUT_ELEMENT_DESC, 2> Layout = {
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
      D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
    { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12,
      D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};

Gestion des Ressources GPU

Initialisation des Tampons

ComPtr<ID3D12Resource> CreerTamponUpload(ID3D12Device* peripherique, UINT taille)
{
    ComPtr<ID3D12Resource> ressource;
    auto proprietesTas = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
    auto desc = CD3DX12_RESOURCE_DESC::Buffer(taille);
    
    peripherique->CreateCommittedResource(
        &proprietesTas,
        D3D12_HEAP_FLAG_NONE,
        &desc,
        D3D12_RESOURCE_STATE_GENERIC_READ,
        nullptr,
        IID_PPV_ARGS(&ressource));
    
    return ressource;
}

Transfert de Données

void CopierVersTampon(ID3D12Resource* destination, ID3D12Resource* source, const void* donnees, UINT taille)
{
    D3D12_SUBRESOURCE_DATA donneesSubressource = {};
    donneesSubressource.pData = donnees;
    donneesSubressource.RowPitch = taille;
    
    UpdateSubresources(<listeCommandes>, destination, source, 0, 0, 1, &donneesSubressource);
}

Exemple de Cube

std::vector<SommetPositionLocaleCouleur> sommetsCube = {
    {{-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}},
    {{-1.0f, +1.0f, -1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}},
    // ... autres sommets
};

std::vector<uint16_t> indicesCube = {
    0, 1, 2, 0, 2, 3, // Face avant
    4, 6, 5, 4, 7, 6, // Face arrière
    // ... autres faces
};

Programmation des Shaders

Shader de Vertex

struct SommetEntree
{
    float3 PositionLocale : POSITION;
    float4 Couleur : COLOR;
};

struct SommetSortie
{
    float4 PositionHomogene : SV_Position;
    float4 Couleur : COLOR;
};

SommetSortie VS(SommetEntree entree)
{
    SommetSortie sortie;
    sortie.PositionHomogene = mul(float4(entree.PositionLocale, 1.0f), MatriceMondeVueProj);
    sortie.Couleur = entree.Couleur;
    return sortie;
}

Shader de Pixel

float4 PS(SommetSortie entree) : SV_Target
{
    return entree.Couleur;
}

Compilation des Shaders

ComPtr<ID3DBlob> CompilerShader(const std::wstring& fichier, const std::string& pointEntree)
{
    UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
    #ifdef _DEBUG
    flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
    #endif
    
    ComPtr<ID3DBlob> octetCode, erreurs;
    D3DCompileFromFile(
        fichier.c_str(),
        nullptr,
        D3D_COMPILE_STANDARD_FILE_INCLUDE,
        pointEntree.c_str(),
        "vs_5_0",
        flags,
        0,
        &octetCode,
        &erreurs);
    
    return octetCode;
}

Constantes et Organisation du Rendu

Tampon de Constantes

struct TamponUpload
{
    ComPtr<ID3D12Resource> Ressource;
    void* DonneesMappees = nullptr;
    
    TamponUpload(ID3D12Device* peripherique, UINT tailleElement, UINT compte)
    {
        UINT tailleTampon = Aligner(tailleElement * compte, 256);
        auto proprietesTas = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
        auto desc = CD3DX12_RESOURCE_DESC::Buffer(tailleTampon);
        
        peripherique->CreateCommittedResource(
            &proprietesTas,
            D3D12_HEAP_FLAG_NONE,
            &desc,
            D3D12_RESOURCE_STATE_GENERIC_READ,
            nullptr,
            IID_PPV_ARGS(&Ressource));
        
        Ressource->Map(0, nullptr, &DonneesMappees);
    }
};

Configuration de la Signature Racine

void CreerSignatureRacine(ID3D12Device* peripherique)
{
    CD3DX12_DESCRIPTOR_RANGE plageCBV;
    plageCBV.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
    
    CD3DX12_ROOT_PARAMETER parametres[1];
    parametres[0].InitAsDescriptorTable(1, &plageCBV);
    
    CD3DX12_ROOT_SIGNATURE_DESC descSignature;
    descSignature.Init(1, parametres, 0, nullptr);
    
    ComPtr<ID3DBlob> signatureSerialisee;
    D3D12SerializeRootSignature(&descSignature, D3D_ROOT_SIGNATURE_VERSION_1, 
                                &signatureSerialisee, nullptr);
    
    peripherique->CreateRootSignature(
        0,
        signatureSerialisee->GetBufferPointer(),
        signatureSerialisee->GetBufferSize(),
        IID_PPV_ARGS(&signatureRacine));
}

État du Pipeline Graphique

D3D12_GRAPHICS_PIPELINE_STATE_DESC descPSO = {};
descPSO.pRootSignature = signatureRacine.Get();
descPSO.VS = { octetCodeVS->GetBufferPointer(), octetCodeVS->GetBufferSize() };
descPSO.PS = { octetCodePS->GetBufferPointer(), octetCodePS->GetBufferSize() };
descPSO.InputLayout = { Layout.data(), (UINT)Layout.size() };
// Configuration des états de rasterizer, blend, depth/stencil...

peripherique->CreateGraphicsPipelineState(&descPSO, IID_PPV_ARGS(&pso));

Étiquettes: DirectX12 HLSL Shader CBV PSO

Publié le 9 juillet à 21h50