文章目錄
- 概覽:
- 詳細步驟:
- 概覽:
- 詳細步驟:
- 概覽:
- 詳細步驟:
Shader 程式在OGRE中的應用
1. 綜述
本文主要闡述在OGRE程式中使用可程式化管線來實現對實體的渲染具體過程。主要是從以OGRE使用shader的方式,並發散shader的渲染基礎知識,提供需要研究的方向。
本文組織是以stepBystep方式展開,共包括
1.著色程式定義
2.著色程式聲明
3.著色程式在材質指令碼中的應用
2. 第一步: 定義shader著色程式概覽:
shader源檔案是指在渲染管線中使用的GPU程式。用來完成渲染的頂點變換和像素變換兩個過程。Shader的程式格式主要包括四種:組譯工具、GLSL、HLSL、CG。(CG教程中第三章),但是,由於彙編的開發效率較低,多數shader由後三者完成。(DemoTexture.hlsl)
詳細步驟:
首先是頂點程式:
1 struct VS_INPUT 2 { 3 float4 Position : POSITION0; 4 float2 Texcoord : TEXCOORD0; 5 6 }; 7 8 struct VS_OUTPUT 9 {10 float4 Position : POSITION0;11 float2 Texcoord : TEXCOORD0;12 13 };
我們看到,首先定義了兩個結構體VS_INPUT、VS_OUTPUT 分別作為輸入輸出的參數(因為當參數較多的傳入傳出時結構體時最好的選擇)。結構體中兩個參數 分別儲存位置和貼圖資訊 具體參數意義參考CG教程中第七章。
VS_OUTPUT vs_main( in VS_INPUT Input ,VS_OUTPUT Output,uniform float4x4 matViewProjection){ Output.Position = mul( matViewProjection ,Input.Position); Output.Texcoord = Input.Texcoord; return( Output ); }
接下來是一個以VS_OUTPUT為傳回值的函數vs_main,當然還包含一些參數,這些參數就是作為GPU預設傳入的參數,而第三個參數一會我們將會看到。
在函數體內部我們做了關於位置和材質的處理後,返回儲存了其值的結構體變數。
接下來是像素著色程式:
struct PS_INPUT { float2 Texcoord : TEXCOORD0; };
首先定義了一個作為輸入接收容器的結構體PS_INPUT,接收從頂點著色程式而來的參數,頂點的座標資訊不會傳入,所以只有材質資訊是它需要的。
float4 ps_main( in PS_INPUT Input,uniform sampler2D DemobaseMap : register(s0)) : COLOR0{ return tex2D( DemobaseMap,Input.Texcoord ) * 1.5; }
接下來是一個以四維浮點數為傳回值的函數ps_main,用來處理獲得的紋理並返回像素顏色。而為什麼一定要四維浮點數呢?因為在GPU中都是以四元組的形式處理參數的,不足四維的會以0代替之,矩陣處理可以參考3D數學編程基礎。
到這裡整個shader程式就完成了他所有的工作:頂點處理和像素處理,而對於管線(CG教程中第二章)的其他部分(裁剪、光柵化等)是由GPU其他固定程式完成的。
3. 第二步: 聲明shader著色程式概覽:
在C++或者其他某些語言中,函數在使用之前需要聲明,表示存在這樣一個函數,我們可以拿來用。在使用我們上面的定義的頂點著色程式和片段著色程式之前,我們需要先聲明一下。
在一般的語言聲明時候,較為簡單,只要說明函數的原型、參數列表即可,但是在這裡的程式聲明就較為複雜一點,因為我們需要指定源檔案、程式類型、指定入口程式、版本資訊等。(DemoTexture.program)(OGRE協助文檔 3.1.4節)
詳細步驟:
首先是頂點程式的聲明:
vertex_program Demo/TexV hlsl { source DemoTexture.hlsl entry_point vs_main target vs_2_0}
可以看到這裡的程式結構較為清晰:vertex_program: 表明是頂點程式, Demo/TexV: 程式名稱。 hlsl:程式格式是 基於Directx的著色程式(基於OpenGL的為 glsl,CG的是cg)
大括弧裡面: source DemoTexture.hlsl 指定頂點程式的源檔案。
entry_point vs_main 指定入口函數(當定義多個函數時用來指定)
target vs_2_0 指定版本
關於版本的支援OGRE協助文檔 3.1.4節。當然你可以通過調用:
GpuProgramManager::getSingleton().getSupportedSyntax()
得到當前顯卡支援的文法列表。
接下來是像素程式的聲明:
fragment_program Demo/TexF hlsl{ source DemoTexture.hlsl entry_point ps_main target ps_2_0}
在像素著色程式聲明和頂點的基本是一樣的。我們看到源檔案是同一個,但是我們指定的入口函數不一樣,所以不會產生分析。另外,對於GLSL中是不需要指定入口函數和目標定義的,因為它以main()函數作為入口,並且它的源檔案以編譯到了本地圖形處理器了,則不需要中間編譯(OGRE協助文檔 3.1.7節)
4. 第三步: 在材質指令碼中引用 shader程式概覽:
下面是對聲明過的頂點著色程式和片段著色程式的引用了。
著色程式在OGRE中作為材質中Pass中的一部分(符合硬體邏輯,其實著色程式在GPU處理中確實是替換了渲染通道(pass)的一部分)來引用的。(DemoTexture.material)
在引用中指定引用函數名稱和初始化參數。
詳細步驟:
以下是引用了shader程式的材質指令碼:material Demo/Texture
{ technique { pass { vertex_program_ref Demo/TexV { param_named_auto matViewProjection viewproj_matrix } fragment_program_ref Demo/TexF { } texture_unit { texture Fieldstone.tga } } } }
我們看到在這個材質的Pass(關於參考OGRE協助文檔 3.1.2節)內多了兩個定義如下:
vertex_program_ref Demo/TexV { param_named_auto matViewProjection viewproj_matrix } fragment_program_ref Demo/TexF { }
當材質中出現這兩個定義是,表示對於使用這個材質指令碼的實體來說已經放棄了固定管線的渲染方式,而是只通過shader來渲染。當程式無法找到你的源檔案,或者你的shader程式有錯誤的話,將導致無法處理的局面:沒有任何材質可用的白色實體。
在引用體當中我們看到如下代碼:
param_named_auto matViewProjection viewproj_matrix
這便是對於我們在來源程式中的matViewProjection中的初始化賦值函數。而viewproj_matrix則是一個在GPU中固化的一個座標值,有由GPU自動獲得。關於參數的詳細介紹,參考OGRE協助文檔 3.1.9節。
這樣,我們就完成了對頂點程式和片段程式的引用和初始化過程。當載入此材質時,見到有shader程式的引用,就會採用指向的頂點著色程式和片端著色程式來處理相應的傳入的變數並將處理結果傳出。
效果:
5. 總結
以上就是在OGRE中使用頂點著色程式和片段著色程式的全部過程,通過書寫shader程式、程式的聲明、程式的引用,主要使我們清楚了整個shader程式的載入過程和一些基本的程式概念。整個指令碼的載入過程:
更多Demo請參考:
http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Shaders