著色器(Shader)之畫素著色器

2021-09-11 02:42:55 字數 4041 閱讀 2207

畫素著色器實際上就是對每乙個畫素進行光柵化的處理期間,在gpu上運算的一段程式。

不同與頂點著色器,畫素著色器不會以軟體的形式來模擬畫素著色器。

畫素著色器實質上是取代了固定功能流水線中多重紋理的環節,而且賦予了我們訪問單個畫素以及訪問每乙個畫素紋理座標的能力

多重紋理就是我們同時啟用多層紋理,然後規定他們的融合方式,以得到特殊效果。

多重紋理最典型的應用就是光照運算,在頂點運算階段,我們不打算使用direct3d的光照模型,而是使用光照紋理圖,

他規定了某一面是如何被照亮的。

例如:我們想在板條箱的上面投射聚光燈,我們可用結構d3dlight9來定義該聚光燈,也可以將代表光照的紋理和板條箱的紋理進行融合

通過多重紋理進行融合比比direct3d光照計算模型的優點:

1、光照已經預先計算好,並儲存在聚光燈的紋理圖中,這樣程式在執行的時候,就不需要在對光照進行計算了,節省了時間

2、由於光照紋理圖是預先計算好的,我們可以採用比direct3d更精確的光照模型,從而得到更逼真的效果

多重紋理環節一般適用於為靜態的物體實現乙個完整的光照引擎。假如我們現在手上有多張已經計算好的紋理圖,

比如:物體本身的紋理圖,漫反射光照的紋理圖,還有就是鏡面光照的紋理圖,當我們需要這些紋理的合成的時候,

只需對這些預先計算好的紋理圖進行查詢即可高效的為場景增加光照和增加細節。

多重紋理中有一點就是多重紋理座標,用最簡單的三角形來看的話,簡單的繪製三角形,我們只需要一層紋理,此時只需要

乙個紋理座標,當我們需要三層紋理融合的時候,按照這種思路的話,每乙個頂點裡面就需要三對兒紋理座標,

每乙個紋理座標都對應一層紋理的中的乙個頂點。

固定的流水線至多支援8層紋理座標,再多的話就只能使用頂點宣告了。

但是在新的畫素著色器中,乙個紋理座標可以對應多個索引來引用紋理,這樣就無需多個紋理座標了,當然這是建立在每乙個紋理層

都使用的相同的紋理座標,如果每層紋理中的紋理座標有差異,還是需要多個紋理座標。

畫素著色器的輸入包括每個畫素的顏色以及紋理座標。

每乙個畫素的紋理座標其實就是指定了紋理中將被對映到當前畫素的紋理元的座標。

在進入畫素著色器之前。direct3d先根據頂點的顏色以及頂點的紋理座標計算出每乙個畫素的顏色以及紋理座標。

輸入畫素著色器的顏色和紋理座標的個數  是由 頂點著色器輸出的顏色和紋理座標的個數決定。

如果乙個頂點著色器輸出兩種顏色和3個紋理座標,則direct3d計算出每乙個畫素的兩種顏色以及3個紋理座標對,

然後將結果輸入到畫素著色器中。

此時我們需要**來將剛才的結果作為畫素著色器的輸入:

struct ps_input 

;

就輸出而言,畫素著色器將會輸出每乙個畫素的單個值(不太明白,應該是兩種顏色融合之後的值吧)

struct ps_output 

1、編寫畫素著色器程式,然後進行編譯

2、建立乙個idirect3dpixershader9的介面物件,表示經過編譯之後的畫素著色器

3、使用setpixershader方法來啟用畫素著色器

tip:畫素著色器使用完成之後必須進行銷毀

畫素著色器的編寫和頂點著色器的編寫完全相同,具體可以參見頂點著色器程式的編寫。

**編寫完成之後,我們可以使用d3dxcompileshaderfromfile對著色器進行編譯,編譯的版本應該是:ps_2_0,應該

區別於頂點著色器的vs_2_0。

著色器**經過了編譯,我們就可借助下述方法獲取指向idirect3dpixelshader9介面的指標,

該介面代表了乙個畫素著色器。

hresult createpixelshader(

const dword*peunction,idirect3dpixelshader9**ppshader

);

·pfunction指向經過編譯的著色器**的指標。

·ppshader 返回乙個指向idirect3dpixelshader9介面的指標。

例如,假定變數shader是1d3dxbuffer介面的物件,它包含了經過編譯的著色器**。

為了獲取idirect3dpixelshader9介面的指標,我們可以這樣做:

idirect3dpixelshader9* multitexps=0; 

hr=device->createpixelshader(

(dword*)shader->getbufferpointer(),

&multitexps);

當獲取了代表畫素著色器的介面idirect3dpixelshader9的指標後,我們可用下述方法將其啟用:

hresult setpixelshader(

idirect3dpixelshader9*pshader

);

該方法只接收乙個引數,我們可將指向希望啟用的畫素著色器的指標傳給該引數。

為了啟用我們剛才建立的著色器,可以這樣:

device->setpixelshader(multitexps);

像direct3d的所有其他介面一樣,介面idirect3dpixelshader9在使用完畢之後也必須

呼叫其自身的release方法來釋放它所占用的資源。

d3d::release(multitexps);

畫素著色器中對紋理進行取樣,hlsl裡面有內建函式。

tip:取樣就是根據畫素的能紋理座標和取樣狀態來檢索畫素所對應的紋理元

紋理座標是作為畫素著色器的輸入。而我們檢索的特定的紋理在畫素著色器中用乙個hlsl物件——取樣器(sampler)來標識

例如:我們現在使用3層紋理,在畫素著色器中我們這麼寫:

sampler firsttex;

sampler secondtex;

sampler thirdtex;

direct3d將每乙個sampler的物件唯一的與某一層紋理關聯起來,在應用程式中我們找出sampler物件所對應的紋理層,

然後為該紋理層設定合適紋理以及取樣器的狀態。

下面**就做了這些:

//建立紋理 

idirect3dtexture9* tex; 

d3dxcreatetexturefromfile(device,"tex.bmp",&tex);

//獲取常量的控制代碼

firsttexhandle =multitexct->getconstantbyname(0,"firsttex");

//獲取常量的描述

d3dxconstant_desc firsttexdesc; 

uint count; 

multitexct->getconstantdesc(firsttexhandle,&firsttexdesc,& count);

//為取樣器firsttex設定紋理/取樣器狀態

//registerindex是d3dxconstant_desc的成員

device->settexture(firsttexdesc. registerindex, tex); 

device->setsamplerstate(firsttexdesc. registerindex, d3dsamp_mageilter,d3dtexf_linear); 

device->setsamplerstate(firsttexdesc. registerindex, d3dsamp_minfilter,d3dtexf_linear); 

device->setsamplerstate(firsttexdesc. registerindex, d3dsamp_mipfilter,d3dtexf_linear);

小結:

畫素著色器取代了固定流水線中的多重紋理功能,使我們能夠對畫素進行單個的訪問,並且可以操縱畫素的紋理座標,使我們更具有靈活性。

多重紋理是讓好幾層紋理進行融合,然後產生效果,我們經常使用多重紋理對靜態物體進行完整光照計算引擎

hlsl裡面的sampler物件標識了乙個特定的紋理層。

著色器(Shader)之頂點著色器

頂點著色器其實就是我們自己編寫的一段在gpu中執行的程式,有了頂點著色器,我們就可以從固定的功能流水線中代替一些模組,從而獲得更多的頂點操作的靈活性。對於頂點位置進行操作的的能力具有廣泛的應該場合 織物模擬 粒子系統的點尺寸處理等。可程式設計流水線中的頂點結構比固定的流水線具有更加豐富的資料。首先我...

OpenGL ES 著色器 片斷著色器詳解

opengl es 入門 01 opengl es 入門 02 opengl es 入門 03 opengl es 入門 04 opengl es 入門 05 opengl es 入門練習 01 opengl es 入門練習 02 opengl es 入門練習 03 opengl es 入門練習 0...

頂點著色器 片段著色器

一 著色器 著色器只是一種把輸入轉化為輸出的程式。著色器也是一種非常獨立的程式,因為它們之間不能相互通訊 它們之間唯一的溝通只有通過輸入和輸出。在最簡配置下,至少都得有兩個著色器 乙個叫頂點著色器 vertex shader 它將作用於每個頂點上 另乙個叫片段著色器 fragment shader ...