=====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 [[https://msdn.microsoft.com/en-us/library/ff729719.aspx|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.\\ \\ {{Tutorial02.png}}\\ \\
===== 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 [[http://www.rtr.myzen.co.uk/D3D11tutorial.zip|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:
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%
===== 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:
DIM SimpleVertex{} = XMFLOAT3{}
===== 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:
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%
===== 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:
REM Set primitive topology:
SYS ID3D11DeviceContext.IASetPrimitiveTopology%, pImmediateContext%, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
===== 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:
REM Render a triangle:
SYS ID3D11DeviceContext.VSSetShader%, pImmediateContext%, pVertexShader%, NULL, 0
SYS ID3D11DeviceContext.PSSetShader%, pImmediateContext%, pPixelShader%, NULL, 0
SYS ID3D11DeviceContext.Draw%, pImmediateContext%, 3, 0