青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當(dāng)自強(qiáng)而不息

像素著色器入門(1)

像素著色器是一段執(zhí)行在圖形卡的GPU上的程序,它運(yùn)行在對每個像素進(jìn)行光柵化處理時。(不像頂點(diǎn)著色器,Direct3D不會以軟件模擬像素著色器的功能。)實(shí)際上它替換了固定功能管線的多紋理化階段(the multitexturing stage),并賦予我們直接操縱單獨(dú)的像素和訪問每個像素的紋理坐標(biāo)的能力。這種對像素和紋理坐標(biāo)的直接訪問使我們可以達(dá)成各種特效,例如:多紋理化(multitexturing)、每像素光照(per pixel lighting)、景深(depth of field)、云狀物模擬(cloud simulation)、焰火模擬(fire simulation)、高級陰影技術(shù)(sophisticated shadowing technique)。

圖形卡支持的像素著色器的版本可以通過D3DCAPS9結(jié)構(gòu)的PixelShaderVersion成員和D3DPS_VERSION宏進(jìn)行檢查。下列代碼片斷展示了這點(diǎn):

// If the device's supported version is less than version 2.0

if( caps.PixelShaderVersion < D3DPS_VERSION(2, 0) )

     // Then pixel shader version 2.0 is not supported on this device.

 

18.1多紋理化概覽

多紋理化(Multitexturing)可能是用像素著色器實(shí)現(xiàn)的最簡單的技巧了。

多紋理化后面的概念有一點(diǎn)和混合(blending)相關(guān),可以將正要被光柵化的像素與之前寫入后臺緩沖的像素進(jìn)行混合來達(dá)成一種特效。我們延伸這種相同的思想到多紋理化中(multiple texture)。也就是說,我們一次使用幾個紋理,然后定義這些紋理如何被混合在一起,以達(dá)到一種特殊效果。多紋理化的一個通常的用法是執(zhí)行光照。作為在頂點(diǎn)處理階段使用Direct3D的光照模型的替代,我們使用一種叫做“光照圖”(light map)的特殊紋理貼圖(texture map),它編碼(encode)表面是如何被光照的。例如,假設(shè)我們希望一盞聚光燈(spotlight)照在一個大木箱上,我們要么定義一個D3DLIGHT9結(jié)構(gòu)的聚光燈,要么將代表木箱的紋理貼圖與代表聚光燈的光照映射混合在一起,如圖18.1所示。

注意:結(jié)果圖像依賴于紋理被混合的方式。在固定功能管線的多紋理化階段,混合方程式被紋理渲染狀態(tài)(texture render state)控制。用像素著色器,我們能以可編程的方式在代碼中寫出混合函數(shù)的簡單表達(dá)式。這使我們可以用任何我們想要的方式混合紋理。

混合多個紋理(本例中是兩個)來照亮木箱比起Direct3D的光照來有兩個好處:

光照是是預(yù)先在聚光燈的光照貼圖里計(jì)算好的。因此,光照不需要在運(yùn)行時被計(jì)算,這節(jié)省了處理時間。當(dāng)然,只有靜態(tài)對象和靜態(tài)燈光的光照可以被預(yù)先計(jì)算。

因?yàn)楣庹請D是預(yù)先計(jì)算好的,我們能夠使用比Direct3D的(光照)模型多的多的更加精確的和成熟的光照模型。(更好的光照可以產(chǎn)生更真實(shí)的場景。)

備注:多紋理化階段的典型應(yīng)用是實(shí)現(xiàn)靜態(tài)對象的完全光照引擎(full lighting engine)。例如,我們可以用一個紋理貼圖保存對象的顏色,比如木箱的紋理貼圖。然后我們可以用一個散射光照貼圖(diffuse light map)保存散射表面著色(diffuse surface shade),一個單獨(dú)的鏡面光照貼圖保存鏡面表面著色,一個霧狀物貼圖(fog map)保存覆蓋在表面的霧狀物的總量,還有可以用一個細(xì)節(jié)貼圖(detail map)保存小的、高訪問率的表面的細(xì)節(jié)。當(dāng)所有這些紋理被組合起來,只需到這些預(yù)先計(jì)算的紋理中檢索,就可以有效的照亮、著色并且增加細(xì)節(jié)到場景中去。

注意:聚光燈光照貼圖在很基礎(chǔ)的光照貼圖中是一個價(jià)值不高(trivial)的例子。一般的的程序通過給定的場景和光源來生成光照貼圖。

 

18.1.1 允許多個紋理

回憶一下,紋理是用IDirect3DDevice9::SetTexture方法設(shè)置,而采樣器狀態(tài)(sampler state)是用IDirect3DDevice9::SetSamplerState方法設(shè)置,原型如下:

HRESULT IDirect3DDevice9::SetTexture(

     DWORD Stage, // specifies the texture stage index

     IDirect3DBaseTexture9 *pTexture

);

 

HRESULT IDirect3DDevice9::SetSamplerState(

     DWORD Sampler, // specifies the sampler stage index

     D3DSAMPLERSTATETYPE Type,

     DWORD Value

);

 

注意:一個特定的采樣器階段索引I關(guān)聯(lián)第i個紋理階段(texture stage)。即第i個采樣器階段指定采樣器狀態(tài)是第i集(set)紋理。

紋理/采樣器階段索引標(biāo)識了我們希望設(shè)置的紋理/采樣器的紋理/采樣器階段。因此,我們可以允許多個紋理并通過使用不同的階段索引設(shè)置其相應(yīng)的采樣器狀態(tài)。例如,假設(shè)我們要允許三個紋理,我們像這樣使用階段0,1和2:

// Set first texture and corresponding sampler states.

Device->SetTexture(0, Tex1);

Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

 

// Set second texture and corresponding sampler states.

Device->SetTexture(1, Tex2);

Device->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

Device->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

Device->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

 

// Set third texture and corresponding sampler states.

Device->SetTexture(2, Tex3);

Device->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

Device->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

Device->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

這段代碼使用Tex1, Tex2和Tex3,并設(shè)置每個紋理的過濾模式。

 

18.1.2 多紋理坐標(biāo)

對于每個3D三角形,我們應(yīng)該在紋理上定義一個三角形以映射該3D三角形。我們通過對每個頂點(diǎn)增加紋理坐標(biāo)完成映射。因此,每三個頂點(diǎn)定義一個三角形,它對應(yīng)于紋理上的三角形。

現(xiàn)在使用多紋理,每三個頂點(diǎn)定義一個三角形,我們需要在每個被使用的紋理上定義一個相應(yīng)的三角形。通過給每個頂點(diǎn)增加額外的一套紋理坐標(biāo)——每個頂點(diǎn)一套,對應(yīng)于每個使用的紋理。舉個例子,如果我們混合三個紋理到一起,那么每個頂點(diǎn)必須有三套紋理坐標(biāo)以索引到三個使用的紋理。因此,一個包含三個紋理的多紋理化頂點(diǎn)結(jié)構(gòu)看起來可能像這樣:

struct MultiTexVertex

{

     MultiTexVertex(float x, float y, float z,

                    float u0, float v0,

                    float u1, float v1,

                    float u2, float v2)

     {

          _x =  x;   _y = y; _z = z;

          _u0 = u0;  _v0 = v0;

          _u1 = u1;  _v1 = v1;

          _u2 = u2;  _v2 = v2;

     }

 

     float _x, _y, _z;

     float _u0, _v0; // Texture coordinates for texture at stage 0.

     float _u1, _v1; // Texture coordinates for texture at stage 1.

     float _u2, _v2; // Texture coordinates for texture at stage 2.

 

     static const DWORD FVF;

};

const DWORD MultiTexVertex::FVF = D3DFVF_XYZ | D3DFVF_TEX3;

 

注意,指定自由頂點(diǎn)格式標(biāo)記D3DFVF_TEX3表明頂點(diǎn)結(jié)構(gòu)包含3套紋理坐標(biāo)。固定功能管線支持最多8套紋理坐標(biāo)。如果多于8套,你必須使用頂點(diǎn)聲明和可編程頂點(diǎn)管線。

注意:在新版本像素著色器中,我們可以使用一套紋理坐標(biāo)集來索引多個紋理,并因此消除了對多個紋理坐標(biāo)的需要。當(dāng)然這得假設(shè)每個紋理階段使用相同的紋理坐標(biāo)。如果每個階段的紋理坐標(biāo)不同,則我們?nèi)匀恍枰嗉y理坐標(biāo)。

 

18.2像素著色器輸入和輸出

有兩樣?xùn)|西要輸入到像素著色器:顏色和紋理坐標(biāo)。兩樣都是以每像素為單位的。

注意:頂點(diǎn)顏色是在圖元的面(face of primitive)間進(jìn)行插值的。

每個像素的紋理坐標(biāo)就是簡單的 (u , v) ,它指定了紋理的哪個圖素被映射到像素上。在輸入到像素著色器前,Direct3D根據(jù)頂點(diǎn)顏色和頂點(diǎn)紋理坐標(biāo),為每個像素計(jì)算顏色和紋理坐標(biāo)。輸入到像素著色器的顏色和紋理坐標(biāo)的數(shù)值依賴于頂點(diǎn)著色器輸出的顏色和紋理坐標(biāo)的數(shù)值。例如,如果一個頂點(diǎn)著色器輸出了兩個顏色和三個紋理坐標(biāo),那么Direct3D將會為每個像素計(jì)算兩個顏色和三個紋理坐標(biāo)并且把它們把它們輸入到像素著色器。我們使用帶語意的語法(semantic syntax)映射輸入顏色和紋理坐標(biāo)進(jìn)我們的著色器程序的變量里。用前面的例子,我們可以這樣寫:

struct PS_INPUT

{

     vector c0 : COLOR0;

     vector c1 : COLOR1;

     float2 t0 : TEXCOORD0;

     float2 t1 : TEXCOORD1;

     float2 t2 : TEXCOORD2;

};

 

對于輸出,像素著色器只輸出一個計(jì)算過的該像素的顏色值:

struct PS_OUTPUT

{

     vector finalPixelColor : COLOR0;

};

 

 

18.3使用像素著色器的步驟

下面的列表概述了創(chuàng)建和使用像素著色器的必要步驟:

1.        編寫并編譯像素著色器

2.        創(chuàng)建一個IDirect3DPixelShader9接口來代表基于已編譯代碼的像素著色器

3.        用IDirect3DDevice9::SetPixelShader方法允許該像素著色器

當(dāng)然,用完頂點(diǎn)著色器之后我們必須銷毀它。

 

18.3.1 編寫并編譯像素著色器

我們用與編譯頂點(diǎn)著色器一樣的方式編譯像素著色器。首先,我們必須編寫一個像素著色器程序, 我們用HLSL編寫我們的著色器。一旦寫好著色器代碼,我們就可以用D3DXCompileShaderFromFile函數(shù)編譯該著色器了,這個函數(shù)返回一個ID3DXBuffer指針,它包含已編譯的著色器代碼。

注意:因?yàn)槲覀兪褂玫氖窍袼刂鳎砸浀冒丫幾g目標(biāo)改成像素著色器目標(biāo)(比如:ps_2_0),而不是頂點(diǎn)著色器目標(biāo)(比如:vs_2_0)。編譯目標(biāo)通過D3DXCompileShaderFromFile函數(shù)的一個參數(shù)指定。

 

18.3.2 創(chuàng)建像素著色器

一旦我們編譯了著色器代碼,我們就可以獲得一個IDirect3DPixelShader的接口指針,它代表一個像素著色器,使用下面的方法:

HRESULT IDirect3DDevice9::CreatePixelShader(

      CONST DWORD *pFunction,

      IDirect3DPixelShader9** ppShader

);

pFunction——已編譯著色器代碼的指針

ppShader——返回一個IDirect3DPixelShader9接口的指針

例如,假設(shè)變量shader是一個包含已編譯著色器代碼的ID3DXBuffer接口指針。那么要獲得IDirect3DPixelShader9接口,我們應(yīng)該寫:

IDirect3DPixelShader9* MultiTexPS = 0;

hr = Device->CreatePixelShader( (DWORD*)shader->GetBufferPointer(), &MultiTexPS);

注意:重申一遍,D3DXCompileShaderFromFile是一個可以返回已編譯著色器代碼(shader)的函數(shù)。

 

18.3.3 建立像素著色器

在我們獲得一個代表我們的像素著色器的IDirect3DPixelShader9接口的指針之后,我們可以使用下面的方法使用它:

HRESULT IDirect3DDevice9::SetPixelShader(

      IDirect3DPixelShader9* pShader

);

這個方法只接受一個參數(shù),我們通過它傳遞一個我們希望使用的指向像素著色器的指針。

Device->SetPixelShader(MultiTexPS);

 

18.3.4 銷毀像素著色器

和其它所有Direct3D接口一樣,要清除這些接口,我們必須在使用完畢后調(diào)用它們的Release方法。

d3d::Release<IDirect3DPixelShader9*>(MultiTexPS);


posted on 2008-04-11 12:38 lovedday 閱讀(2344) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

隨筆分類(178)

3D游戲編程相關(guān)鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            最新日韩欧美| 女同性一区二区三区人了人一 | 日韩视频永久免费| 好吊色欧美一区二区三区四区 | 一区二区三区视频在线播放| 免费高清在线视频一区·| 午夜精品久久久久久久白皮肤| 一本色道久久综合狠狠躁的推荐| 亚洲九九爱视频| 在线播放中文一区| 伊人婷婷欧美激情| 亚洲电影免费在线观看| 亚洲一区二区三区免费在线观看| 在线一区二区视频| 欧美高清在线观看| 亚洲国产成人在线| 亚洲日本成人女熟在线观看| 亚洲激情校园春色| 老司机免费视频久久| 欧美va亚洲va国产综合| 欧美成人精品不卡视频在线观看 | 欧美激情中文字幕一区二区| 欧美一区2区三区4区公司二百| 午夜精品在线| 久久深夜福利免费观看| 欧美成人精品在线播放| 最近中文字幕日韩精品| 亚洲私人黄色宅男| 久久婷婷一区| 欧美日韩欧美一区二区| 欧美激情小视频| 欧美日韩中文在线观看| 国产日韩欧美成人| 亚洲日本中文字幕区| 亚洲视频在线一区观看| 欧美综合77777色婷婷| 亚洲男女自偷自拍| 麻豆精品在线播放| 在线一区二区三区四区五区| 久久久欧美精品| 欧美日韩在线三区| 怡红院av一区二区三区| 一区二区三区视频在线看| 久久精品首页| 亚洲美女在线观看| 久久九九国产| 国产精品视频一二三| 亚洲国产日韩一级| 欧美在线观看网站| 亚洲美女黄色| 美女视频黄 久久| 国产美女精品免费电影| 国产精品一区二区欧美| 亚洲欧洲日本专区| 久久精品中文| 亚洲天堂男人| 欧美精品一区二区三区视频| 黄色亚洲在线| 久久精品2019中文字幕| 一本一本久久| 欧美看片网站| 亚洲福利在线观看| 久久先锋影音| 欧美伊久线香蕉线新在线| 模特精品裸拍一区| 国产一区二区三区视频在线观看| 欧美三级在线视频| 一本不卡影院| 久久免费视频在线观看| 亚洲第一色在线| 久久亚洲影音av资源网| 国产视频一区二区在线观看 | 亚洲视频每日更新| 欧美久久久久久| 亚洲精品护士| 亚洲国产精品成人| 老司机一区二区三区| 伊人久久噜噜噜躁狠狠躁 | 国产精品一区久久久| 日韩亚洲欧美在线观看| 欧美不卡视频一区发布| 久久久不卡网国产精品一区| 国产一区二区三区黄视频| 99v久久综合狠狠综合久久| 亚洲国产欧美一区二区三区丁香婷| 久久精品国产一区二区三区免费看 | 国产欧美韩日| 久久九九99视频| 欧美一区二区精品| 国产揄拍国内精品对白| 久久伊人精品天天| 99精品国产在热久久| 国产精品v亚洲精品v日韩精品| 亚洲午夜精品久久| 亚洲午夜高清视频| 国产视频一区二区在线观看| 亚洲精品免费一二三区| 亚洲人成在线观看| 欧美调教vk| 欧美专区在线| 免费成人av| 亚洲一区二区三区在线看 | 亚洲图片欧美午夜| 亚洲一区免费网站| 国产日韩欧美一区在线 | 亚洲午夜一区二区| 欧美在线日韩在线| 亚洲欧美日韩综合一区| 欧美福利在线观看| 久久久久成人精品| 国产精品毛片高清在线完整版| 免费观看成人网| 国产日韩欧美二区| 亚洲中字黄色| 亚洲一区免费在线观看| 欧美高清视频在线播放| 久久久噜噜噜久久久| 国产精品视频| 一本大道久久精品懂色aⅴ | 在线成人h网| 亚洲欧美日韩直播| 亚洲午夜电影| 欧美精品在线观看播放| 欧美激情视频给我| 亚洲国产精品va| 久久色在线观看| 免播放器亚洲一区| 精品动漫一区二区| 久久久久久**毛片大全| 久久精品久久综合| 国产在线观看一区| 久久疯狂做爰流白浆xx| 久久久人成影片一区二区三区| 国产欧美一区二区三区视频| 亚洲自拍偷拍麻豆| 欧美一区二区观看视频| 国产嫩草一区二区三区在线观看| 亚洲永久视频| 欧美一进一出视频| 国产一区二区三区直播精品电影| 午夜一区二区三区不卡视频| 久久黄色影院| 狠狠色综合网| 麻豆九一精品爱看视频在线观看免费| 欧美va亚洲va国产综合| 最新国产の精品合集bt伙计| 欧美国内亚洲| 中文国产成人精品久久一| 羞羞漫画18久久大片| 韩日在线一区| 欧美高清不卡| 一二三区精品福利视频| 欧美在线精品一区| 尤物精品在线| 欧美日韩成人综合天天影院| 中文亚洲免费| 另类人畜视频在线| 夜夜嗨av一区二区三区免费区| 国产精品爱久久久久久久| 午夜亚洲性色视频| 亚洲电影免费| 香蕉久久一区二区不卡无毒影院| 国内精品福利| 欧美理论在线播放| 欧美在线观看网址综合| 欧美国产乱视频| 亚洲欧美制服另类日韩| 伊人久久亚洲影院| 国产精品久久久久久久午夜 | 国产精品久久福利| 久久精品视频在线| 亚洲精品乱码久久久久久日本蜜臀| 亚洲一区图片| 亚洲国产一区二区三区青草影视| 欧美三区在线视频| 久久久综合网| 亚洲一区影院| 亚洲国产色一区| 久久久激情视频| 亚洲视频一区在线观看| 尤物yw午夜国产精品视频| 国产精品国产三级国产a| 久久视频一区二区| 午夜一区二区三区在线观看| 亚洲人体影院| 男女av一区三区二区色多| 亚洲欧美综合精品久久成人| 欧美精品一区二区三区蜜桃 | 久久久久国色av免费看影院 | 亚洲激情成人| 久久夜色撩人精品| 欧美一区二区三区免费看| 日韩视频在线免费| 亚洲大胆美女视频| 国产一区美女| 国产日韩一区二区三区在线| 欧美精品三级| 欧美激情国产日韩精品一区18| 久久精品国产亚洲高清剧情介绍| 亚洲视频每日更新|