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));