• <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>

            永遠也不完美的程序

            不斷學習,不斷實踐,不斷的重構……

            常用鏈接

            統計

            積分與排名

            好友鏈接

            最新評論

            HLSL初級教程(3)

            3.像素著色器

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

                   像素著色器的編寫、使用和頂點著色器大同小異,有了之前的基礎,不用太過于詳細的介紹相信讀者也能理解,下面使用像素著色器實現多紋理化。


            3.1多紋理化

                   簡單的說,多紋理化就是使用多個紋理貼圖混合后進行渲染,如圖3.1,渲染過程中,從紋理1和紋理2中分別采樣,得到的顏色值依據一定規則進行組合得到紋理3,這就是多紋理化。

            3.1



            3.2多紋理效果的像素著色器

                   下面是像素著色器的代碼,該代碼存儲于ps.txt中,該像素著色器根據輸入的兩套紋理坐標對對應的紋理貼圖進行采樣,根據一定比例Scalar混合后輸出像素顏色。

            //全局變量

             

            //存儲顏色混合的比例值s,其中

            //Scalar.x = s

            //Scalar.y = 1-s

            vector Scalar;

             

            //紋理

            texture Tex0;

            texture Tex1;

             

            //紋理采樣器

            sampler Samp0 =

            sampler_state

            {

                Texture = <Tex0>;

                MipFilter = LINEAR;

                MinFilter = LINEAR;

                MagFilter = LINEAR;

            };

             

            sampler Samp1 =

            sampler_state

            {

                Texture = <Tex1>;

                MipFilter = LINEAR;

                MinFilter = LINEAR;

                MagFilter = LINEAR;

            };

             

            //輸入兩套紋理坐標

            struct PS_INPUT

            {

                   float2 uvCoords0 : TEXCOORD0;

                   float2 uvCoords1 : TEXCOORD1;

            };

             

            //輸出像素顏色

            struct PS_OUTPUT

            {

                   float4 Color : COLOR0;

            };

             

            //入口函數

            PS_OUTPUT PS_Main(PS_INPUT input)

            {

                   PS_OUTPUT output = (PS_OUTPUT)0;

                   //分別對兩個紋理進行采樣按照比例混合后輸出顏色值

                   output.Color = tex2D(Samp0, input.uvCoords0)*Scalar.x + tex2D(Samp1, input.uvCoords1)*Scalar.y;

                   return output;

            }

                   整個程序很容易理解,程序中涉及到著色器的紋理和采樣,是我們第一次接觸的內容,下面給于說明。

            3.2.1HLSL采樣器和紋理

                   vectormatrix一樣,采樣器sample和紋理texture也是HLSL語言的一種類型,HLSL著色器使用采樣器對指定紋理進行采樣,得到采樣后的顏色值以供處理。

                   它們的用法如下:

                   //聲明一個紋理變量

                   texture g_texture;

             

                   //定義采樣器

                   sampler g_samp =

                   sampler_state

                   {

                          //關聯到紋理

                   Texture = <g_texture>;

                   //設置采樣器狀態

                       MipFilter = LINEAR;

                       MinFilter = LINEAR;

                       MagFilter = LINEAR;

                   };

             

                   //調用HLSL內置函數tex2D取得顏色值,參數一為采樣器,參數二為紋理坐標

                   vector Color = tex2D(g_samp, uvCoords);

                   更多HLSL采樣器和紋理的內容請參見DirectX文檔。

             

                   以上是本例用到的像素著色器,在接下來的應用程序中,我們將給三個著色器全局變量賦值:

            ²        Scalar

                          存儲顏色混合的比例值s,其中Scalar.x = s, Scalar.y = 1-s;

            ²        Samp0

                          第一層紋理采樣器;

            ²        Samp1

                          第二層紋理采樣器;

                   像素著色器的輸入結構中我們設定了一個頂點對應兩套紋理坐標,讀者可以留意一下應用程序中對應的頂點格式的定義。


            3.3應用程序

                   程序中我們首先創建一個四邊形,然后使用像素著色器進行紋理混合后對其進行渲染。下面是應用程序代碼:

            /*********************頂點格式定義*****************/

            struct CUSTOMVERTEX

            {

                   //定點位置坐標

                   float x,y,z;

                   //兩套紋理坐標;

                   float tu0, tv0;

                   float tu1, tv1;

            };

            #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX2)

            /*********************聲明變量*****************/

            //頂點著色器

            LPDIRECT3DPIXELSHADER9 pixelShader   = 0;

            //常量表

            ID3DXConstantTable* pixelConstTable = 0;

             

            //常量句柄

            D3DXHANDLE ScalarHandle              = 0;

            D3DXHANDLE Samp0Handle                = 0;

            D3DXHANDLE Samp1Handle                = 0;

             

            //常量描述結構

            D3DXCONSTANT_DESC Samp0Desc;

            D3DXCONSTANT_DESC Samp1Desc;

             

            //四邊形頂點緩存

            LPDIRECT3DVERTEXBUFFER9 quadVB = NULL;

            //兩個紋理

            LPDIRECT3DTEXTURE9 quadTexture0 = NULL;

            LPDIRECT3DTEXTURE9 quadTexture1 = NULL;

             

            /********************初始化應用程序*****************/

            //創建四邊形頂點模型

            CUSTOMVERTEX quad[] =

            // x      y      z    tu0   tv0   tu1   tv1

            {{-3.0f, -3.0f, 10.0f, 0.0f, 1.0f, 0.0f, 1.0f},

            { -3.0f3.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f},

            3.0f, -3.0f, 10.0f, 1.0f, 1.0f, 1.0f, 1.0f},

            3.0f3.0f, 10.0f, 1.0f, 0.0f, 1.0f, 0.0f}};

             

            //創建頂點緩存

            void *ptr = NULL;

            g_pd3dDevice->CreateVertexBuffer(sizeof(quad),

                                                                     D3DUSAGE_WRITEONLY,

                                                                     0,

                                                                     D3DPOOL_MANAGED,

                                                                     &quadVB,

                                                                     NULL);

            quadVB->Lock(0, 0, (void**)&ptr, 0);

            memcpy((void*)ptr, (void*)quad, sizeof(quad));

            quadVB->Unlock();

             

            //創建紋理

            D3DXCreateTextureFromFile(g_pd3dDevice, "porpcart.jpg", &quadTexture0);

            D3DXCreateTextureFromFile(g_pd3dDevice, "luoqi.jpg", &quadTexture1);

             

            //檢測系統是否支持像素著色器

            D3DCAPS9 caps;

            g_pd3dDevice->GetDeviceCaps(&caps);

            if(caps.PixelShaderVersion < D3DPS_VERSION(1, 1))

            {

                   MessageBox(0, "NotSupport Pixel Shader - FAILED", 0, 0);

                   exit(0);

            }

             

            //創建像素著色器

            ID3DXBuffer* codeBuffer        = 0;

            ID3DXBuffer* errorBuffer       = 0;

             

            HRESULT hr = D3DXCompileShaderFromFile("ps.txt",

                                                                              0,

                                                                              0,

                                                                              "PS_Main", // entry point function name

                                                                              "ps_1_1",

                                                                              D3DXSHADER_DEBUG,

                                                                              &codeBuffer,

                                                                              &errorBuffer,

                                                                              &pixelConstTable);

             

            // output any error messages

            if(errorBuffer)

            {

                   MessageBox(0, (char*)errorBuffer->GetBufferPointer(), 0, 0);

                   ReleaseCOM(errorBuffer);

            }

             

            if(FAILED(hr))

            {

                   MessageBox(0, "D3DXCompileShaderFromFile() - FAILED", 0, 0);

                   return false;

            }

             

             

            hr = g_pd3dDevice->CreatePixelShader((DWORD*)codeBuffer->GetBufferPointer(), &pixelShader);

             

            if(FAILED(hr))

            {

                   MessageBox(0, "CreatePixelShader - FAILED", 0, 0);

                   return false;

            }

             

            ReleaseCOM(codeBuffer);

            ReleaseCOM(errorBuffer);

             

            //得到各常量句柄

            ScalarHandle = pixelConstTable->GetConstantByName(0, "Scalar");

            Samp0Handle = pixelConstTable->GetConstantByName(0, "Samp0");

            Samp1Handle = pixelConstTable->GetConstantByName(0, "Samp1");

             

            //得到對著色器變量Samp0Samp0的描述

            UINT count;

            pixelConstTable->GetConstantDesc(Samp0Handle, & Samp0Desc, &count);

            pixelConstTable->GetConstantDesc(Samp1Handle, & Samp1Desc, &count);

             

            //設定各著色器變量為初始值

            pixelConstTable->SetDefaults(g_pd3dDevice);

            /********************渲染*****************/

            g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(153,153,153), 1.0f, 0 );

            g_pd3dDevice->BeginScene();

             

            //為著色器全局變量Scalar賦值

            D3DXVECTOR4 scalar(0.5f, 0.5f, 0.0f, 1.0f);

            pixelConstTable->SetVector(g_pd3dDevice, ScalarHandle, &scalar);

             

            //設置像素著色器

            g_pd3dDevice->SetPixelShader(pixelShader);

             

            //設置定點格式、綁定數據流

            g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);

            g_pd3dDevice->SetStreamSource(0, quadVB, 0, sizeof(CUSTOMVERTEX));

             

            //設置第一、二層紋理

            g_pd3dDevice->SetTexture(Samp0Desc.RegisterIndex, quadTexture0);

            g_pd3dDevice->SetTexture(Samp1Desc.RegisterIndex, quadTexture1);

             

            //繪制圖形

            g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

             

            g_pd3dDevice->EndScene();

            g_pd3dDevice->Present(NULL, NULL, NULL, NULL);

             

                   程序中像素著色器的使用和之前頂點著色器的使用無二,只是設置著色器中紋理采樣器變量Samp0Samp1和設定著色器其他變量稍有不同:

                1. 首先通過變量名稱得到變量句柄:

                          Tex0Handle = pixelConstTable->GetConstantByName(0, " Samp0");

                          Tex1Handle = pixelConstTable->GetConstantByName(0, " Samp1");

                2. 然后通過句柄得到對變量的描述:

                          UINT count;

                          pixelConstTable->GetConstantDesc(Samp0Handle, & Samp0Desc, &count);

                          pixelConstTable->GetConstantDesc(Samp1Handle, & Samp1Desc, &count);

                3.最后通過SetTexture配合所得到的描述信息設置紋理:

                          g_pd3dDevice->SetTexture(Samp0Desc.RegisterIndex, quadTexture0);

                          g_pd3dDevice->SetTexture(Samp1Desc.RegisterIndex, quadTexture1);

             

                   編譯運行程序,運行效果如圖3.2,這里我們將顏色混合比例設置為0.5,如果讀者在渲染過程中不斷變換對著色器變量Scalar的賦值,你將會得到一個混合度不斷變換的多紋理效果。

                   D3DXVECTOR4 scalar(0.5f, 0.5f, 0.0f, 1.0f); //讀者可以嘗試改變混合采用的比例值

                   pixelConstTable->SetVector(g_pd3dDevice, ScalarHandle, &scalar);

             

             

            紋理一

            紋理二

            混合后紋理三

            3.2


            posted on 2008-08-04 15:56 狂爛球 閱讀(2624) 評論(0)  編輯 收藏 引用

            一本一道久久精品综合| 色欲综合久久中文字幕网| 久久最新精品国产| 久久综合综合久久狠狠狠97色88 | 四虎国产精品成人免费久久| 欧美日韩成人精品久久久免费看| 中文字幕日本人妻久久久免费| 久久99国产精品尤物| 久久久久综合国产欧美一区二区| 久久综合给合久久国产免费| 久久久精品日本一区二区三区| 久久夜色精品国产噜噜麻豆| 日韩欧美亚洲综合久久影院Ds| 久久国产一区二区| 久久精品国产AV一区二区三区 | 亚洲色婷婷综合久久| 久久精品国产亚洲5555| 国产精品天天影视久久综合网| 久久久久久久91精品免费观看| 国产精品内射久久久久欢欢| 91精品国产乱码久久久久久| 伊人久久大香线蕉av一区| 欧美午夜A∨大片久久| 97久久精品人人澡人人爽| 久久久精品一区二区三区| 久久国产精品99精品国产| 久久亚洲中文字幕精品有坂深雪| 亚洲精品国精品久久99热| 人妻无码久久精品| 国产成人综合久久久久久| 精品久久久久久无码中文字幕 | 久久免费精品视频| 亚洲AV日韩精品久久久久| 7777精品伊人久久久大香线蕉| 亚洲伊人久久综合中文成人网| 国产精品久久久天天影视香蕉| 2021久久精品国产99国产精品| 久久亚洲AV成人出白浆无码国产 | 久久精品国产亚洲AV香蕉| 2021国产精品久久精品| 亚洲国产精品无码久久一区二区|