C++Directx11開發筆記四:著色器之頂點著色器和像素著色器

來源:互聯網
上載者:User

前面我們學習了Directx 11如何在螢幕上繪製一個圖形(三角形),其中涉及到著色器,我們只是使用了其中的方法,而沒有講解著色器是如何工作的,到底什麼是著色器等等,今天將來瞭解一下著色器到底是什麼!!!由於在Directx 11中包含了多種著色器,而有些著色器在一些進階的應用中才會用到,因此作為一個初學者,先瞭解頂點著色器和像素著色器就OK了,其它的在碰到的時候再進行深入瞭解。

 

著色器:

在以前的顯卡中,映像的呈現就像流水線一樣,不能夠進行編程。不過後來GPU出現了,那樣就可以計算很多東東,也就可以進行編程了,著色器就是一個可程式化的例子,他通過代碼傳給GPU進行計算,然後通過螢幕顯示出來。就像在前面的例子中,我們建立了一個快取資料(Vertex Buffer)將三角形的座標傳給GPU。在Directx 11 SDK中,支援三種基礎著色器:頂點著色器(Vertex Shader),像素著色器(Pixel Shader)【註:有些地方也就叫Fragment Shader】,以及幾何著色器(Geometry Shader)。頂點著色器通過頂點作為輸入資料,只要將每個頂點快取資料傳入GPU就會執行;像素著色器使用一個像素作為輸入資料;而幾何著色器使用基元(primitive)作為輸入,基元可以是一個點,一條線或一個三角形。這三個基礎著色器在呈現時都會遇到,在Direct3D 11中,GPU必須包含一個正確的頂點和像素著色器,而幾何著色器是可選的,因此這也是為什麼我們先瞭解頂點著色器和像素著色器的原因。當然在DirectX中,還包含了其他著色器,如Hull Shader,Domain Shader(域著色器)用於曲面細分(有些地方叫做鑲嵌tessellation),Compute Shader用於計算。

 

頂點著色器:

頂點著色器支援編程,可以把頂點著色器看出是C語言中的一個函數,通過頂點作為參數輸入這個函數,並且返回編程後的頂點資訊。當程式通過頂點著色器傳入頂點緩衝資料時,GPU就會迭代頂點緩衝資料,並為每一個頂點執行一次著色器函數。

頂點著色器可以用了做非常多的事情,最主要的是用了進行座標變換等等,在Direct3D編程中會涉及到很多座標的變換,如:將全局座標轉換為螢幕座標等等。比如一個3D的三角形具有(0, 0, 0) (1, 0, 0) (0, 1, 0)座標,當被繪製到2D紋理緩衝時GPU就需要知道在2D座標系裡的座標,那樣才知道需要畫在什麼地方。關於座標的轉換,我們後續還會遇到,這裡就不進行討論,對於前面的例子我們只需要知道傳入一個頂點資訊,返回一個頂點資訊就OK了,具體代碼如下:

1     float4 VS( float4 Pos : POSITION ) : SV_POSITION
2     {
3         return Pos;
4     }

上面的代碼就是HLSL,在前面我們也介紹了一下,他的語言像C一樣,傳入一個float4資料,POSITION是一個聲明性字串,而SV_POSITION具有特殊的聲明意義,在HLSL中可以查詢到,即是告訴繪圖管線這是定義了一個座標資料。而這個座標就是GPU需要的知道的,也就是說在哪裡繪製。

 

像素著色器:

在現代的顯示器中,螢幕是有很多個正方形格子組成的,這些格式很小,我們把它叫做像素,每一個像素都包含著自己的顏色,他們之間不用相互依賴。其實當我們需要在螢幕上繪製一個三角形時,在螢幕上呈現的不切切是一個三角形,如所示,我們將會更好的理解。

 

 一個三角形,包含了三個頂點,通過這三個頂點連在一起,即叫做光柵化。GPU首先需要知道哪些像素需要被呈現,然後將這些需要呈現(三角形內部)像素啟用並賦予顏色值,像素著色器就是為了計算哪些像素需要的顏色。像素著色器通過輸入的像素顏色值,然後計算顏色並且將其返回給繪圖管線。像素管線參數一般由幾何著色器返回,假如沒有幾何著色器,比如我們上一節說說的例子,那麼就通過頂點著色器返回。

頂點著色器中通過SV_POSITION聲明描述建立了一個float4的值用於返回像素的座標位置,這將作為像素著色器的輸入參數,這樣就告之了GPU當前座標,而像素著色器返回的一個顏色值,即也為float4數值,並且使用SV_TARGET聲明描述,以表示將用於目標的轉譯格式。其代碼如下所示:

1     float4 PS( float4 Pos : SV_POSITION ) : SV_Target
2     {
3         return float4( 1.0f, 1.0f, 0.0f, 1.0f );    // Yellow, with Alpha = 1
4     }

 

編譯著色器:

著色器編寫的代碼即HLSL儲存在一個文字檔中,可以通過Direct3D 11中的D3DX11CompileFromFile()進行編譯,其代碼如下所示:

1     // Create the vertex shader
2     if( FAILED( D3DX11CompileFromFile( "Tutorial03.fx", NULL, NULL, "VS", "vs_4_0", D3DCOMPILE_ENABLE_STRICTNESS, NULL, NULL, &pVSBlob, &pErrorBlob, NULL ) ) )
3         return FALSE;

5     // Create the pixel shader
6     if( FAILED( D3DX11CompileFromFile( "Tutorial03.fx", NULL, NULL, "PS", "ps_4_0", D3DCOMPILE_ENABLE_STRICTNESS, NULL, NULL, &pPSBlob, &pErrorBlob, NULL ) ) )
7         return FALSE;

 

綁定著色器:

這樣我們就可以在C++代碼中通過VSSetShader() 和 PSSetShader()兩個方法將頂點著色器和像素著色器綁定到管線上,當我們使用Draw方法時,將頂點緩衝資訊Vertex Buffer傳入到繪圖管線中進行繪製,這樣關於頂點著色器和像素著色器就瞭解完畢了。

 

通過這篇文章其實就是瞭解到兩個東東,頂點著色器是告訴管線座標,而像素著色器是告訴管線顏色,有了這兩項東西就可以繪製圖形了。當然在實際需求中不可能這麼便宜,書寫的代碼還是挺多的,最主要希望微軟也能夠將HLSL的言語智能提示繼承到VS中,那樣我想像我這種寫代碼的人將會帶來很爽的感覺。

 

附:

Directx11管道流水線

 

曲面細分(Tessellator):

從上面這張技術解析圖,我們可以很瞭解到Hull Shader、Tessellator、Domain Shader這3個新單元的具體作用:Hull Shader主要負責定義細分等級(LOD)和相關控制點在細分中的“形變”趨勢,需要說明的是這種形變僅僅是類似於曲率改變等小幅度的變化,而非大幅度的多邊形位移;Tessellator則負責根據Hull Shader傳輸下來的資訊,通過“暴力”增加多邊形去實現Hull Shader的要求;Domain Shader負責的最重要的功能就是通過貼圖控制的方式,實現模型的形變,也就是我們大家在DX11的細分曲面中看到的高細節畫面。

相關文章

聯繫我們

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