Directx11學習筆記【十】 畫一個簡單的三角形


本篇筆記要實現的是在屏幕上渲染出一個三角形,重點要學習的是渲染一個幾何體的流程方式。

為了渲染幾何圖形,需要一個頂點緩存和一個描述頂點布局的輸入層,還有着色器(主要是頂點着色器和像素着色器),下面來看看具體Demo的實現。

新建一個Win32項目 ,新建一個類我們叫做TriangleDemo,繼承自前面教程我們實現的基類Dx11DemoBase。

 

TriangleDemo.h頭文件

#pragma once

#include "Dx11DemoBase.h"

class TriangleDemo : public Dx11DemoBase
{
public:
    TriangleDemo();
    ~TriangleDemo();

    bool LoadContent() override;
    void UnLoadContent() override;

    void Update(float dt) override;
    void Render() override;

private:
    ID3D11Buffer *m_pVertexBuffer;
    ID3D11InputLayout *m_pInputLayout;
    ID3D11VertexShader *m_pSolidColorVS;
    ID3D11PixelShader *m_pSolidColorPS;
};

在類中添加了四個成員變量,用來保存着色器、頂點緩存和頂點布局的指針。

定義頂點結構體

#include "TriangleDemo.h"
#include <xnamath.h>

struct VertexPos
{
    XMFLOAT3 pos;
};

TriangleDemo::TriangleDemo() 
: m_pInputLayout(0), m_pVertexBuffer(0), m_pSolidColorPS(0), m_pSolidColorVS(0)
{
}


TriangleDemo::~TriangleDemo()
{
}

void TriangleDemo::UnLoadContent()
{
    if (m_pSolidColorPS)
        m_pSolidColorPS->Release();
    if (m_pSolidColorVS)
        m_pSolidColorVS->Release();
    if (m_pVertexBuffer)
        m_pVertexBuffer->Release();
    if (m_pInputLayout)
        m_pInputLayout->Release();
    m_pSolidColorVS = 0;
    m_pSolidColorPS = 0;
    m_pVertexBuffer = 0;
    m_pInputLayout = 0;
}

着色器的加載

為了方便我們在基類中定義了一個CompileD3DShader函數實現加載着色器文本的功能,具體實現如下

bool Dx11DemoBase::CompileD3DShader(char* filePath, char* entry, char* shaderModel, ID3DBlob** buffer)
{
    DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;

#if defined _DEBUG || defined DEBUG
    shaderFlags = D3DCOMPILE_DEBUG;
#endif

    ID3DBlob *errorBuffer = 0;
    HRESULT result;

    result = D3DX11CompileFromFile(filePath, 0, 0, entry, shaderModel, shaderFlags, 0, 0, buffer, &errorBuffer,0);

    if (FAILED(result))
    {
        if (errorBuffer != 0)
        {
            OutputDebugString((char*)errorBuffer->GetBufferPointer());
            errorBuffer->Release();
        }
        return false;
    }

    if (errorBuffer != 0)
    {
        return false;
    }

    return true;
}

 

具體加載着色器的代碼我們寫在LoadContent函數中,下面是該函數的一部分代碼

 1 //載入頂點着色器
 2     ID3DBlob *vsBuffer = 0;
 3     bool compileResult = CompileD3DShader("SolidColor.fx", "VS_Main", "vs_4_0", &vsBuffer);
 4     if (!compileResult)
 5     {
 6         MessageBox(0, "載入頂點着色器錯誤", "編譯錯誤", MB_OK);
 7         return false;
 8     }
 9 
10     HRESULT result;
11     result = m_pd3dDevice->CreateVertexShader(vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(),
12         0, &m_pSolidColorVS);
13 
14     if (FAILED(result))
15     {
16         if (vsBuffer)
17         {
18             vsBuffer->Release();
19         }
20         return false;
21     }
22 
23     D3D11_INPUT_ELEMENT_DESC solidColorLayout[] = 
24     {
25         {"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0}
26     };
27 
28     UINT numLayoutElements = ARRAYSIZE(solidColorLayout);
29     result = m_pd3dDevice->CreateInputLayout(solidColorLayout, numLayoutElements, vsBuffer->GetBufferPointer(),
30         vsBuffer->GetBufferSize(), &m_pInputLayout);
31     vsBuffer->Release();
32 
33     if (FAILED(result))
34     {
35         return false;
36     }
37 
38     //載入像素着色器
39     ID3DBlob *psBuffer = 0;
40     compileResult = CompileD3DShader("SolidColor.fx", "PS_Main", "ps_4_0", &psBuffer);
41     if (!compileResult)
42     {
43         MessageBox(0, "像素着色器加載失敗", "編譯錯誤", MB_OK);
44         return false;
45     }
46 
47     result = m_pd3dDevice->CreatePixelShader(psBuffer->GetBufferPointer(), psBuffer->GetBufferSize(),
48         0, &m_pSolidColorPS);
49     psBuffer->Release();
50     if (FAILED(result))
51     {
52         return false;
53     }

其中輸入布局信息D3D11_INPUT_ELEMENT_DESC

(A description of a single element for the input-assembler stage.)

定義如下

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;

 

頂點信息生成及處理

TriangleDemo::LoadContent() 的 上半部分完成了 inputlayout 和 shader, 剩下的就是 vertex 這些頂點的生成及處理了。

三角形的頂點列表 vertex list 存放處在 vertices數組里, 同時這個vertices 也作為 創建vertex buffer函數CreateBuffer()的參數之一:Subresource data。

下面是LoadContent()的另外一部分代碼:

 1 VertexPos vertices[]  =
 2     {
 3         XMFLOAT3(0.5f, 0.5f, 0.5f),
 4         XMFLOAT3(0.5f, -0.5f, 0.5f),
 5         XMFLOAT3(-0.5f,-0.5f,0.5f)
 6     };
 7 
 8     D3D11_BUFFER_DESC vertexDesc;
 9     ZeroMemory(&vertexDesc, sizeof(vertexDesc));
10     vertexDesc.Usage = D3D11_USAGE_DEFAULT;
11     vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
12     vertexDesc.ByteWidth = sizeof(VertexPos)* 3;
13     
14     D3D11_SUBRESOURCE_DATA resourceData;
15     ZeroMemory(&resourceData, sizeof(resourceData));
16     resourceData.pSysMem = vertices;
17     
18     result = m_pd3dDevice->CreateBuffer(&vertexDesc, &resourceData, &m_pVertexBuffer);
19     if (FAILED(result))
20     {
21         return false;
22     }
23 
24     return true;

其中D3D11_BUFFER_DESC定義如下:

typedef struct D3D11_BUFFER_DESC {
  UINT        ByteWidth;
  D3D11_USAGE Usage;
  UINT        BindFlags;
  UINT        CPUAccessFlags;
  UINT        MiscFlags;
  UINT        StructureByteStride;
} D3D11_BUFFER_DESC;

D3D11_SUBRESOURCE_DATA定義如下:

typedef struct D3D11_SUBRESOURCE_DATA {
  const void *pSysMem;
  UINT       SysMemPitch;
  UINT       SysMemSlicePitch;
} D3D11_SUBRESOURCE_DATA;

 

渲染幾何體

剩下代碼是渲染幾何體和 shaders 。我們在TriangleDemo::Render() 函數進行渲染幾何體的工作

 1 void TriangleDemo::Render()
 2 {
 3     if (m_pImmediateContext == 0)
 4         return;
 5     //清除渲染目標視圖
 6     float clearColor[4] = { 0.5f, 0.5f, 0.5f, 1.0f };//背景顏色
 7     m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, clearColor);
 8 
 9     UINT stride = sizeof(VertexPos);
10     UINT offset = 0;
11     //設置數據信息格式控制信息
12     m_pImmediateContext->IASetInputLayout(m_pInputLayout);
13     //設置要繪制的幾何體信息
14     m_pImmediateContext->IASetVertexBuffers(0,1,&m_pVertexBuffer,&stride,&offset);
15     //指明如何繪制三角形
16     m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
17     m_pImmediateContext->VSSetShader(m_pSolidColorVS, 0, 0);
18     m_pImmediateContext->PSSetShader(m_pSolidColorPS, 0, 0);
19     m_pImmediateContext->Draw(3, 0);
20     //馬上輸出
21     m_pSwapChain->Present(0, 0);
22 }

 

着色器.fx文件代碼

float4 VS_Main( float4 pos : POSITION ) : SV_POSITION  
  
{    
    return pos;  
  
}  
  
float4 PS_Main( float4 pos : SV_POSITION ) : SV_TARGET  
  
{  
  
    return float4( 1.0f, 0.0f, 0.0f, 1.0f );  
  
}  

我們使用的vertex shader很簡單的, 僅僅是傳遞輸入的頂點坐標到輸出設備;

pixel shader的工作也很簡單, 僅僅是 為每個 像素pixel 配置一種固定的顏色( 紅色)。 

 

最終效果圖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM