Once everything has been created and loaded, we can look at drawing the vertices to the screen using the specified shader. There are a couple of steps before which we can call the
Draw()
method; however, these are all simple method calls to indicate we will use each resource.
Note
A quick note on topology
Topology defines how Direct3D will read and interpret the provided indices or vertices to lay out the mesh. When drawing the mesh, it can be optimized to reduce the number of required vertices and indices by reusing the last two indices when drawing. This is referred to as a triangle strip. Consuming and using the vertices and indices as originally described would involve a triangle list, which is the simplest and often most compatible topology that can be used for drawing triangles, as a strip requires extra processing to ensure the order is correct without breaking the model.
Other options such as lines and points also exist, and these notify Direct3D that you don't want shaded triangles to be drawn. Instead, the vertices should be drawn as points, or lines between vertices, allowing for different techniques to be used. This would be a good option if you were looking to draw a wireframe, as you can construct the data using two vertices (or indices) for each line and draw them without having to worry about how to draw lines using rectangles and triangles.
This is a list of commonly used primitive topologies, as defined in the D3D_PRIMITIVE_TOPOLOGY
enumeration:
D3D11_PRIMITIVE_TOPOLOGY_POINTLIST
D3D11_PRIMITIVE_TOPOLOGY_LINELIST
D3D11_PRIMITIVE_TOPOL
OGY_TRIANGLELIST
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
You generally want to follow the given order for drawing a model:
Set the vertex buffer.
Set the index buffer.
Set the primitive topology.
Set the input layout.
Set the vertex shader.
Set the pixel shader.
Set the constant buffer(s).
Draw the model.
We've covered how to set buffers, so ensure that they're set at the appropriate times during the drawing phase. Instead we'll focus on setting the rest of the content.
To set the primitive topology, we need to call the following method:
m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
You'll note that again all of these methods define the pipeline stage using two letters at the start of the method. In this case we're still working with the input assembler; however, after this you'll notice that we have moved onto the vertex shader and pixel shader.
Now we need to set the layout using the simple
IASetInputLayout()
method, which just takes a pointer to the input layout as a parameter.
After this, the shaders need to be set. To set the vertex shader, you have to call the following line:
m_d3dContext->VSSetShader( vertexShader, nullptr, 0 );
Here the only parameter that you need to worry about is the first one, which specifies the D3D11VertexShader
object. The other two lines refer to Shader Model 5 classes, which is far outside the scope of this appendix.
To set a pixel shader you can use pretty much the same method, with the only difference being that you call the PSSetShader()
method instead of the
VSSetShader()
.
Now we just need to set the constant buffer on the vertex shader so that it has the camera data required to perform the transform. To do this, you have to make the following call:
m_d3dContext->VSSetConstantBuffers( 0, 1, &pConstantBuffer );
Here you will specify the slot the constant buffer will be placed in, and the number of buffers within the array. Like the
IASetVertexBuffers
, you can set multiple buffers at once. Finally, you need to point to the array of buffer pointers. In this case we only have one element in the array so we just pass the pointer to the pConstantBuffer
.
Finally we have everything in place, and we can execute the command to draw this model to the screen. There are a couple of different draw calls depending on whether you're using an index buffer, or performing instancing. If you want to draw without an index buffer, it's a simple call to the following:
m_d3dContext->Draw( vertCount, startingVertex );
This is pretty simple; you have to specify the total number of vertices, and the index of the first vertex to start drawing from, usually zero.
If you are using an index buffer, you can use the following method:
m_d3dContext->DrawIndexed( indexCount, startingIndex, baseVertex );
This is pretty similar to the last one; however, here you can also define which vertex in your buffer represents index 0. Sometimes, you may want to use this when you have multiple meshes within a single vertex buffer and you have index buffers for each mesh rather than the entire buffer. You can rebase the vertex buffer so that you're referring to the correct vertices.