HLSL學習筆記(一) —— 旋轉的三角形

來源:互聯網
上載者:User

畢業設計選的是HLSL編程相關的,於是開始學習。

理論方面的不介紹了,這方面資料很多。只是記錄一些編程實踐相關的東西。

首先要準備一個HLSL程式啟動並執行基本架構。這裡我不使用MS提供的DXUT,太過複雜且使你對底層的來龍去脈懵懵懂懂,DX方面的龍書《Introduction to 3D Game Programming with DirectX 9.0》介紹了一個架構十分簡潔明了,但考慮到以後我的程式的複雜度和可擴充性我使用一個物件導向的DX程式架構,主要參考《DX即時渲染技術詳解》(kelly dempski著)。基本有4個檔案

1.Application.h 提供一個基本的CHostApplication類 主要包括 初始化D3D,建立裝置,建立視窗,枚舉模式等基本函數以及 情境初始化,渲染,丟失,銷毀的虛函數。其中最主要的是提供一個Go()函數,這是處理訊息迴圈,情境渲染的主函數。 包括的成員變數有 D3D對象,D3D裝置對象,視窗控制代碼,視窗長寬等。

2.Application.cpp 實現CHostApplication類提供的成員函數。

3.Executable.h  提供2個函式宣告。程式入口函數及訊息處理回呼函數。

4.Executable.CPP 程式執行主體。在main()中建立CHostApplication衍生類別的對象,之後進入訊息迴圈及情境渲染主體Go().

一些基本的D3D初始化及視窗函數在CHostApplication基類中已經實現,我們只要將重心移到CHostApplication的衍生類別,在衍生類別中重寫CHostApplication基類的渲染初始化,渲染操作,結束渲染等函數用以實現特定情境的繪製工作。

下面介紹這個HLSL程式:旋轉的三角形。

1.在VertexApplication.h中。構建CHostApplication類的衍生類別 CVertexApplication

 #include "Application.h"

class CVertexApplication : public CHostApplication 
{
public:
 BOOL FillVertexBuffer();
 BOOL CreateVertexBuffer();
 void DestroyVertexBuffer();
 CVertexApplication();
 virtual ~CVertexApplication();

 //This function will be called after the D3D object is
 //created.  Here we'll actually create the vertex buffer.
 virtual BOOL PostInitialize();

 //This function will clean up the vertex buffer prior to
 //the destruction of the device
 virtual BOOL PreTerminate();

 //These functions will ensure that lost vertex buffers are
 //recreated once the device is reset
 virtual BOOL PreReset();
 virtual BOOL PostReset();

 //This function will actually render the data.
 virtual void Render();

 //This is the pointer to our vertex buffer
 LPDIRECT3DVERTEXBUFFER9 m_pVertexBuffer;
 IDirect3DVertexShader9* m_pVertexShader;
 LPD3DXCONSTANTTABLE m_pConstantTable_VS;
 D3DXMATRIXA16 m_matWorld,m_matView,m_matProj;
};

注意最後我添加了用於構建HLSL程式的頂點渲染器對象及常量表。

2. 在VertexApplication.cpp 檔案中實現上述相關函數。給出關鍵代碼

BOOL CVertexApplication::PostInitialize()
{
 if (FAILED(EasyCreateWindowed(m_hWnd, D3DDEVTYPE_HAL,
          D3DCREATE_HARDWARE_VERTEXPROCESSING)))
  return FALSE;

    // 建立頂點緩衝區

if(!CreateVertexBuffer())
  return FALSE;

    // 填充頂點緩衝區

 if(!FillVertexBuffer())
  return FALSE;

    //編譯頂點渲染器代碼
 LPD3DXBUFFER pCode_VS;
 DWORD dwShaderFlags = D3DXSHADER_SKIPOPTIMIZATION|D3DXSHADER_DEBUG;
    if(FAILED((D3DXCompileShaderFromFile( L"HLSLTransform.vsh", NULL, NULL, "VS",
                                     "vs_2_0", dwShaderFlags, &pCode_VS,
                                     NULL, &m_pConstantTable_VS))))
    return FALSE;

 //建立頂點渲染器
    if(FAILED((m_pD3DDevice->CreateVertexShader((DWORD*)pCode_VS->GetBufferPointer(),
                                      &m_pVertexShader ))))
    return FALSE;

    pCode_VS->Release();

 //構造觀察矩陣
 D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-5 );
    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
    D3DXMatrixLookAtLH( &m_matView, &vEyePt, &vLookatPt, &vUpVec );

 //構造投影矩陣
 float fAspectRatio = (float)m_WindowWidth/m_WindowHeight;
    D3DXMatrixPerspectiveFovLH( &m_matProj, D3DX_PI/4, fAspectRatio, 1.0f, 100.0f );
  
 //關閉光照處理, 預設情況下使用光照處理
    m_pD3DDevice->SetRenderState( D3DRS_LIGHTING, false );

 //設定剔出模式,為不剔出任何面
 m_pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

 return TRUE;
}

以上是渲染情境前的初始化操作。編譯了HLSL代碼並建立了頂點渲染器對象。

下面是情境繪製代碼

void CVertexApplication::Render()
{
 //Here we regenerate the data and draw the points
 //FillVertexBuffer();

    HRESULT hr = 0;
 //建立世界矩陣
 UINT  iTime  = timeGetTime() % 2000;
    FLOAT fAngle = iTime * (2.0f * D3DX_PI) / 2000.0f;
 D3DXMatrixIdentity( &m_matWorld );
    D3DXMatrixRotationY( &m_matWorld, fAngle );

 //設定全域變數
 D3DXMATRIX mWorldViewProj = m_matWorld * m_matView * m_matProj;
 m_pConstantTable_VS->SetMatrix( m_pD3DDevice, "matWorldViewProj", &mWorldViewProj);

 //設定頂點渲染器對象
 hr = m_pD3DDevice->SetVertexShader(m_pVertexShader);
 if(FAILED(hr))
  return;
 
 // 繪製三角形
 m_pD3DDevice->SetStreamSource(0,m_pVertexBuffer,0,sizeof(SIMPLE_VERTEX));
 m_pD3DDevice->SetFVF(D3DFVF_SIMPLEVERTEX);
 m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 1);
}

在繪製情境的過程中,通過不斷改變世界矩陣而改變mWorldViewProj 局部變數值,然後綁定該變數到HLSL代碼檔案中的全域變數matWorldViewProj,我們可以先來看看HLSL代碼檔案:

//==============================================================
// Desc: 頂點渲染器代碼
//==============================================================

//座標變換矩陣
float4x4 matWorldViewProj; 

//--------------------------------------------------------------
// Desc: 輸出結構
//--------------------------------------------------------------
struct VS_OUTPUT
{
   float4 Pos   : POSITION;
   float4 Color : COLOR;
};

//--------------------------------------------------------------
// Desc: 頂點渲染
//--------------------------------------------------------------
VS_OUTPUT VS( float4 Pos: POSITION, float4 Color: COLOR )
{
   VS_OUTPUT Out = (VS_OUTPUT) 0;
   Out.Pos = mul(Pos, matWorldViewProj);
   Out.Color = Color;
   return Out;
}

可以看到,對於固定流水線中頂點緩衝中的每個頂點的位置POSITION和顏色COLOR作為輸入參數傳遞給VS函數,然後將頂點位置通過Pos*matWorldViewProj達到變換頂點座標的效果之後返回該頂點座標,而HLSL代碼檔案中的matWorldViewProj全域變數綁定到了固定流水線中mWorldViewProj這個局部變數的地址,隨著mWorldViewProj的改變(mWorldViewProj每一幀都在變化),matWorldViewProj同樣改變著,故而使頂點座標達到了變換的效果,之後在頂點緩衝區中的頂點座標為變換後的座標,將之Draw出來即可。

:

完整的工程檔案地址:

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.