Tutorial+2+-+Rendering+a+Triangle

//by Richard Russell, August 2015//


 * Note that the code in this tutorial requires Windows 8.1 or Windows 10**

This tutorial is closely based on Microsoft's Direct 3D 11 [|Tutorial 2] but with the code translated from C++ to //BBC BASIC for Windows//. You should refer to the original for a detailed explanation of the code.



Summary
In the previous tutorial, we built a minimal Direct3D 11 application that outputs a single colour to the window. In this tutorial, we will extend the application to render a single triangle on the screen. We will go through the process to set up the data structures associated with a triangle.

The outcome of this tutorial is a window with a triangle rendered to the centre of the window.

Source
The source files, libraries etc. may be downloaded from [|here].

Input Layout
The GPU must know about the vertex layout in order to extract correct attributes from the buffer. To accomplish this requires the use of an input layout:

code format="bb4w" REM Define the input layout: DIM layout{(0)} = D3D11_INPUT_ELEMENT_DESC{} sn0$ = "POSITION" + CHR$(0) layout{(0)}.SemanticName% = !^sn0$ layout{(0)}.Format% = DXGI_FORMAT_R32G32B32_FLOAT layout{(0)}.AlignedByteOffset% = 0 layout{(0)}.InputSlotClass% = D3D11_INPUT_PER_VERTEX_DATA numElements% = DIM(layout{},1) + 1

REM Create the input layout: SYS ID3D11Device.CreateInputLayout%, pd3dDevice%, layout{(0)}, numElements%, bp%, bs%, \ \  ^pVertexLayout% TO hr% SYS ID3D10Blob.Release%, pVSBlob% IF hr% <> 0 OR pVertexLayout% = 0 ERROR 100, "ID3D11Device::CreateInputLayout failed: "+STR$~hr%

REM Set the input layout: SYS ID3D11DeviceContext.IASetInputLayout%, pImmediateContext%, pVertexLayout% code

Vertex Layout
In this tutorial, we are only working with the position of the vertices. Therefore, we define our vertex structure with a single field of the type XMFLOAT3. This type is a vector of three floating-points components, which is typically the data type used for position in 3D:

code format="bb4w" DIM SimpleVertex{} = XMFLOAT3{} code

Creating Vertex Buffer
One thing that we will need to do during initialization is to create the vertex buffer that holds the vertex data. The coordinates in the vertices array are chosen so that we see a triangle in the middle of our application window when rendered with our shaders:

code format="bb4w" REM Create vertex buffer: DIM vertices{(2)} = SimpleVertex{} vertices{(0)}.x% = 0 vertices{(0)}.y% = FN_f4(0.5) vertices{(0)}.z% = FN_f4(0.5)

vertices{(1)}.x% = FN_f4(0.5) vertices{(1)}.y% = FN_f4(-0.5) vertices{(1)}.z% = FN_f4(0.5)

vertices{(2)}.x% = FN_f4(-0.5) vertices{(2)}.y% = FN_f4(-0.5) vertices{(2)}.z% = FN_f4(0.5)

DIM bd{} = D3D11_BUFFER_DESC{} bd.Usage% = D3D11_USAGE_DEFAULT bd.ByteWidth% = DIM(SimpleVertex{}) * (DIM(vertices{},1)+1) bd.BindFlags% = D3D11_BIND_VERTEX_BUFFER bd.CPUAccessFlags% = 0

DIM InitData{} = D3D11_SUBRESOURCE_DATA{} InitData.pSysMem% = vertices{(0)} SYS ID3D11Device.CreateBuffer%, pd3dDevice%, bd{}, InitData{}, ^pVertexBuffer% TO hr% IF hr% <> 0 OR pVertexBuffer% = 0 ERROR 100, "ID3D11Device::CreateBuffer failed: "+STR$~hr%

REM Set vertex buffer: stride% = DIM(SimpleVertex{}) offset% = 0 SYS ID3D11DeviceContext.IASetVertexBuffers%, pImmediateContext%, 0, 1, \ \                                  ^pVertexBuffer%, ^stride%, ^offset% code

Primitive Topology
Primitive topology refers to how the GPU obtains the three vertices it requires to render a triangle. What if we want to render two triangles? One way is to send 6 vertices to the GPU. The first three vertices define the first triangle and the second three vertices define the second triangle. This topology is called a triangle list:

code format="bb4w" REM Set primitive topology: SYS ID3D11DeviceContext.IASetPrimitiveTopology%, pImmediateContext%, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST code

Rendering the Triangle
The final item missing is the code that does the actual rendering of the triangle. We have created two shaders to for rendering, the vertex shader and pixel shader. The vertex shader is responsible for transforming the individual vertices of the triangles to their correct locations and the pixel shader is responsible for calculating the final output colour for each pixel of the triangle. This is covered in more detail in the next tutorial:

code format="bb4w" REM Render a triangle: SYS ID3D11DeviceContext.VSSetShader%, pImmediateContext%, pVertexShader%, NULL, 0 SYS ID3D11DeviceContext.PSSetShader%, pImmediateContext%, pPixelShader%, NULL, 0 SYS ID3D11DeviceContext.Draw%, pImmediateContext%, 3, 0 code