C++Directx11開發筆記三:繪製圖形

來源:互聯網
上載者:User

在前面我們講過了如何初始化D3D11Device裝置初始化等等,這裡所講的繪製圖形將在上一篇文章的項目裡進行擴充,在螢幕中繪製圖形。在3D的呈現中最小的單位為三角形,無論我們看到的是多麼大或多麼小的,都是有一個或很多個三角形通過各種方向,角度構成的,當然這會涉及到很多數學中的幾何學問題,最悲劇的就是我在大學裡卻沒學好代數以及幾何學,有學也忘記了。不過Directx SDK中以及為我們解決了很多幾何上的問題,通過他們的方法就可以得到結果,說了這麼多目的就是我告訴大家,要掌握高階運用,必然要學會基礎知識,所以我們這裡就來學習一下如何在螢幕上繪製一個三角形,並塗上顏色。

 

一個三角形由三個點組成,也可以說座標。在座標系裡,三個不同的點就可以組成一個唯一的三角形,當然也就是唯一的面,我想3D圖形是由很多個面組成的,這也就是最小單位為三角形的原因。為了能夠讓GPU(就是顯卡中的CPU,簡單的認為一下,(*^__^*) )呈現三角形,我們必須告訴他三個點的座標,那樣他才能夠在螢幕中顯示出來。例如:在2D中,我們要在螢幕中畫出如下的圖示的三角形,就必須告訴GPU他們三個頂點(0,0),(0,1),(1,0)的座標,那樣GPU才能夠畫出他們。

我們已經知道要把頂點告訴GPU,但是如何告訴他們呢?在Direct3D 11中,頂點資訊如三角形三個頂點的座標是儲存在一個緩衝資源中的,叫做頂點緩衝(Vertex Buffer)。我們必須建立一個足夠大的頂點緩衝,讓他能夠承載三角形的三個頂點座標資訊。

 

 INPUT LAYOUT

一個頂點不只包含一個座標,還可能包含一個或多個顏色值,紋理座標等等,而Input Layout就是定義這些資訊如何在記憶體中儲存:不同資料類型將會有不同的大小, 當然不同的大小也決定著不同的儲存順序。和C語言很像,一個頂點一般使用一個結構來定義。在這裡,我們只需要定義一個三角形頂點的座標,所以我們只要使用XMFLOAT3來定義一個座標,具體代碼如下:


// 3D Vector; 32 bit floating point components
typedef struct _XMFLOAT3
{
    FLOAT x;
    FLOAT y;
    FLOAT z;

#ifdef __cplusplus

    _XMFLOAT3() {};
    _XMFLOAT3(FLOAT _x, FLOAT _y, FLOAT _z) : x(_x), y(_y), z(_z) {};
    _XMFLOAT3(CONST FLOAT *pArray);

    _XMFLOAT3& operator= (CONST _XMFLOAT3& Float3);

#endif // __cplusplus

} XMFLOAT3;

// 以上是XMFLOAT3的結構資訊,在3D中座標的結構

struct SimpleVertex
{
    XMFLOAT3 Pos;  // Position
};


 

 我們定義了一個SimpleVertex結構,就是為了儲存三角形的頂點座標,為了能夠讓GPU瞭解並且能夠在記憶體中獲得相關資訊,我們就必須使用到Input Layout。在Direct 3D 11中,一個Input Layout被定義成能夠讓GPU識別的結構資訊,每一個頂點屬性可以使用一個叫D3D11_INPUT_ELEMENT_DESC結構來進行描述。不同的頂點資訊可以通過定義一個數組來解決這個問題,那樣每一個頂點都能夠進行描述,下面讓我們來瞭解一下這個結構的具體屬性。

typedef struct D3D11_INPUT_ELEMENT_DESC    {
    LPCSTR SemanticName;
    UINT SemanticIndex;
    DXGI_FORMAT Format;
    UINT InputSlot;
    UINT AlignedByteOffset;
    D3D11_INPUT_CLASSIFICATION InputSlotClass;
    UINT InstanceDataStepRate;
    }     D3D11_INPUT_ELEMENT_DESC;

 屬性說明:

  •  

    SemanticName:用來描述目的或名稱的字元,只要任何符合C語言結構的字串都可以使用,並且忽略大小寫,比如用於描述頂點座標可以使用“POSITION”字串。

  • SemanticIndex:這個用來描述索引,當SemanticName相同的情況下就可以使用索引來描述到底哪個才是當前需要的。因為一個頂點可能包含多個顏色,或紋理座標等等,例如多個顏色可以使用如COLOR0,COLOR1來描述,也可以都是用COLOR來描述,使用0和1來填充SemanticIndex。
  • Format:描述這個資料的資料類型,如:DXGI_FORMAT_R32G32B32_FLOAT描述3個32位的float資料類型,即12位元組長度;而DXGI_FORMAT_R16G16B16A16_UINT表示4個16位的uint資料類型,即8位元組長度。
  • InputSlot:輸入槽,在前面提到過的,每一個頂點資訊都通過一個Vertex Buffer輸入讓GPU識別,在Direct 3D 11中多個頂點資訊可以同時的輸入,最多可以有16個,這樣就需要讓GPU知道當前將使用哪個Vertex Buffer資訊,也就是這個值將在0到15之間了。 
  • AlignedByteOffset:記憶體位移量,告訴GPU當前緩衝記憶體起始位移量。
  • InputSlotClass:這個一般使用D3D11_INPUT_PER_VERTEX_DATA來填充,當使用執行個體資料類型時,將使用D3D11_INPUT_PER_INSTANCE_DATA,這個是比較進階的或許在我們以後的學習當中會遇到,這裡我們不大清楚,就先放過。 
  • InstanceDataStepRate:這個用於D3D11_INPUT_PER_INSTANCE_DATA時候,如果不是則必須將其設定為0。

 瞭解了上面的資訊,我們就可以定義我們自己的

D3D11_INPUT_ELEMENT_DESC了,具體代碼如下所示:

1     // Define the input layout
2     D3D11_INPUT_ELEMENT_DESC layout[] =
3     {
4         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
5     };
6     UINT numElements = ARRAYSIZE( layout );


 

 Vertex Layout

 頂點布局主要就是為了給頂點著色器(Vertex Shader)提供計算的【註:也許這個描述不正確】,為了建立一個頂點布局就需要頂點著色器輸入簽名,我們使用ID3DBlob介面對象來描述,而ID3DBlob介面通過D3DX11CompileFromFile來檢索頂點著色器包含簽名的位元據。只要我們有了這個資料,就可以通過ID3D11Device::CreateInputLayout()方法來建立我們的Vertex Layout對象,和使用ID3D11DeviceContext::IASetInputLayout()方法來啟用它,具體代碼如下:

2 if( FAILED( g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(), 
3         pVSBlob->GetBufferSize(), &g_pVertexLayout ) ) )
4     return FALSE;
5 // Set the input layout
6 g_pImmediateContext->IASetInputLayout( g_pVertexLayout );

 

 建立Vertex Buffer

 知道了上面的內容我們還需要做一件事,在初始化時我們必須建立一個Vertex Buffer並且承載了這個頂點的資料資訊。為了建立Vertex Buffer,必須填充兩個結構D3D11_BUFFER_DESC和D3D11_SUBRESOURCE_DATA,然後使用ID3D11Device::CreateBuffer()方法進行建立。D3D11_BUFFER_DESC結構對Vertex Buffer要建立的內容對象進行描述,而

D3D11_SUBRESOURCE_DATA則是包含了具體的資料資訊,這些資料資訊在建立時會進行拷貝。建立緩衝和初始化是在同一時間完成的,在建立後我們可以使用ID3D11DeviceContext::IASetVertexBuffers()方法將其綁定到裝置中,那樣我們就可以在螢幕上呈現出來了,具體代碼如下:SimpleVertex vertices[] =
{
    XMFLOAT3( 0.0f, 0.5f, 0.5f ),
    XMFLOAT3( 0.5f, -0.5f, 0.5f ),
    XMFLOAT3( -0.5f, -0.5f, 0.5f ),
};
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof( SimpleVertex ) * 3;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA InitData; 
ZeroMemory( &InitData, sizeof(InitData) );
InitData.pSysMem = vertices;
if( FAILED( g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ) ) )
    return FALSE;

// Set vertex buffer
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );

 

Primitive Topology (原型拓撲結構)

 從上面我們可以得知,如果要呈現一個三角形那樣就需要將三個頂點資訊告知GPU,那樣如果兩個三角形就必須告訴GPU6個頂點的資訊,如果一個四邊形(兩個三角形組成),也就是說有兩個頂點是共有的,PrimitiveTopology就是為瞭解決這個問題的。在四邊形中,只要傳入是個頂點資訊,就可以畫出四邊形了,,就可以很好的理解了。

 

 如,如果要呈現3a中的圖,只要告訴GPU是個頂點,GPU就會直接畫出這個四邊形了,當然也要注意一下順序:A B C D,其實在Vertex Buffer中描述的是A B C和B C D,這樣 B C兩點是共用的,當然在3b圖形中也一樣。我們只要設定如下代碼就可以得到,如下所示:

g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

 

接下來就是畫出三角形,以上這些都是在裝置初始化後進行的。而畫出三角形就需要用到頂點和像素著色器,具體代碼如下:

void Render()
{
    // Clear the back buffer 
    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red,green,blue,alpha
    g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );

    // Render a triangle
    g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
    g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
    g_pImmediateContext->Draw( 3, 0 );

    // Present the information rendered to the back buffer to the front buffer (the screen)
    g_pSwapChain->Present( 0, 0 );
}

 最終顯示結果如下:

 

寫到了這裡差點瀏覽器掛掉,OK今天就到這裡,發現這個部落格園的代碼編輯器在Google瀏覽器裡還不是很好用,第一行代碼老是要跑到外面出去。 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.