• 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 配置一种固定的颜色( 红色)。 

    最终效果图

  • 相关阅读:
    《全职高手》的全部职业和职业技能(最新版)
    博客园样式美化
    科幻电影免费百度云分享(Scince-fiction cloud share)
    阅读须知
    Website's Game source code
    #P2010 回文日期 的题解
    #P1909 买铅笔 的题解
    #P4770 [NOI2018]你的名字 的题解
    #1074 骑士问题 的题解
    [C++基本语法:从菜鸟变成大佬系列,就像1,2,3那么简单](七):C++的修饰符
  • 原文地址:https://www.cnblogs.com/zhangbaochong/p/5428751.html
Copyright © 2020-2023  润新知