Partager via


Créer et afficher un maillage de base

Les jeux de plateforme Windows universelle (UWP) 3D utilisent généralement des polygones pour représenter des objets et des surfaces dans le jeu. Les listes de sommets qui composent la structure de ces objets polygonaux et surfaces sont appelées maillages. Ici, nous créons un maillage de base pour un objet cube et le fournissons au pipeline du shader pour le rendu et l'affichage.

Important L’exemple de code inclus ici utilise des types (tels que DirectX ::XMFLOAT3 et DirectX ::XMFLOAT4X4) et des méthodes inline déclarées dans DirectXMath.h. Si vous coupez et collez ce code, #include <DirectXMath.h> dans votre projet.

 

Ce que vous devez savoir

Technologies

  • Direct3D

Conditions préalables

  • Connaissance de base des systèmes de coordonnées linéaires et 3D
  • Un modèle Direct3D Visual Studio 2015 ou version ultérieure

Les instructions

Ces étapes vous montrent comment créer un cube de maillage de base.

Étape 1 : Construire le maillage du modèle

Dans la plupart des jeux, le maillage d’un objet de jeu est chargé à partir d’un fichier qui contient les données de vertex spécifiques. L’ordre de ces sommets dépend de l’application, mais ils sont généralement sérialisés en tant que bandes ou farandoles. Les données de vertex peuvent provenir de n’importe quelle source logicielle, ou elles peuvent être créées manuellement. C’est à votre jeu d’interpréter les données de manière à ce que le nuanceur de vertex puisse le traiter efficacement.

Dans notre exemple, nous utilisons un maillage simple pour un cube. Le cube, comme n’importe quel maillage d’objets à ce stade du pipeline, est représenté à l’aide de son propre système de coordonnées. Le nuanceur de vertex prend ses coordonnées et, en appliquant les matrices de transformation que vous fournissez, retourne la projection finale de vue 2D dans un système de coordonnées homogène.

Définissez le maillage d’un cube. (Ou chargez-le à partir d’un fichier. À vous de décider !)

SimpleCubeVertex cubeVertices[] =
{
    { DirectX::XMFLOAT3(-0.5f, 0.5f, -0.5f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f) }, // +Y (top face)
    { DirectX::XMFLOAT3( 0.5f, 0.5f, -0.5f), DirectX::XMFLOAT3(1.0f, 1.0f, 0.0f) },
    { DirectX::XMFLOAT3( 0.5f, 0.5f,  0.5f), DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f) },
    { DirectX::XMFLOAT3(-0.5f, 0.5f,  0.5f), DirectX::XMFLOAT3(0.0f, 1.0f, 1.0f) },

    { DirectX::XMFLOAT3(-0.5f, -0.5f,  0.5f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f) }, // -Y (bottom face)
    { DirectX::XMFLOAT3( 0.5f, -0.5f,  0.5f), DirectX::XMFLOAT3(1.0f, 0.0f, 1.0f) },
    { DirectX::XMFLOAT3( 0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f) },
    { DirectX::XMFLOAT3(-0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f) },
};

Le système de coordonnées du cube place le centre du cube à l'origine, avec l'axe y qui s'étend de haut en bas à l'aide d'un système de coordonnées gaucher. Les valeurs de coordonnées sont exprimées sous forme de valeurs flottantes 32 bits entre -1 et 1.

Dans chaque jumelage entre crochets, le deuxième groupe de valeurs DirectX ::XMFLOAT3 spécifie la couleur associée au vertex comme valeur RVB. Par exemple, le premier vertex à (-0.5, 0.5, -0.5) a une couleur verte complète (la valeur G est définie sur 1,0, et les valeurs « R » et « B » sont définies sur 0).

Par conséquent, vous avez 8 sommets, chacun avec une couleur spécifique. Chaque association sommet/couleur constitue les données complètes d’un sommet dans notre exemple. Lorsque vous spécifiez notre mémoire tampon de vertex, vous devez garder cette disposition spécifique à l’esprit. Nous fournissons cette disposition d’entrée au nuanceur de vertex afin qu’elle puisse comprendre vos données de vertex.

Étape 2 : Configurer la mise en page des entrées

Maintenant, vous avez les sommets en mémoire. Toutefois, votre appareil graphique a sa propre mémoire et vous utilisez Direct3D pour y accéder. Pour intégrer vos données de sommets dans le périphérique graphique pour le traitement, vous devez préciser leur structure : vous devez déclarer comment les données de sommets sont organisées afin que le périphérique graphique puisse les interpréter lorsqu'il les reçoit de votre jeu. Pour ce faire, vous utilisez ID3D11InputLayout.

Déclarez et définissez la disposition d’entrée pour la mémoire tampon de vertex.

const D3D11_INPUT_ELEMENT_DESC basicVertexLayoutDesc[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "COLOR",    0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

ComPtr<ID3D11InputLayout> inputLayout;
m_d3dDevice->CreateInputLayout(
                basicVertexLayoutDesc,
                ARRAYSIZE(basicVertexLayoutDesc),
                vertexShaderBytecode->Data,
                vertexShaderBytecode->Length,
                &inputLayout)
);

Dans ce code, vous spécifiez une disposition pour les sommets, en particulier les données que chaque élément de la liste de vertex contient. Ici, dans basicVertexLayoutDesc, vous spécifiez deux composants de données :

  • POSITION: il s’agit d’une sémantique HLSL pour les données de position fournies à un nuanceur. Dans ce code, il s'agit d'une structure DirectX::XMFLOAT3, ou plus précisément, de trois valeurs à virgule flottante 32 bits qui correspondent à une coordonnée 3D (x, y, z). Vous pouvez également utiliser un float4 si vous fournissez la coordonnée homogène « w » et, dans ce cas, vous spécifiez DXGI_FORMAT_R32G32B32A32_FLOAT. Que vous utilisiez DirectX::XMFLOAT3 ou float4 dépend des besoins spécifiques de votre jeu. Assurez-vous simplement que les données de vertex pour votre maillage correspondent correctement au format que vous utilisez !

    Chaque valeur de coordonnée est exprimée sous la forme d’une valeur à virgule flottante entre -1 et 1, dans l’espace de coordonnées de l’objet. Une fois le shader de sommet terminé, le sommet transformé se trouve dans l’espace de projection de vue homogène (perspective corrigée).

    « Mais la valeur d’énumération indique RVB, pas XYZ ! » vous notez intelligemment. Bon œil ! Dans les deux cas de données de couleur et de données de coordonnées, vous utilisez généralement 3 ou 4 valeurs de composant. Pourquoi ne pas utiliser le même format pour les deux ? La sémantique HLSL, et non le nom de format, indique comment le nuanceur traite les données.

  • COLOR: il s’agit d’une sémantique HLSL pour les données de couleur. Comme POSITION , elle se compose de 3 valeurs à virgule flottante 32 bits (DirectX::XMFLOAT3). Chaque valeur contient un composant de couleur : rouge (r), bleu (b) ou vert (g), exprimé sous la forme d’un nombre flottant compris entre 0 et 1.

    Les valeurs de couleur sont généralement retournées sous la forme d'une valeur RGBA à 4 composants à la fin du pipeline du shader. Pour cet exemple, vous définissez la valeur alpha « A » sur 1,0 (opacité maximale) dans le pipeline du nuanceur pour tous les pixels.

Pour obtenir la liste complète des formats, consultez DXGI_FORMAT. Pour obtenir la liste complète de la sémantique HLSL, consultez sémantique.

Appelez ID3D11Device ::CreateInputLayout et créez la disposition d’entrée sur l’appareil Direct3D. Vous devez maintenant créer une mémoire tampon qui peut contenir réellement les données !

Étape 3 : Remplir les mémoires tampons de vertex

Les tampons de sommets contiennent la liste des sommets de chaque triangle dans le maillage. Chaque vertex doit être unique dans cette liste. Dans notre exemple, vous avez 8 sommets pour le cube. Le nuanceur de vertex s’exécute sur l’appareil graphique et lit à partir de la mémoire tampon de vertex, et interprète les données en fonction de la disposition d’entrée que vous avez spécifiée à l’étape précédente.

Dans l’exemple suivant, vous fournissez une description et une sous-ressource pour la mémoire tampon, ce qui indique à Direct3D un certain nombre d’éléments sur le mappage physique des données de vertex et comment le traiter en mémoire sur l’appareil graphique. Cela est nécessaire car vous utilisez un ID3D11Buffer générique, qui peut contenir n'importe quoi ! Les structures D3D11_BUFFER_DESC et D3D11_SUBRESOURCE_DATA sont fournies pour s’assurer que Direct3D comprend la disposition de mémoire physique de la mémoire tampon, y compris la taille de chaque élément de vertex dans la mémoire tampon ainsi que la taille maximale de la liste de vertex. Vous pouvez également contrôler l’accès à la mémoire tampon ici et la façon dont elle est parcourue, mais c’est un peu au-delà de l’étendue de ce didacticiel.

Après avoir configuré la mémoire tampon, vous appelez ID3D11Device ::CreateBuffer pour le créer réellement. Évidemment, si vous avez plusieurs objets, créez des mémoires tampons pour chaque modèle unique.

Déclarez et créez la mémoire tampon de vertex.

D3D11_BUFFER_DESC vertexBufferDesc = {0};
vertexBufferDesc.ByteWidth = sizeof(SimpleCubeVertex) * ARRAYSIZE(cubeVertices);
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;

D3D11_SUBRESOURCE_DATA vertexBufferData;
vertexBufferData.pSysMem = cubeVertices;
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;

ComPtr<ID3D11Buffer> vertexBuffer;
m_d3dDevice->CreateBuffer(
                &vertexBufferDesc,
                &vertexBufferData,
                &vertexBuffer);

Sommets chargés. Mais quel est l’ordre de traitement de ces sommets ? Cela est géré lorsque vous fournissez une liste d’indices aux sommets : l’ordre de ces indices est l’ordre dans lequel le shader de sommet les traite.

Étape 4 : remplir les mémoires tampons d’index

À présent, vous fournissez une liste des index pour chacun des sommets. Ces index correspondent à la position du sommet dans la mémoire tampon de vertex, à compter de 0. Pour vous aider à visualiser cela, considérez que chaque vertex unique dans votre maillage a un nombre unique qui lui est attribué, comme un ID. Cet ID est la position entière du sommet dans la mémoire tampon de sommet.

un cube avec huit sommets numérotés

Dans notre exemple de cube, vous avez 8 sommets, ce qui crée 6 quads pour les côtés. Vous fractionnez les quads en triangles, pour un total de 12 triangles qui utilisent nos 8 sommets. À 3 sommets par triangle, vous avez 36 entrées dans notre mémoire tampon d’index. Dans notre exemple, ce modèle d’index est appelé liste de triangles et vous l’indiquez à Direct3D en tant que D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST lorsque vous définissez la topologie primitive.

Il s’agit probablement de la façon la plus inefficace de répertorier les index, car il existe de nombreuses redondances lorsque les triangles partagent des points et des côtés. Par exemple, lorsqu’un triangle partage un côté avec une forme de losange, vous devez répertorier six indices pour les quatre sommets, comme suit :

'ordre des index lors de la construction d’un rhombus

  • Triangle 1 : [0, 1, 2]
  • Triangle 2 : [0, 2, 3]

Dans une topologie de bande ou de ventilateur, vous organisez les sommets de manière à éliminer de nombreux côtés redondants lors de la traversée (comme le côté allant de l'index 0 à l'index 2 dans l'image). Pour les grands maillages, cela réduit considérablement le nombre de fois que le shader de sommets est lancé et améliore significativement les performances. Toutefois, nous allons garder cela simple et nous contenter de la liste des triangles.

Déclarez les indices du tampon de sommets comme une topologie de liste de triangles simples.

unsigned short cubeIndices[] =
{   0, 1, 2,
    0, 2, 3,

    4, 5, 6,
    4, 6, 7,

    3, 2, 5,
    3, 5, 4,

    2, 1, 6,
    2, 6, 5,

    1, 7, 6,
    1, 0, 7,

    0, 3, 4,
    0, 4, 7 };

Trente six éléments d’index dans la mémoire tampon sont très redondants lorsque vous n’avez que 8 sommets ! Si vous choisissez d’éliminer certaines redondances et d’utiliser un type de liste de vertex différent, tel qu’une bande ou un ventilateur, vous devez spécifier ce type lorsque vous fournissez une valeur D3D11_PRIMITIVE_TOPOLOGY spécifique à la méthode ID3D11DeviceContext ::IASetPrimitiveTopology.

Pour plus d’informations sur les différentes techniques de liste d’index, consultez topologies primitives.

Étape 5 : Créer une mémoire tampon constante pour vos matrices de transformation

Avant de commencer à traiter les sommets, vous devez fournir les matrices de transformation qui seront appliquées (multipliées) à chaque sommet lorsque le programme s'exécute. Pour la plupart des jeux 3D, il y a trois d’entre eux :

  • Matrice 4x4 qui se transforme du système de coordonnées objet (modèle) au système de coordonnées global du monde.
  • La matrice 4x4 qui transforme du système de coordonnées du monde au système de coordonnées de caméra (vue).
  • La matrice 4x4 qui transforme du système de coordonnées de la caméra au système de coordonnées de projection de vue en 2D.

Ces matrices sont transmises au nuanceur dans une mémoire tampon constante . Une mémoire tampon constante est une région de mémoire qui reste constante tout au long de l’exécution du prochain passage du pipeline de nuanceur, et qui peut être directement accessible par les nuanceurs à partir de votre code HLSL. Vous définissez chaque mémoire tampon constante deux fois : tout d’abord dans le code C++ de votre jeu, et (au moins) une fois dans la syntaxe HLSL de type C pour votre code de nuanceur. Les deux déclarations doivent correspondre directement en termes de types et d’alignement des données. Il est facile d’introduire des erreurs difficiles à trouver lorsque le nuanceur utilise la déclaration HLSL pour interpréter les données déclarées en C++, et les types ne correspondent pas ou l’alignement des données est désactivé !

Les mémoires tampons constantes ne sont pas modifiées par hlSL. Vous pouvez les modifier lorsque votre jeu met à jour des données spécifiques. Souvent, les développeurs de jeux créent 4 classes de mémoires tampons constantes : un type pour les mises à jour par image ; un type pour les mises à jour par modèle/objet ; un type pour les mises à jour par actualisation de l’état du jeu ; et un type pour les données qui ne changent jamais dans la durée de vie du jeu.

Dans cet exemple, nous n’avons qu’un seul élément qui ne change jamais : les données DirectX ::XMFLOAT4X4 pour les trois matrices.

Remarque L’exemple de code présenté ici utilise des matrices principales de colonnes. Vous pouvez utiliser des matrices en ordre ligne à la place en utilisant le mot clé row_major dans HLSL, et vous assurer que vos données de matrice source sont également en ordre ligne. DirectXMath utilise des matrices principales de ligne et peut être utilisée directement avec des matrices HLSL définies avec le mot clé row_major.

 

Déclarez et créez une mémoire tampon constante pour les trois matrices que vous utilisez pour transformer chaque sommet.

struct ConstantBuffer
{
    DirectX::XMFLOAT4X4 model;
    DirectX::XMFLOAT4X4 view;
    DirectX::XMFLOAT4X4 projection;
};
ComPtr<ID3D11Buffer> m_constantBuffer;
ConstantBuffer m_constantBufferData;

// ...

// Create a constant buffer for passing model, view, and projection matrices
// to the vertex shader.  This allows us to rotate the cube and apply
// a perspective projection to it.

D3D11_BUFFER_DESC constantBufferDesc = {0};
constantBufferDesc.ByteWidth = sizeof(m_constantBufferData);
constantBufferDesc.Usage = D3D11_USAGE_DEFAULT;
constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantBufferDesc.CPUAccessFlags = 0;
constantBufferDesc.MiscFlags = 0;
constantBufferDesc.StructureByteStride = 0;
m_d3dDevice->CreateBuffer(
                &constantBufferDesc,
                nullptr,
                &m_constantBuffer
             );

m_constantBufferData.model = DirectX::XMFLOAT4X4( // Identity matrix, since you are not animating the object
            1.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f);

);
// Specify the view (camera) transform corresponding to a camera position of
// X = 0, Y = 1, Z = 2.  

m_constantBufferData.view = DirectX::XMFLOAT4X4(
            -1.00000000f, 0.00000000f,  0.00000000f,  0.00000000f,
             0.00000000f, 0.89442718f,  0.44721359f,  0.00000000f,
             0.00000000f, 0.44721359f, -0.89442718f, -2.23606800f,
             0.00000000f, 0.00000000f,  0.00000000f,  1.00000000f);

Remarque Vous déclarez généralement la matrice de projection lorsque vous configurez des ressources spécifiques à l’appareil, car les résultats de la multiplication avec celui-ci doivent correspondre aux paramètres actuels de taille de la fenêtre d’affichage 2D (qui correspondent souvent à la hauteur et à la largeur du pixel de l’affichage). Si ces valeurs changent, vous devez mettre à l’échelle les valeurs de coordonnées x et y en conséquence.

 

// Finally, update the constant buffer perspective projection parameters
// to account for the size of the application window.  In this sample,
// the parameters are fixed to a 70-degree field of view, with a depth
// range of 0.01 to 100.  

float xScale = 1.42814801f;
float yScale = 1.42814801f;
if (backBufferDesc.Width > backBufferDesc.Height)
{
    xScale = yScale *
                static_cast<float>(backBufferDesc.Height) /
                static_cast<float>(backBufferDesc.Width);
}
else
{
    yScale = xScale *
                static_cast<float>(backBufferDesc.Width) /
                static_cast<float>(backBufferDesc.Height);
}
m_constantBufferData.projection = DirectX::XMFLOAT4X4(
            xScale, 0.0f,    0.0f,  0.0f,
            0.0f,   yScale,  0.0f,  0.0f,
            0.0f,   0.0f,   -1.0f, -0.01f,
            0.0f,   0.0f,   -1.0f,  0.0f
            );

Pendant que vous êtes ici, définissez les tampons de vertex et d’index sur laID3D11DeviceContext, ainsi que la topologie que vous utilisez.

// Set the vertex and index buffers, and specify the way they define geometry.
UINT stride = sizeof(SimpleCubeVertex);
UINT offset = 0;
m_d3dDeviceContext->IASetVertexBuffers(
                0,
                1,
                vertexBuffer.GetAddressOf(),
                &stride,
                &offset);

m_d3dDeviceContext->IASetIndexBuffer(
                indexBuffer.Get(),
                DXGI_FORMAT_R16_UINT,
                0);

 m_d3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

D’accord! L'assemblage d'entrée est terminé. Tout est en place pour le rendu. Faisons fonctionner ce nuanceur de sommets.

Étape 6 : Traiter le maillage avec le nuanceur de vertex

Maintenant que vous disposez d’une mémoire tampon de vertex avec les sommets qui définissent votre maillage et la mémoire tampon d’index qui définit l’ordre dans lequel les sommets sont traités, vous les envoyez au nuanceur de vertex. Le code du nuanceur de vertex, exprimé en langage de nuanceur de haut niveau compilé, s’exécute une fois pour chaque vertex dans la mémoire tampon de vertex, ce qui vous permet d’effectuer vos transformations par vertex. Le résultat final est généralement une projection 2D.

(Avez-vous chargé votre nuanceur de vertex ? Si ce n’est pas le cas, passez en revue Comment charger des ressources dans votre jeu DirectX.)

Ici, vous créez le shader de sommet...

// Set the vertex and pixel shader stage state.
m_d3dDeviceContext->VSSetShader(
                vertexShader.Get(),
                nullptr,
                0);

... et définissez les mémoires tampons constantes.

m_d3dDeviceContext->VSSetConstantBuffers(
                0,
                1,
                m_constantBuffer.GetAddressOf());

Voici le code du nuanceur de vertex qui gère la transformation des coordonnées d’objet en coordonnées mondiales, puis vers le système de coordonnées de projection de vue 2D. Vous appliquez également un éclairage simple par vertex pour rendre les choses jolies. Cela se trouve dans le fichier HLSL de votre nuanceur de vertex (SimplifieVertexShader.hlsl, dans cet exemple).

cbuffer simpleConstantBuffer : register( b0 )
{
    matrix model;
    matrix view;
    matrix projection;
};

struct VertexShaderInput
{
    DirectX::XMFLOAT3 pos : POSITION;
    DirectX::XMFLOAT3 color : COLOR;
};

struct PixelShaderInput
{
    float4 pos : SV_POSITION;
    float4 color : COLOR;
};

PixelShaderInput SimpleVertexShader(VertexShaderInput input)
{
    PixelShaderInput vertexShaderOutput;
    float4 pos = float4(input.pos, 1.0f);

    // Transform the vertex position into projection space.
    pos = mul(pos, model);
    pos = mul(pos, view);
    pos = mul(pos, projection);
    vertexShaderOutput.pos = pos;

    // Pass the vertex color through to the pixel shader.
    vertexShaderOutput.color = float4(input.color, 1.0f);

    return vertexShaderOutput;
}

Vous voyez le cbuffer en haut ? Il s’agit de l’analogue HLSL à la même mémoire tampon constante que celle que nous avons déclarée dans notre code C++ précédemment. Et le VertexShaderInputstruct? Eh bien, on dirait que cela ressemble à votre configuration d'entrée et à votre déclaration des données de sommet ! Il est important que la mémoire tampon constante et les déclarations de données de vertex dans votre code C++ correspondent aux déclarations de votre code HLSL, et qui incluent des signes, des types et l’alignement des données.

PixelShaderInput spécifie la disposition des données retournées par la fonction principale du nuanceur de vertex. Lorsque vous terminez le traitement d’un sommet, vous retournerez une position de sommet dans l’espace de projection 2D et une couleur utilisée pour l’éclairage par sommet. La carte graphique utilise la sortie de données par le nuanceur pour calculer les « fragments » (pixels possibles) qui doivent être colorés lorsque le nuanceur de pixels est exécuté à l’étape suivante du pipeline.

Étape 7 : Passage du maillage au nuanceur de pixels

En règle générale, à ce stade du pipeline graphique, vous effectuez des opérations par pixel sur les surfaces projetées visibles de vos objets. (Les gens aiment les textures.) Pour les besoins de l’échantillon, cependant, vous le faites simplement passer à cette étape.

Tout d’abord, créons une instance du nuanceur de pixels. Le nuanceur de pixels s’exécute pour chaque pixel de la projection 2D de votre scène, en affectant une couleur à ce pixel. Dans ce cas, nous passons la couleur du pixel retourné par le nuanceur de vertex directement.

Définissez le nuanceur de pixels.

m_d3dDeviceContext->PSSetShader( pixelShader.Get(), nullptr, 0 );

Définissez un shader de pixels pass-through dans HLSL.

struct PixelShaderInput
{
    float4 pos : SV_POSITION;
};

float4 SimplePixelShader(PixelShaderInput input) : SV_TARGET
{
    // Draw the entire triangle yellow.
    return float4(1.0f, 1.0f, 0.0f, 1.0f);
}

Placez ce code dans un fichier HLSL distinct du nuanceur de vertex HLSL (tel que SimplePixelShader.hlsl). Ce code est exécuté une fois pour chaque pixel visible dans votre fenêtre d'affichage (une représentation en mémoire de la partie de l'écran sur laquelle vous dessinez), qui, dans ce cas, correspond à l'ensemble de l'écran. Maintenant, votre pipeline graphique est entièrement défini !

Étape 8 : Rastérisation et affichage du maillage

Nous allons exécuter le pipeline. C’est facile : appelez ID3D11DeviceContext::DrawIndexed.

Dessinez ce cube !

// Draw the cube.
m_d3dDeviceContext->DrawIndexed( ARRAYSIZE(cubeIndices), 0, 0 );
            

Dans la carte graphique, chaque vertex est traité dans l’ordre spécifié dans votre mémoire tampon d’index. Une fois que votre code a exécuté le nuanceur de vertex et que les fragments 2D sont définis, le nuanceur de pixels est appelé et les triangles colorés.

Maintenant, placez le cube à l’écran.

Présentez cette mémoire tampon d’image à l’écran.

// Present the rendered image to the window.  Because the maximum frame latency is set to 1,
// the render loop is generally  throttled to the screen refresh rate, typically around
// 60 Hz, by sleeping the app on Present until the screen is refreshed.

m_swapChain->Present(1, 0);

Et tu as fini ! Pour une scène remplie de modèles, utilisez plusieurs tampons de vertex et d'index, et vous pouvez même utiliser des shaders différents pour différents types de modèles. N’oubliez pas que chaque modèle possède son propre système de coordonnées et que vous devez les transformer en système de coordonnées du monde partagé à l’aide des matrices que vous avez définies dans la mémoire tampon constante.

Remarques

Cette rubrique traite de la création et de l’affichage d’une géométrie simple que vous créez vous-même. Pour plus d’informations sur le chargement d’une géométrie plus complexe à partir d’un fichier et sa conversion au format d’objet tampon de vertex spécifique à l’exemple (.vbo), consultez Comment charger des ressources dans votre jeu DirectX.