1: 設(shè)計初衷
它設(shè)計初衷是完全跨平臺的。抽象的接口隱藏了平臺相關(guān)的細(xì)節(jié)。
它設(shè)計初衷是大幅度支持?jǐn)U展的。支持多種場景類型,獨立出平臺和3D接口限制。
2: 基本類結(jié)構(gòu)關(guān)系
Roo:對象為一切的入口,它負(fù)責(zé)創(chuàng)建Ogre的所有基礎(chǔ)元素,三大基礎(chǔ)元素大致包括:場景管理器,繪制系統(tǒng),資源管理器。
場景管理器:場景節(jié)點,動態(tài)對象。
資源管理器:資源組管理,資源管理
渲染模塊:硬件緩沖區(qū)管理,渲染系統(tǒng),渲染窗口
3:關(guān)鍵詞
Root::Ogre系統(tǒng)入口,程序一開始就應(yīng)當(dāng)創(chuàng)建,最后釋放,它幫助我們獲得其他元素的指針。甚至包括StartRender()
RenderSystem::渲染系統(tǒng)。是對3D渲染API的一個封裝。一般來說無需手工調(diào)用,場景管理器對對其進(jìn)行控制,只有在實現(xiàn)一些特殊需要的時候,可以獲取使用。
SceneManager:負(fù)責(zé)對整個場景中內(nèi)容的創(chuàng)建和管理。包括靜態(tài)地形場景,攝象機(jī),動態(tài)對象,光線,材質(zhì)等都?xì)w屬其管理。場景管理器根據(jù)室內(nèi)室外等渲染管理進(jìn)行了不同類型的優(yōu)化,在創(chuàng)建時可以傳參進(jìn)行選擇。
ResourceGroupManager:資源組管理器包含多種的資源管理器,例如紋理,網(wǎng)格Mesh等
的資源加載管理器,他們各司其職管理其所負(fù)責(zé)的資源數(shù)據(jù)對象。和渲染系統(tǒng)一樣,大多數(shù)情況下他們會被自動調(diào)用的進(jìn)行資源加載,我們僅需要做的就是
Root::getSingleton().addRessourceLocation()告訴Ogre從哪兒加載資源即可,除非個別特殊需求,我們動態(tài)
的手工控制時候可以TextureManager::getSingleton()獲取相應(yīng)的資源管理器進(jìn)行處理。
Mesh對象:就是一個具體的模型,而在一些情況下,Mesh對象僅指那些能夠移動的對象,那些靜態(tài)對象即不屬于Mesh對象之列。Ogre有自己的一套定義的Mesh結(jié)構(gòu),即.mesh,該文件格式可以被網(wǎng)格工具編輯。
Entity實體:是一個可移動的對象實例。和Mesh的不同是,實體
包括網(wǎng)格,但若網(wǎng)格未和場景結(jié)點綁定起來,則不可使用該實體。我們可以修改場景結(jié)點來獲得實體的修改,但此時Mesh實際是沒有變化的。注意:實體是允許
有子實體的,網(wǎng)格也一樣有子網(wǎng)格。每一個子網(wǎng)格可以有自己的材質(zhì)。相關(guān)函數(shù)如下:SceneManager::CreateEntity()由場景管理器
去創(chuàng)建實體對象,Entity::GetSubEntity()獲取子實體指針,再SetMaterialName()修改材質(zhì)。
材質(zhì):它是由資源管理器管理,但在場景管理器中也保存著一份材質(zhì)的列表。它的屬性有默認(rèn)
的,SceneManager::GetDefaultMaterialSetting()函數(shù)可以獲取其默認(rèn)屬性,當(dāng)然也可以修改。值得注意的
是,OGRE允許在程序運(yùn)行時,通過材質(zhì)腳本對材質(zhì)進(jìn)行設(shè)置。
Overlays層:一般是拿來做一些不接收用戶交互信息的UI面層
的。當(dāng)然游戲中也可以設(shè)置一些層元素作為游戲內(nèi)容,例如飛機(jī)駕駛艙,不接受任何用戶交互信息,并且要求最前端顯示。層有一個專門的層管理器,它負(fù)責(zé)層的創(chuàng)
建釋放等工作。每個層有自己的一個Z深度信息,通過它進(jìn)行遮擋關(guān)系的計算。另外,每幾個層可以分為一個小組進(jìn)行統(tǒng)一控制,這個在Ogre中被稱為層容器
OverlayContainer。每個層可以進(jìn)行獨立的旋轉(zhuǎn)縮放等功能。它允許是2D或3D。
OverlayManager::getSingleton().createOverlayElement(“Panel”,
“myNewPanel”)。
4:Ogre的腳本
1:材質(zhì)腳本。在
資源組管理器初始化完畢時,裝載材質(zhì)腳本,OGRE會自動的在組相關(guān)的資源位置查找”.materal”擴(kuò)展名的文件,并對這些腳本進(jìn)行語法解析。手動解
析也可以MaterialSerializer::parseScript()但是注意的是:解析腳本時并沒有對腳本中定義的全部紋理等資源進(jìn)行加載。所
以,在我們訪問一個材質(zhì)的時候,一定要確保它已經(jīng)裝載,或者,我們手動將此材質(zhì)Load()一次再進(jìn)行訪問。另外,材質(zhì)名必須唯一,且不可有”:”號。
格式:以{},空格,//作為標(biāo)識符。
// 后跟注釋,不支持多行注釋。
{} 之間代表為一個解析單元
每一個material XXX 代表是一個材質(zhì)單元。其中,每一個technique代表一個材質(zhì)渲染手法,pass是每個渲染通路模式,texture_unit則是一個紋理單元。
一個材質(zhì)腳本允許有多個渲染手法技術(shù),一個渲染手法技術(shù)中允許有多個渲染通路模式,一個渲染通道允許有多個紋理單元。
渲染手法技術(shù)Techinique:
一個“渲染手法技術(shù)”就是一個單獨的渲染物體的方法。多個技術(shù)的存在原因是為適用不同的顯卡以及根據(jù)遠(yuǎn)近關(guān)系對一個物體進(jìn)行不同的渲染。
技術(shù)的排列需要一定順序,一般來說,最常用最的技術(shù)放在腳本最前面,
格式為: Techinique 技術(shù)名
不命名的技術(shù)默認(rèn)會以其序列號進(jìn)行命名,注意,技術(shù)名不可重復(fù)。
方案技術(shù)scheme:
因為我們對不同的顯卡標(biāo)準(zhǔn)或根據(jù)某中不同的需求,設(shè)計出不同的技術(shù),每種技術(shù)所適用的環(huán)境方案需要我們指出。
格式為: scheme 方案名
默認(rèn)的方案是default,若我們某一個技術(shù)適用于開啟hdr,Shader3.0的方案,我們只需對該技術(shù)設(shè)置方案為 scheme hdr_open_shader_3_0 即可。
細(xì)節(jié)層次索引 lod_index:
每一個技術(shù)都必須對應(yīng)一個細(xì)節(jié)層次索引。一般來說,默認(rèn)的都是0,即最近最優(yōu)秀的渲染技術(shù),當(dāng)我們需要對遠(yuǎn)處細(xì)節(jié)進(jìn)行渲染時,則設(shè)置這個值吧。
格式為: lod_index 數(shù)值層級
雖說lod的數(shù)值層級是從0-65535,一般設(shè)置2-4層就差不多了吧。因為技術(shù)有一定的排列順序,所以,我們一般是將index大的技術(shù)放在后面。
細(xì)節(jié)層次距離 lod_distances:
這里指定使用不同的細(xì)節(jié)層次的距離值,注意,該屬性必須在所有的技術(shù)塊外面進(jìn)行聲明指定。
如例子中所標(biāo)識:lod_distance 200 就代表,在0-200這個距離內(nèi),我們使用細(xì)節(jié)層次為0的技術(shù),在200以上的則使用細(xì)節(jié)層次為1的技術(shù)
Lod_distance 200 700.5 則表示在0-200時我們使用細(xì)節(jié)0,200-700.5這段距離使用細(xì)節(jié)1的材質(zhì)技術(shù),700.5以上使用細(xì)節(jié)2的材質(zhì)技術(shù)。200和700.5間使用空格間隔。
所以技術(shù)的排列順序通常為這樣
Material MyTestMaterial
{
lod_distances 200
Technique Lod_0_Hdr_Open_Shader_3_0
{
Lod_index 0
Pass 0
{
Texture_unit
{
//…..
}
Texture_unit
{
//…..
}
}
Pass 1
{
Texture unit
{
// ….
}
}
}
Technique Lod_0_Hdr_Close_Shader_1_0
{
Lod_index 0
Pass
{
Texture_unit
{
//…..
}
Texture_unit
{
//…..
}
}
}
Technique Lod_1_Hdr_Open_Shader_3_0
{
Lod_index 1
Pass
{
Texture_unit
{
//…..
}
Texture_unit
{
//…..
}
}
}
Technique Lod_1_Hdr_Close_Shader_1_0
{
Lod_index 1
Pass
{
Texture_unit
{
//…..
}
Texture_unit
{
//…..
}
}
}
}
Pass渲染通路:
再次強(qiáng)調(diào)一個概念:一個材質(zhì)腳本,為了適應(yīng)不同的顯卡和LOD細(xì)節(jié)層次技術(shù),我們允許有多個技術(shù),為了加速充分的使用GPU,每個技術(shù)中同時又支持多通道的渲染,每個渲染通道內(nèi),同時又允許有多個紋理單元。首先這個改變必須明確理解才能順利的進(jìn)行材質(zhì)腳本的設(shè)計。
我們在“渲染通路”這層可以設(shè)置以下屬性:
· ambient 材質(zhì)的環(huán)境光反射系數(shù)
格式是 ambient red green blue alpha
每個值要求為0.0-1.0之間,例如ambient 0.2 0.2 1.0 1.0代表每個頂點對環(huán)境光的反射系數(shù)。注意:若關(guān)閉了動態(tài)光照和紋理層的光照色彩混合的話,該項就不起作用了。默認(rèn)值為全白
· diffuse 材質(zhì)的漫反射系數(shù)
格式是 diffuse red green blue alpha 其他同上。
· specular 材質(zhì)的鏡面反射系數(shù)
格式是 specular red green blue alpha Shininess ,最后多了一個參數(shù),是閃耀值,該值處于1-128之間。注意:若該值較大則會令人感到耀眼的反射。
· emissive 材質(zhì)自發(fā)光系數(shù)
格式是 emissive red green blue alpha
· scene_blend
設(shè)置渲染通道和現(xiàn)有的渲染層內(nèi)容混合方式。有預(yù)設(shè)的四種方式
格式為scene_blend add或scene_blend modulate/alpha_blend/colour_blend
Add 是將渲染出的顏色和亮度一起疊加到渲染場景中,相當(dāng)于“scene_blend one one”
Modulate 是將渲染輸出的顏色疊加到渲染場景中,相當(dāng)于”scene_blend dest_colour zero”
alpha_blend 是將渲染輸出的亮度疊加到渲染場景中,相當(dāng)于”scene_blend src_colour one_minus_src_colour”
colour_blend 是將渲染輸出的alpha值進(jìn)行遮罩緩和。相當(dāng)于”scene_blend src_alpha one_minus_src_alpha”
當(dāng)然,我們也可以不使用預(yù)設(shè)的方式,進(jìn)行自定義源和目標(biāo)的混合因數(shù)
格式為 scene_blend src_factor dest_factor
這樣最終渲染出的顏色就是 (渲染通道的結(jié)果 * src_factor) + (渲染場景的顏色 * dest_factor),其中src_factor dest_factor兩個參數(shù)可選以下值
one
常數(shù)值1.0
zero
常數(shù)值0.0
dest_colour
已存在的像素顏色
src_colour
紋理像素顏色
one_minus_dest_colour
1 -(dest_colour)
one_minus_src_colour
1 -(src_colour)
dest_alpha
已存在的像素alpha值
src_alpha
紋理像素alpha值
one_minus_dest_alpha
1 -(dest_alpha)
one_minus_src_alpha
1 -(src_alpha)
例如:scene_blend one zero (代表渲染出的紋理完全覆蓋其后的渲染場景,即渲染管道出來的紋理是完全不透明的) ß默認(rèn)的混合模式也正是這種。
· depth_check
是否開啟深度緩沖檢測 格式為 depth_check on 或 depth_check off
· depth_write
是否打開深度緩沖寫入。 格式為 depth_write on 或 depth_write off
默認(rèn)的時候深度緩沖是打開的,個別時候我們需要渲染一系列透明物體的關(guān)系時候,則將其關(guān)閉。
· depth_func
寫入象素前的深度比較函數(shù)。 格式為 depth_func compareFun
其中compareFun可以取下面值之一。
always_fail
永遠(yuǎn)不向渲染目標(biāo)寫入像素
always_pass
總是將像素寫入渲染目標(biāo)
less
如果將要寫入的像素的深度小于現(xiàn)在緩沖區(qū)內(nèi)容的深度,則寫入
less_equal
如果將要寫入的像素的深度小于等于現(xiàn)在緩沖區(qū)內(nèi)容的深度,則寫入
equal
如果將要寫入的像素的深度等于現(xiàn)在緩沖區(qū)內(nèi)容的深度,則寫入
not_equal
如果將要寫入的像素的深度不等于現(xiàn)在緩沖區(qū)內(nèi)容的深度,則寫入
greater_equal
如果將要寫入的像素的深度大于等于現(xiàn)在緩沖區(qū)內(nèi)容的深度,則寫入
greater
如果將要寫入的像素的深度大于現(xiàn)在緩沖區(qū)內(nèi)容的深度,則寫入
默認(rèn)值是 depth_func less_equal ,注意:當(dāng)我們關(guān)閉深入緩沖檢測的話,該函數(shù)無效。
· depth_bias
無法理解。不會用。
· alpha_rejection
對渲染管道的材質(zhì)紋理進(jìn)行alpha信息剪裁。 格式為 alpha_rejection compareFun value
其中value取值范圍是0-255,例如 alpha_rejection less_equal 122 則代表拋棄渲染管道中alpha值大于等于122的象素。附注:考慮到硬件兼容,Value最好是0-128之間。
· cull_hardware
硬件剪裁方式。 格式為 cull_hardware HCutFun
HCutFun枚舉下列三種方式:clockwise / anticlockwise/ none
clockwise將逆時針的三角型都cut掉(即CUT鏡頭反面)
anticlockwise將順時針的三角型都cut掉(即CUT鏡頭正面)
none 不做任何剪切。
默認(rèn)為 clockwise
· cull_software
軟件剪裁方式。 格式為 cull_software SCutFun
SCutFun 枚舉以下三種格式:back / front / none
實際上,這個和硬件裁減是類似的,不過,對于一些動態(tài)的物件建議不要開啟該項,消耗很大。默認(rèn)是 back 剪裁。
· lighting
是否開啟動態(tài)光照。 格式為 lighting on / off
注意:使用了頂點程序,此屬性無效。動態(tài)光照一旦關(guān)閉,環(huán)境光反射,鏡面反射光,放射光,陰影等屬性均無效。默認(rèn)為on
· shading
Ogre陰影模式。 格式為 shading flat/ gouraud/ phong
Flat不進(jìn)行插值,每個平面的陰影都由該平面的第一個頂點色決定。
Gouraud 對平面上每個頂點顏色進(jìn)行線形插入計算。
Phong 全平面使用頂點法線向量。效果好,代價高,部份硬件無法支持此屬性。
默認(rèn)為 : gouraud
· polygon_mode
柵格化方式。 格式為 polygon_mode solid/ wireframe/ points
面,線,點的柵格化。默認(rèn)當(dāng)然是面solid模式。
· fog_override
是否開啟霧化。 fog_override true/false
當(dāng)fog_override true的時候就需要順序跟出以下參數(shù)
霧的type: none 無霧。 相當(dāng)于fog_override false
Linear 線性霧。 從 start到end之間有霧
Exp 幾何方次性霧。 受濃度 density 影響
Exp2 幾何二次方增加。 受濃度 density 影響
霧的顏色 color: RGB三種顏色值。0.0-1.0之間
霧的濃度 density:設(shè)置幾何方次性霧的濃度。對線形霧不影響,但也必須寫上進(jìn)行占位。
霧的起始位置 start :對非線性霧無效,但必須寫上占位。
霧的結(jié)束位置 end : 對非線性霧無效,但必須寫上占位。
例如:fog_override true exp 1 1 1 0.002 100 10000 開啟幾何次方霧。顏色為1,1,1白色,濃度為0.002(若是線性則代表,離鏡頭100至10000之間的距離有霧)
· colour_write
是否關(guān)閉渲染通路的顏色寫入功能。 colour_write on/off
該功能一旦關(guān)閉,則代表渲染通路不可輸入任何的顏色渲染。僅在初期初始化深度緩沖區(qū)時個別時間有用。默認(rèn)為開on
· max_lights
此渲染通路最大光源數(shù)量。一般使用默認(rèn)為8 格式為 max_lights 8
· start_light
· iteration
是否對渲染通路進(jìn)行迭代渲染。 默認(rèn)為僅渲染一次,格式為Iteration once
Iteration 5 代表本渲染通路將被重復(fù)執(zhí)行5次渲染。
Iteration once per_light point 則代表本渲染通道將每個光源點進(jìn)行一次渲染。
Iteration 5 per_light point則代表本渲染通道將每個光源點進(jìn)行5次渲染。
· point_size
· point_sprites
· point_size_attenuation
· point_size_min
· point_size_max
Texture_unit 紋理單元
我們在PASS渲染通道處已經(jīng)進(jìn)行了一次整體的渲染環(huán)境設(shè)置,然而,在每個紋理單元,我們還可以對單獨的紋理進(jìn)行渲染屬性設(shè)置。
· texture_alias
設(shè)置一個紋理的別名。類似于技術(shù)的別名。格式: texture_alias 紋理別名
默認(rèn)該別名就是紋理單元的名字。
· texture
本層要使用的靜態(tài)紋理圖象名字。可以簡單的格式為
Texture xxx.jpg (注意:紋理文件名禁止有空格)也可對其屬性進(jìn)行詳細(xì)的設(shè)置。如下
Texture xxx.jpg 2d 8 none PF_A8R8G8B8
2d是裝載的紋理類型,類型實際上包括1d(1象素的紋理點),2d(紋理面,默認(rèn)也是該項),3d(3D帶深度的紋理),cubic(有些類似天空盒式的貼在立方體內(nèi)側(cè)6個2D紋理,但是僅可貼同一種紋理,不如使用cubic_texture)
8 是MipMap的層級,默認(rèn)是unlinited,代表可以無限的對紋理進(jìn)行mipmap,我們這里設(shè)置為8代表生成8個層級遞減的MIPMAP。注意:若多個材質(zhì)腳本中使用同一個紋理,切記他們的mipmap數(shù)量必須一致。
None 這項是我們指定的單獨的透明通道做為alpha進(jìn)行裝載,默認(rèn)的為 none,表示以紅色作為alpha通道。
PF_A8R8G8B8紋理格式,常用的有PF_R5G6B5,PF_A4R4G4B4,PF_A8R8G8B8,PF_X8R8G8B8等。
· anim_texture
與上面的texture對應(yīng),是用于活動的紋理層,即動態(tài)圖象。注意,這里不是使用默認(rèn)的保存好的.gif動畫,而是導(dǎo)入多楨圖,設(shè)置好楨之間的間隔時間。這里我們有兩種方法。
一種是按照Ogre內(nèi)部規(guī)定對動畫的紋理命名:xxx_0.jpg xxx_1.jpg xxx_2.jpg這樣以0為首,加下劃線遞增命名,這樣我們調(diào)用時會比較方便,這樣便可以了
Anim_texture xxx.jpg 3 2.2 即代表xxx_0.jpg這樣命名的紋理有3張,間隔時間為2.2秒。
另一種是非標(biāo)準(zhǔn)的紋理命名,則需要我們?nèi)缦聦懀?/span>
Anim_texture 1.jpg flame2.jpg xxx_3.png hit4.tga 2.2 直接以空格間隔標(biāo)示逐個標(biāo)示出每一楨的紋理即可。
注意:2.2是每楨間的間隔時間,若設(shè)置為0,則不會自動進(jìn)行楨畫面切換,需要我們代碼中手工控制了。
· cubic_texture
創(chuàng)建一個立方體紋理。這個一般用于反射映射和天空盒中。其格式和動態(tài)紋理一樣,有兩種方式,一種是Ogre制定的規(guī)范,我們調(diào)用就更加簡單,如下
Cubic_texture skybox.jpg combinedUVW
我們僅提供一個基礎(chǔ)的紋理名,此時OGRE會默認(rèn)的去查找skybox_fr.jpg, skybox_bk.jpg, skybox_up.jpg, skybox_dn.jpg, skybox_lf.jpg, skybox_rt.jpg這些紋理。
第二中方式則是按照“前后上下左右”的順序?qū)⑦@些紋理羅列出來。
最后一個參數(shù)需要設(shè)置為combinedUVW或separateUV, combinedUVW會將紋理組合到一個立方體紋理映射中,帶有UVW三維紋理坐標(biāo),適合做反射映射。而separateUV僅僅保存2D的UV坐標(biāo),適用于天空盒。
· tex_coord_set
因為一個Mesh網(wǎng)格允許有多套紋理坐標(biāo)集,我們在這里設(shè)置使用哪套坐標(biāo)集。格式為 tex_coord_set 3 (使用編號為3的坐標(biāo)集)
默認(rèn)為 tex_coord_set 0
· tex_address_mode
紋理尋址模式。即當(dāng)紋理UV值大于1.0時的紋理處理方法。參數(shù)有以下幾種枚舉選擇:
Wrap 會將所有UV值大于1.0的值設(shè)置為0.0,紋理會被重復(fù)連續(xù)繪制。
Clamp 會將所有UV值大于1.0的值設(shè)置為1.0,這樣的話就相當(dāng)于在模糊邊界。
Mirror 會當(dāng)UV值等于1.0的時候,將紋理反轉(zhuǎn)后連續(xù)繪制。
Border 超過1.0的UV都會被設(shè)置為邊界色,就是描邊效果。此項可設(shè)置tex_border_colour屬性。
· tex_border_colour
和上一屬性對應(yīng),設(shè)置紋理邊界色,僅對Border紋理尋址有效。
格式 : tex_border_colour RGBA(0.0 – 1.0取值)
· filtering
紋理過濾形式:我們可以使用其預(yù)定的四種基本類型,包括
None 不進(jìn)行紋理過濾
Bilinear 進(jìn)行雙線性紋理過濾。就是對mipmap進(jìn)行挑選過濾,但是不對mipmap各個級別之間進(jìn)行過濾
Trilinear 進(jìn)行三線性紋理過濾。將最近的兩個mipmap一起進(jìn)行過濾。
Anisotropic 各向異性紋理過濾。使用該項,則你必須設(shè)置其max_anisotropy值。
默認(rèn)為bilinear。
· max_anisotropy
最大各相異性程度偏差值。根據(jù)硬件不同一般限制為8或者16
默認(rèn)為 max_anisotropy 1
· mipmap_bias
我們在Pass通道時已經(jīng)允許設(shè)置mipmap紋理Lod運(yùn)用層級以及適用的距離。在紋理單元這層級我們可以重新對其進(jìn)行調(diào)整。格式為
Mipmap_bias -3 后面的整數(shù)代表在所有的范圍內(nèi)強(qiáng)制使用增大或縮小的mip級別。-3代表,在所有范圍內(nèi)強(qiáng)制使用更大3級的mip紋理。
默認(rèn)是不進(jìn)行層級偏移:mipmap_bias 0
· colour_op
簡單的紋理混合方式,我們可以使用預(yù)定義的4項枚舉:
Replace 不處理,用當(dāng)前的紋理直接替換掉后面的所有顏色。覆蓋式。
Add 將當(dāng)前紋理色和后面的渲染顏色進(jìn)行加法處理。
Modulate 將當(dāng)前紋理色和后面的渲染顏色進(jìn)行乘法處理。
Alpha_blend 將當(dāng)前紋理和后面的紋理進(jìn)行alpha顏色混合。
默認(rèn)為 colour_op modulate 當(dāng)前紋理色和后面顏色進(jìn)行乘法混合。
· colour_op_ex
高級的紋理混合模式,可以詳細(xì)的指定混合系數(shù)和效果,但個人不推薦使用。效率消耗較大,且受不用的硬件限制性大,使用默認(rèn)支持的4種混合模式可以了。
· colour_op_multipass_fallback
當(dāng)上面一個colour_op_ex設(shè)置要求過高,硬件無法支持多紋理混合時,則不得不調(diào)用該項進(jìn)行多通路混合渲染。若我們使用的是colour_op預(yù)設(shè)置的4種紋理混合模式,則無需在此處理,OGRE底層已經(jīng)做了完善的處理。
· alpha_op_ex
同colour_op_ex,不推薦使用。
· env_map
設(shè)置環(huán)境映射效果。該項可以使用預(yù)定義的五個選項
Off 關(guān)閉環(huán)境映射反射。 默認(rèn)即本項。
Spherical 開啟球面環(huán)境映射。 它需要一個單獨的紋理,該紋理進(jìn)行周圍反射的記錄。
Cubic_reflection 開啟平面環(huán)境映射。
· scroll
靜態(tài)紋理偏移。 個人感覺這個函數(shù)的存在意義完全是拿來彌補(bǔ)美術(shù)的小BUG。或者是個別情況下,事件響應(yīng)時調(diào)用對紋理的修改?
格式如下:scroll x y
· scroll_anim
動態(tài)紋理偏移。 ……針對上一功能的補(bǔ)足。給紋理層一個移動速度進(jìn)行偏移。
格式為 scroll_anim xspeed yspeed
· rotate
以固定角度靜態(tài)旋轉(zhuǎn)一個紋理。和scroll沒什么區(qū)別。格式如下 rotate angle
注: angle是逆時針旋轉(zhuǎn)的角度數(shù)
· rotate_anim
動態(tài)旋轉(zhuǎn)一個紋理。 格式為 rotate_anim 3 代表每秒旋轉(zhuǎn)3次360度。
· scale
靜態(tài)縮放一個紋理。 格式為 scale x_scale y_scale。
· wave_xform
制作類似于水面波紋性質(zhì)的專用函數(shù)。可以制造出一個類似于波狀的動態(tài)紋理變化形式。
格式: wave_xform <xform_type> <wave_type> <base> <frequency> <phase> <amplitude>
示例: wave_xform scale_x sine 1.0 0.2 0.0 5.0
xform_type
scroll_x
變動x滾動值
scroll_y
變動y滾動值
rotate
變動旋轉(zhuǎn)值
scale_x
變動x比例值
scale_y
變動y比例值
wave_type
sine
典型的正弦波,在最小值和最大值之間平穩(wěn)地循環(huán)。
triangle
以恒定的速度增加減少的有角度的波,在極值時立即改變。
square
最大是波長的一半,最小是瞬時轉(zhuǎn)換之間的停止時間。
sawtooth
經(jīng)過一段時間,從最小逐漸持續(xù)增加到最大,最后立即回到最小。
inverse_sawtooth
經(jīng)過一段時間,從最大逐漸持續(xù)減少到最小,最后又立即返回最大。::base
基值,如果amplitude > 0就是指最小值,amplitdue < 0就是指最大值。
frequency
波每秒重復(fù)的次數(shù),即速度。
phase
波開始的偏移量。
amplitude
波的大小。
波的輸出范圍在{base, base+amplitude}。所以,以在x方向調(diào)整紋理為例,沿正弦波方向從1(標(biāo)準(zhǔn)值)調(diào)整到5,即表示每5秒一個周期(每秒0.2個波)。
· transform
為紋理提供一個4*4矩陣以直接替代上面的旋轉(zhuǎn),縮放,移動等一系列變化。
格式為 transform m00 m01 m02 m03 m10 m11 m12 m13 m20 m21 m22 m23 m30 m31 m32 m33
· binding_type
設(shè)置綁定類型。該紋理是綁定到片斷處理單元還是頂點處理單元。格式為:
Binding_type fragment / vertex
默認(rèn)為綁定片斷處理單元。
· content_type
設(shè)置紋理內(nèi)容的來源類型。格式為 content_type named / shadow
默認(rèn)是為named,表示紋理單元圖片來源于texture,cubic_texture,anim_texture之一,但個別時候我們需要使用陰影紋理,則此時可以設(shè)置為shadow
注: 除去上面的紋理屬性設(shè)置之外,假若我們需要更高級的紋理屬性支持,可以使用外部紋理源。
頂點程序和片斷程序聲明:
假設(shè)我們在材質(zhì)腳本中需要使用頂點程序或者片段程序,那么,類似于函數(shù)聲明調(diào)用一樣,我們必須在調(diào)用它之前先對其進(jìn)行聲明定義。
假若調(diào)用點都在一個.meterial腳本內(nèi)還好,我們只需要在調(diào)用處的上面進(jìn)行聲明定義,但,假若多個腳本都調(diào)用一段頂點程序,我們就需要將
這段頂點片斷程序獨立出任何的.meterial腳本之外,獨立編寫一個 .program
格式的腳本,在這個腳本中進(jìn)行定義,這樣的話,這個外部定義的頂點片斷程序就會順利的在任何位置上被調(diào)用讀取。
個人推薦所有的頂點程序都獨立為一個腳本,可以更大程度上方便我們整理。
頂點程序本身既可以是一些低級語言,例如vs_1_1語法規(guī)格寫的匯編代碼,也可以是HLSL,GLSL,CG,個人更推薦使用后者。
一個最基本的片斷程序要求有以下幾個要點說明:
vertex_program myVertexProgram asm
{
source myVertexProgram.asm
syntax vs_1_1
}
1:在頭部給出程序名字,之后說明程序類型。“asm”
2:指示出資源來自何處。” source”
3:指示出語法規(guī)則。“vs_1_1”
我們可以通過Ogre的GPU管理器來獲取當(dāng)前顯卡支持的語法列表。
GpuProgramManager::GetSingleton().getSupportedSyntax()來獲得。
一般顯卡支持的語法規(guī)則如下:
vs_1_1
這是一種DirectX頂點渲染器匯編語法。
支持顯卡有:ATI Radeon 8500,nVidia GeForce 3。
vs_2_0
另一種DirectX頂點渲染器匯編語法。
支持顯卡有:ATI Radeon 9600,nVidia GeForce FX 5系列。
vs_2_x
另一種DirectX頂點渲染器匯編語法。
支持顯卡有:ATI Radeon X系列,nVidia GeForce FX 6系列。
vs_3_0
另一種DirectX頂點渲染器匯編語法。
支持顯卡有:nVidia GeForce FX 6系列。
arbvp1
這是OpenGL標(biāo)準(zhǔn)頂點程序匯編格式。大體上相當(dāng)于DirectX vs_1_1。
vp20
這是一種nVidia特有的OpenGL頂點渲染器語法,是vs 1.1的一個超集。
vp30
另一種nVidia特有的OpenGL頂點渲染器語法。它是vs 2.0的一個超集,被nVidia GeForce FX 5系及以上系列支持。
vp40
另一種nVidia特有的OpenGL頂點渲染器語法。它是vs 3.0的一個超集,被nVidia GeForce FX 6系及以上系列支持。
ps_1_1, ps_1_2, ps_1_3
DirectX像素渲染器(例如片斷程序)匯編語法。
支持顯卡:ATI Radeon 8500,nVidia GeForce 3。
注解:對于ATI
8500,9000,9100,9200硬件,也可用于OpenGL。ATI
8500到9200不支持arbfp1但是確實支持OpenGL的atifs擴(kuò)展,非常類似DirectX的ps_1_4。OGRE有針對atifs編譯
器的ps_1_x模塊,當(dāng)在ATI硬件上使用ps_1_x時,它會自動執(zhí)行。
ps_1_4
DirectX像素渲染器(片斷程序)匯編語法。
支持顯卡有:ATI Radeon 8500,nVidia GeForce FX 5系列。
注解:對于ATI
8500,9000,9100,9200硬件,此項也可用于OpenGL。ATI
8500到9200不支持arbfp1但是支持OpenGL的atifs擴(kuò)展,功能上非常類似于DirectX中的ps_1_4。OGRE有針對
atifs編譯器的ps_1_x模塊,當(dāng)在ATI硬件上使用ps_1_x時,它會自動執(zhí)行。
ps_2_0
DirectX像素渲染器(片斷程序)匯編語法。
支持顯卡有:ATI Radeon 9600,nVidia GeForce FX 5系列。
ps_2_x
DirectX像素渲染器(片斷程序)匯編語法。基本上是帶有更多指令的ps_2_0。
支持顯卡有:ATI Radeon X系列,nVidia GeForce FX 6系列。
ps_3_0
DirectX像素渲染器(片斷程序)匯編語法。
支持顯卡有:nVidia GeForce FX 6系列。
ps_3_x
DirectX像素渲染器(片斷程序)匯編語法。
支持顯卡有:nVidia GeForce FX 7系列。
arbfp1
這是OpenGL標(biāo)準(zhǔn)片斷程序匯編格式。大體上相當(dāng)于ps_2_0,意味著不是所有支持DirectX下的基本像素渲染器都支持arbfp1(例如GeForce3和GeForce4就都不支持arbfp1,但是它們都支持ps_1_1)。
fp20
這是一個nVidia特有的OpenGL片斷
程序語法,是ps
1.3的一個超集。它允許你為基本片斷程序使用'nvparse'格式。實際上,它使用NV_texture_shader和
NV_register_combiners在GL下提供相當(dāng)于DirectX's
ps_1_1的功能,但是僅限于nVidia顯卡。然而,因為ATI顯卡比nVidia早一步采用arbfp1,所以它主要用于像GeForce3和
GeForce4系列的nVidia顯卡。你可以在http://developer.nvidia.com/object/nvparse.html找
到更多有關(guān)nvparse的信息。
fp30
另一種nVidia特有的OpenGL片斷渲染語法。它是ps 2.0的一個超集,被nVidia GeForce FX 5系列或更高級的顯卡支持。
fp40
另一種nVidia特有的OpenGL片斷渲染語法。它是ps 3.0的一個超集,被nVidia GeForce FX 6系列或更高級的顯卡支持。
詳細(xì)的語法編寫,實在沒有興趣詳細(xì)研究下去了。所以這里略過,我們需要知道的是,除了HLSL,GLSL,CG以外,還有一個Ogre自動識別處理的類型,unified可以統(tǒng)一的對程序定義,這樣就可以依賴于渲染系統(tǒng)和硬件支持自動的選擇渲染程序。
另外,材質(zhì)拷貝技巧。
一般來說,我們游戲中大量的材質(zhì)是雷同性很強(qiáng)的,假若大段的復(fù)制材質(zhì)渲染模式,實在是非常不值得的體力勞動,所以對于一些只有微小改變的材質(zhì)設(shè)置,推薦使用材質(zhì)拷貝。
材質(zhì)拷貝技巧1:
當(dāng)兩個材質(zhì)完全一致時。直接類似于C++的繼承的寫法即可:
Material met1
{
Technique
{
Pass 0
{ … }
Pass 1
{ … }
}
}
Material met2 : met1
{
}
我們不需要做任何事情,met2就已經(jīng)過去了met1的材質(zhì)屬性。
材質(zhì)拷貝技巧2:
當(dāng)我們向一個拷貝材質(zhì)中添加新技術(shù)時。直接在新的材質(zhì)腳本中聲明新的技術(shù)即可。例:
Material met2 : met1
{
Technique new
{
}
}
此時new這個技術(shù)就會默認(rèn)的在其父類的默認(rèn)命名為0的技術(shù)之后產(chǎn)生。不過值得注意的是,新創(chuàng)建的這個技術(shù)盡量命名,避免與父源類的技術(shù)名稱發(fā)生沖突。
材質(zhì)拷貝技巧3:
當(dāng)我們想對拷貝材質(zhì)已有的屬性做一點點的改動時候,需要聲明原有技術(shù)和通道,直接聲明需要改動的屬性即可。例:
Material met2 : met1
{
Technique 0 // 父類的技術(shù)并沒有命名,默認(rèn)是以索引為名,索引為0,所以這里填0,但是注意的是,一定要把這個0表示說明出來
{
Pass 1 // 父類中的0號技術(shù)中的命名為0的一個通道
{
max_lights 2 //修改該Pass中的最大光源屬性為2
}
}
}
最常用的是修改一個渲染材質(zhì)中的某一個紋理文件。我們可以這么做
Material met2 : met1
{
Technique 0 // 父類的技術(shù)并沒有命名,默認(rèn)是以索引為名,索引為0,所以這里填0,但是注意的是,一定要把這個0表示說明出來
{
Pass 1 // 父類中的0號技術(shù)中的命名為0的一個通道
{
Texture_unit TreeTexture
{
Texture NewTreeTexture.png
}
}
}
}
這樣我們就將treetexture紋理單元中的紋理圖片替換了,而其他的一切渲染屬性都沒有更改。
材質(zhì)拷貝技巧4:
記得我們之前說紋理單元時候有強(qiáng)調(diào)過紋理有一個屬性叫紋理別名吧。texture_alias。
我們看上面的例子,假若我們材質(zhì)met1,和met2僅差一個紋理的區(qū)別的話,那么上面的寫法也比較麻煩,我們有個更簡單的方法,就是,在初次定義的時候,為紋理定義一個別名,之后我們假若需要換紋理,僅告訴Ogre腳本解釋器,別名現(xiàn)在代表另一張紋理便可以了。
例如:我們要渲染一張“漂亮的圖“,在材質(zhì)1中,“漂亮的圖”代表 1.png,材質(zhì)2中,“漂亮的圖”代表2.png,我們只要告訴Ogre,“漂亮的圖”是哪張便可以了。例子如下:
Material met1
{
Pass 0
{
Texture_unit testTex
{
texture_alias DiffuseMap
texture defaultDiff.png
filtering trilinear
tex_coord_set 1
}
}
}
那么我們假若需要使用同樣的技術(shù)和通道,僅修改紋理圖片,我們可以簡單到如下:
Material met2
{
Set_texture_alias DiffuseMap NewChangedDiff.png
}
一句話便更換了別名DiffuseMap所指代的對象。直接達(dá)到更換紋理貼圖的效果。
所以,我們盡量可能的為技術(shù),通道,紋理單元手動設(shè)置名字,紋理資源盡量設(shè)置別名。
合成器Compositor
雖然在Ogre說明書上占了一定篇幅來說明他,很遺憾的是依舊無法理解這個概念名詞,它的作用也很值得斟酌,在現(xiàn)有的資料來看,它的使用率極低,故不再加以研究。暫時,放棄。
粒子腳本
非常熟悉,不贅述。格式完全類似材質(zhì)腳本,僅修改了屬性關(guān)鍵字。
注意的是,Ogre中的粒子腳本中允許設(shè)置一些力學(xué)信息。
字體定義腳本
Ogre中字體最終就是一個Meterial對象,我們要獲得這個對象可以有2種方法:
1:利用一個字體生成工具自己設(shè)計字體紋理
2:讓Ogre生成一個基于trueType字體的字體紋理
無論使用哪種,都需要在 .fontdef 文件中對字體進(jìn)行定義。
當(dāng)我們使用現(xiàn)有的一個字體紋理,那么該腳本聲明格式為:
MyFont // 字體名稱,程序中調(diào)用時使用,自定義
{
Type image // 告知Ogre,我們使用的是字體紋理,不是tureType
Source XXX.png // 字體紋理文件名
Glyph A 1 3 14 14 // 告知Ogre,A這個字符在紋理中的位置是(1,3)到(14,14)之間。
…… // 對我們所需要的每一個字符都進(jìn)行紋理位置的通知
}
從上面可以看出……對中文適用性之低。
當(dāng)我們使用truetype生成一個字體紋理,那么腳本聲明格式為
MyNewFont // 字體名稱,程序中調(diào)用時使用,自定義
{
Type truetype // 告知Ogre我們將從一個字體中生成紋理
Source XXX.ttf // 要加載的. ttf文件名
Size 16 // 生成字體紋理的大小,若過小,則貼到大的面上就顯示很粗糙,若過大,則貼到小的面上就會模糊不清。
Resolution 96 // 每英寸計算的清晰度,一般是72或96
Antialias_colour true // 關(guān)閉默認(rèn)的字體抗鋸齒,這樣的話我們就會在渲染時手動的對字體邊進(jìn)行抗鋸齒處理。該項默認(rèn)為false, 即不使用手動的抗鋸齒,使用Ogre默認(rèn)的抗鋸齒功能。一般,false即可。
Code_pionts 33-166 // 該項是表示哪一段的unicode編碼應(yīng)當(dāng)被生成字體紋理,默認(rèn)是33-166的字符。
}
Overlay覆蓋層腳本
這個的作用重點表現(xiàn)在UI方面了,它就是將3D的按Z軸深度進(jìn)行分割出的層平面,這個腳本默認(rèn)在Root初始化時會自動搜尋所有的
.overlay
層腳本并且裝載分析。當(dāng)然我們也可以手動去加載OverlayManager::GetSingleton().parseAllSource()或者手
動加載單獨一個腳本OverlayManager::GetSingleton().parseSource().
我們看一個樣板式的層腳本
MyNewOverlays // 該層的唯一標(biāo)識命名
{
Zorder 200 // 該層的Z軸深度,越大代表越接近屏幕
Container Panel (MyNewOverlays/FirstPanel) // Container對
應(yīng)的是element,這兩者都是對Panel的修飾詞,當(dāng)該面上有新的子面時就使用Container,若是一個完全無子面的面,則可使用
element進(jìn)行修飾。Panel是注冊過的本面板元素的類型,Ogre提供了三種基本類型Panel,BorderPanel,TextArea. 括號中的是該元素的唯一識別名稱。我們在程序中就可以使用OverlayManager::GetSingleton().getOverlayElement(唯一識別名稱);來獲得此元素的指針。在該句最后我們還可以加入繼承模版,接下來再說。
{
Left 0
Top 0
Width 0.02
Height 0.3
Material ThisPanelMaterial // 這些都是該面板元素的屬性
}
}
這里我們遺留了三個問題:
1:Ogre提供的三個基本元素類型有什么區(qū)別和作用?
2:什么是面版元素繼承的模版,作用有什么?
3:面板元素都有什么屬性有什么作用?
答1:Ogre提供了三個基本表層元素類型。包括Panel,BorderPanel,TextArea。實際上,一般來說,這三種是完全不夠的,是需要我們進(jìn)行擴(kuò)展的。擴(kuò)展后的類型擁有獨特的功能和屬性。
例如:
Panel 面版
它就是一個矩形的區(qū)域,重點作用就是做一個其他元素的容器。所以一般來說,它更多時候是沒有背景的透明的。他的專有屬性有:
Transparent true / false 是否透明,若為true則代表本面板透明,自己是不參與渲染的。
Tiling 0 1 2 實現(xiàn)多重貼圖。本例說明使用第0層材質(zhì)紋理在面板上X軸方向重復(fù)貼一次,Y軸方向上重復(fù)貼兩次。
Uv_coords topleft_u topleft_v bottomright_u bottomright_v 設(shè)置這個面版上的紋理UV坐標(biāo)。
這三個屬性是Panel專屬的,這意味著其他的表層元素是不具有這些功能和屬性的。
BorderPanel邊框面版
它和Panel區(qū)別僅有一個,就是多個一套邊框。這個邊框會隨著BorderPanel的大小自動的調(diào)節(jié)其紋理大小。它的構(gòu)成由9部分:一個中心區(qū),4個角,4個邊。它的專屬屬性是
Border_size left right top bottom 邊框按屏幕大小的比例尺寸。我們可以發(fā)現(xiàn)到Ogre在記錄UI大小時是很喜歡記錄UI與屏幕長度之間的比例,而非實際的象素大小。這樣做的好處是,當(dāng)屏幕大小有變換時,是很容易實現(xiàn)縮放功能的。
Border_material materialName 因為邊框面板有獨特的邊框,所以,我們需要對它指示出其邊框使用的材質(zhì)紋理。
Border_topleft_uv topleft_U uv_topleft_V buttomRight_U buttomRight_V
Border_top_uv topleft_U uv_topleft_V buttomRight_U buttomRight_V
…… 總共八塊邊緣都需要指定其UV信息。這里我們需要注意,我們美術(shù)資源制作時,要求左右兩邊的材質(zhì)紋理應(yīng)該允許被垂直拉伸,上下兩塊的材質(zhì)紋理應(yīng)該允許被水平拉伸。
TextArea文本區(qū)
用來渲染文本的一個表層元素。它轉(zhuǎn)有屬性包括:
Font_name name 要使用的渲染字體名,我們必須保證這個字體在 .fontdef 里面并且可用。
Char_height 字母高度占用整個屏幕告訴的百分比。
Colour RGB 渲染字體的顏色,默認(rèn)是使用一般的黑白字體。RGB是0.0-1.0之間的浮點數(shù)。
Colour_bottom RGB / colour_top RGB 實現(xiàn)文本從上到下的顏色漸變。
答2:
模板實際上就是類似于材質(zhì)拷貝時的那個父類,實際作用是當(dāng)幾個比較類似屬性的表層元素,我們可以直接定義一個模板,其他元素繼承于該模板就節(jié)約了一些復(fù)制粘貼的操作而已。
我們看下例:
Template container BordPanel ( MyTemplate/BasicBorderPanel ) // template表示該P(yáng)anle是模板面版,本身它是不進(jìn)行渲染的,類似于C++的抽象父類,制定一套屬性樣版提供其他渲染面板直接套用使用。Container也是Panel的一個屬性,表明它是允許有子表層元素的。后面括號里是模板面板名稱。
{
Left 0
……
Material MyPanelMaterialName
Border_size 0.05 0.05 0.06 0.06
Border_material MyBorderPanelMaterialName
……
}
Template container Button (MyTemplate/BasicButton) : MyTemplate/BasicBorderPanel
// 表明該Button是上面的層的子層,Button是開發(fā)人員注冊的一個層元素類型
{
Font_name BlackStyle
Char_height 0.09
Color_top 1 1 0
Color_bottom 1 0.5 0.5
}
上面定義了一套模板邊框面和一套模板按鈕,下面我們將對其實現(xiàn)
MyOverlays // 層名稱
{
Zorder 490 // 層深度
Container BorderPanel (ChatBackPanel ) : MyTemplate/BasicBorderPanel // 實現(xiàn)一個進(jìn)行渲染的背景面層元素,它套用模板邊框面
{
Container Button (JionButton) : MyTemplate/BasicButton // 實現(xiàn)一個進(jìn)行渲染的按鈕,它套用模板按鈕的各項屬性
{
Left 0.8
Top 0.4
}
Container Button (ExitButton) : MyTemplate/BasicButton // 實現(xiàn)另一個進(jìn)行渲染的按鈕,它套用模板按鈕的各項屬性
{
Left 0.6
Top 0.4
}
}
}
這樣,我們就得到了一個渲染出來的邊框面板和上面的兩個按鈕,我們新創(chuàng)建的按鈕就可以省去很多屬性的設(shè)置了,僅對部分獨特的屬性進(jìn)行設(shè)置即可。
可見,模板的作用和抽象Pass通道,技術(shù),紋理單元 是一樣的作用,減少我們屬性設(shè)置而創(chuàng)建的。
答3:
層元素屬性是對層的各項渲染指數(shù)進(jìn)行調(diào)整的東西。我們也看到了,不同的元素因功能特性不同,會有獨特的屬性,但下列通用屬性是每個元素必須有的:
Metrics_mode pixels / relative
屬性參數(shù)解釋方式。默認(rèn)是relative相對模式,這就意味著之后我們設(shè)置top 0.8
代表著這個0.8是針對屏幕寬高得到的比例值。若我們設(shè)置為pixels則代表我們設(shè)置 top 8
是從第8個象素開始的,是一個絕對的象素偏移量。顯而易見,我們再設(shè)置為top 0.8 這樣明顯是不合理的了。
默認(rèn)該項為 metrics_mode relative
Horz_align left/center/right 設(shè)置此元素水平起點位置。例如,horz_align left 則代表本元素會自動的居左對齊,當(dāng)然我們再設(shè)置left xxx可以再次對其位置進(jìn)行調(diào)整。
默認(rèn)該項為 horz_align left
Vert_align top/center.button 同上不再解釋。
默認(rèn)該項為 vert_align top
Left 0.3 設(shè)置元素相對于它上一層的水平位置。后面的參數(shù)跟metrics_mode屬性參數(shù)解釋方式掛鉤。
默認(rèn)該項為 left 0
Top 同上不再解釋。
默認(rèn)該項為 top 0
Width 0.2 設(shè)置元素大小。這里0.2是針對整個屏幕的大小而言,并非針對其父元素的大小。所以當(dāng)我們設(shè)置width 0.5時則意味著這個元素會占屏幕的一半寬。
默認(rèn)該項為 width 1
Height 同上不再解釋
默認(rèn)該項為height 1
Material XXX 設(shè)置該層元素使用的基本材質(zhì)。值得注意的是:一個表層元素的材質(zhì)會默認(rèn)的
禁止其上材質(zhì)的光照和深度檢測。所以,我們不應(yīng)當(dāng)在表層上使用與3D物體相同的材質(zhì)。另外,該項在不同的元素中解釋意義也是不同的,在Panel中他是整
個面版的背景材質(zhì),但是在BorderPanel中它僅僅是中心區(qū)域的材質(zhì)。
Caption XXX 設(shè)置該層元素的標(biāo)題。因為部分元素是沒有標(biāo)題屬性的,所以有些元素可以忽略掉該元素。
Rotation 30 0 0 1 設(shè)置該層的旋轉(zhuǎn)角度,第一個參數(shù)是旋轉(zhuǎn)的角度,第2,3,4屬性分別表示在x,y,z軸的旋轉(zhuǎn)。本例就說明是該層元素需要圍繞z軸旋轉(zhuǎn)30度。
4:Mesh網(wǎng)格工具
Ogre自帶的網(wǎng)格工具包括三種:
1:導(dǎo)出器Exporters 用于從繪圖軟件中導(dǎo)出固定格式的數(shù)據(jù)提供Ogre使用
Ogre這個導(dǎo)出插件能夠?qū)С鰞蓚€文件,一個 .mesh 結(jié)尾的網(wǎng)格模型,一個是 .skeleton 后綴的骨骼模型。值得注意的是,當(dāng)我們需要創(chuàng)建一個模型動畫時候請注意:
·每個頂點必須沒有超過4的加權(quán)骨骼賦值。
·所有的頂點都必須被分配到至少一個骨骼點上,靜態(tài)頂點就分配到根部骨骼點上
·動畫開始和結(jié)束時候每個骨骼點上最少要有一個關(guān)鍵楨
2:Xml轉(zhuǎn)換器 能夠?qū)ml格式的數(shù)據(jù)轉(zhuǎn)換為Mesh數(shù)據(jù)和骨骼數(shù)據(jù)
·因為很多模型工具導(dǎo)出的Mesh都是xml格式的,這時使用該轉(zhuǎn)換器就可以直接將 xml格式的mesh網(wǎng)格轉(zhuǎn)換為 .mesh 文件。其中的語法非常簡單。
格式為: OgreXMLConverter 文件名
這樣就可以了。不過在轉(zhuǎn)換時,你可以有一次機(jī)會對Mesh中的Lod信息進(jìn)行處理。
3:Mesh網(wǎng)格更新器 能夠?qū)W(wǎng)格的數(shù)據(jù)進(jìn)行更新修改功能。
未能順利使用。故不做介紹。
5:硬件緩沖區(qū)(硬件緩存)
·定義
實際上這個緩沖區(qū)就是一塊malloc出來的存儲區(qū)域,不過它不如malloc是在內(nèi)存中申請的區(qū)域,而這個緩沖區(qū)是在gpu/agp中,它的寫讀速度更快。通常硬件緩沖區(qū)作用有拿來做頂點緩沖區(qū),索引緩沖區(qū),和象素緩沖區(qū)。
·使用
硬件緩沖區(qū)的管理是交由一個硬件緩存管理器負(fù)責(zé)的HardwareBufferManager,他負(fù)責(zé)緩沖區(qū)的創(chuàng)建和釋放,它是幾何體創(chuàng)建工廠,單鍵在Root初始化時就會被創(chuàng)建,所以,當(dāng)我們需要一塊內(nèi)存的時候,一定不要直接New或malloc操作,而應(yīng)當(dāng)是這樣
VerBuf = HardwareBufferManager::GetSingleton().CreateVertexBuffer()
·類型
我們在分配一塊硬件緩沖區(qū)時,需要傳一個參數(shù),來指明這塊緩沖區(qū)的類型,是否需要頻繁讀寫?這樣對底層的硬件緩存區(qū)域分配管理提供很大的便利。我們來看一下硬件緩沖區(qū)的類型有哪些,我們分配它的時候應(yīng)該做何選擇。(HBU是HarewareBufferUsage簡寫)
HBU_STATIC 靜態(tài)硬件緩沖區(qū),它意味著我們很少寫入更新緩沖區(qū),偶爾會從中進(jìn)行數(shù)據(jù)讀取。
HBU_STATIC_WRITE_ONLY 只寫靜態(tài)硬件緩沖區(qū)。它意味著我們很少更新緩沖區(qū),并且絕對不從該緩沖區(qū)進(jìn)行數(shù)據(jù)讀取。但是,當(dāng)我們創(chuàng)建了一個備份緩沖的話,我們依舊可以對其讀取。
HBU_DYNAMIC 動態(tài)硬件緩沖區(qū)。它意味著我們會經(jīng)常性的更新緩沖區(qū)中的數(shù)據(jù),并且也希望能從其中讀取數(shù)據(jù),這一個效率最低的緩沖區(qū)使用方法。
HBU_DYNAMIC_WRITE_ONLY 只寫動態(tài)硬件緩沖區(qū),這個是個只許寫入的硬件緩沖區(qū),但當(dāng)我們創(chuàng)建了一個備份緩沖的話,還是允許讀取的。
HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE 這個參數(shù)指明這個硬件緩沖區(qū)是一個需要頻繁更新的緩沖區(qū),大多數(shù)是每楨更新的數(shù)據(jù)存放在這里。但是需要注意的是,向該數(shù)據(jù)緩沖寫入數(shù)據(jù)時記得加緩存鎖。
建議:多使用WRITE_ONLY為后綴的緩沖區(qū)類型。即使必須進(jìn)行讀取,也建議使用備份緩沖,而非時刻可寫的緩沖。
·備份緩沖
當(dāng)我們創(chuàng)建一個WRITE_ONLY的硬件緩沖區(qū)后,我們有些時候假若非要從中讀取數(shù)
據(jù),我們可以在創(chuàng)建緩沖區(qū)時傳參,這樣我們在內(nèi)存中就會創(chuàng)建一個備份的緩沖區(qū)。每當(dāng)我們向顯存中寫入一份數(shù)據(jù)的時候,Ogre會自動的先將這份數(shù)據(jù)拷貝到
內(nèi)存緩沖區(qū)后,再將其更新到顯存中的硬件緩沖區(qū)。當(dāng)然,這個技術(shù)會帶來更多的開銷,所以,非必要時不要用它。
·緩存鎖
當(dāng)我們更新寫入緩沖或者在讀取緩沖的時候,都應(yīng)該先“鎖”住它,以免它被修改。當(dāng)然,
之后記得解鎖。pBuffer->Lock(begin , length ,
lockType)一般來說,鎖的范圍越小越便捷快速。但是鎖的類型lockType也可以對讀取的效率產(chǎn)生影響。
鎖的類型包括:
·HBL_NORMAL 這種鎖支持從緩沖區(qū)讀取數(shù)據(jù),但是效率很低下,因為它允許我們從硬件緩沖區(qū)進(jìn)行數(shù)據(jù)讀取。但是,當(dāng)我們使用備份緩沖的話,這種影響會得到一些改善。
·HBL_READ_ONLY 這種鎖意味著我們只能從緩沖區(qū)中進(jìn)行內(nèi)容的讀取,禁止寫入。此時建議我們使用備份緩沖,會提高我們效率。而且,此時我們實際上讀取到的并非硬件緩沖區(qū),而是內(nèi)存中的數(shù)據(jù)。
·HBL_DISCARD
這種鎖意味著我們每次操作都會將硬件緩沖區(qū)中的所有內(nèi)容丟棄,一般這種操作也是會在每楨都處理的環(huán)境下才會使用,它是禁止讀出的。但是一旦我們?nèi)绱寺暶鳎?
也就基本上是向引擎宣稱我們不會對硬件緩沖區(qū)的內(nèi)容感興趣,那么就不應(yīng)當(dāng)創(chuàng)建備份緩沖區(qū)。在我們沒有使用備份緩沖區(qū)時盡量使用這種鎖,它的效率很高,但若
有了內(nèi)存?zhèn)浞菥彌_區(qū)的話,它就沒有必要了。
·HBL_NO_OVERWRITE 當(dāng)我們有些時候需要更新部分緩沖區(qū)而非全部緩沖區(qū)時,使用HBL_DISCARD就顯的不適合了。此時我們就需要使用這種鎖了,它的效率依舊很高,但是也僅是沒有備份緩沖的時候才有作用。
·硬件緩沖區(qū)和緩沖鎖使用經(jīng)驗
1:因為最快最優(yōu)秀的緩沖自然是通過 HBU_STATIC_WRITE_ONLY類型創(chuàng)建,不創(chuàng)建備份緩存,并且僅進(jìn)行一次HBL_DISCARD的鎖操作永不再額外處理的緩沖。
2:當(dāng)我們需要頻繁更新的緩沖,可以用HBU_DYNAMIC_WRITE_ONLY來創(chuàng)建,不創(chuàng)建備份緩存,之后使用HBL_DISCARD加鎖,若不想全部更新,則使用HBL_NO_OVERWRITE進(jìn)行鎖操作。
3:若我們必須從緩沖區(qū)中讀取數(shù)據(jù)的話,那么我們可以創(chuàng)建一個備份緩沖,用HBL_READ_ONLY將其鎖住。可能的話,盡量聲明緩沖區(qū)為靜態(tài)的。
4:在我們對頂點的不同元素需要使用不同模式的時候,我們不要通過指針大量更新緩沖區(qū)的全部頂點結(jié)
構(gòu),應(yīng)該分塊更新。例如,我們假設(shè)只需要經(jīng)常更新紋理坐標(biāo)信息,那么我們應(yīng)當(dāng)將紋理坐標(biāo)信息保存在一個單獨的緩沖區(qū)區(qū)域,而其他的不經(jīng)常更新的元素拆分保
存在HBU_STATIC_WRITE_ONLY緩沖區(qū)中。
·頂點緩沖區(qū)
VertexData中有幾個重要成員:
·VertexStart 頂點起始位置信息
·VertexCount 頂點個數(shù)
·VertexDeclaration 一個指向頂點數(shù)據(jù)個數(shù)的指針
·VertexBufferBinding 一個指向頂點緩沖區(qū)綁定的指針
其中頂點類型描述中我們需要強(qiáng)調(diào)一個順序問題,為了支持DX9以前的版本,我們有必要按如下順序聲明和數(shù)據(jù)保存:
1:頂點位置信息
2:頂點綁定權(quán)重
3:頂點法線信息
4:頂點環(huán)境光顏色信息
5:頂點鏡面光顏色信息
6:頂點紋理坐標(biāo)信息
除了上面的順序需要注意以外,我們還需要注意的是頂點緩沖區(qū)中,是絕對不允許有空隙存在的。
我們創(chuàng)建了一個頂點緩沖區(qū)后,我們還需要將起和指定的資源進(jìn)行綁定。
格式如下 verterBufferBinding->setBinding(0, vertexBuffer);
之后,我們在運(yùn)行時將頂點緩沖區(qū)綁定起來,循環(huán)的將其信息更新填充進(jìn)入,Ogre提供了臨接點與點之間的間隔長度和起始點信息,以便我們進(jìn)行數(shù)據(jù)更新。
·索引緩沖區(qū)
與頂點緩沖區(qū)基本都是一致的。創(chuàng)建后更新。唯一的區(qū)別就是創(chuàng)建時有些屬性不同而已。
·象素緩沖區(qū)
這里是保存紋理象素信息的。但是和頂點緩沖和索引緩沖不同的是,我們不能手動創(chuàng)建象素緩沖區(qū),只有在我們創(chuàng)建一個紋理的時候,象素緩沖會自動被創(chuàng)建出來。
象素緩沖區(qū)中支持的紋理類型:
TEX_TYPE_1D 一維的紋理,通過1D紋理坐標(biāo)來索引
TEX_TYPE_2D 二維的紋理,通過2D文理坐標(biāo)來索引
TEX_TYPE_3D 三維的紋理,通過3D文理坐標(biāo)來索引
TEX_TYPE_CUBE_MAP 一個立方體的六個表面紋理,通過3D紋理進(jìn)行索引。
象素緩沖區(qū)的內(nèi)存分配格式
Ogre中的圖象數(shù)據(jù)的信息都被封裝在一個
個的PixelBox對象之中,我們需要注意的是PixelBox本身是保存在GPU中,但是真正的紋理都是保存在內(nèi)存中,并非讀到GPU中。GPU中的
PixelBox保存著內(nèi)存中象素的格式位置內(nèi)容信息的描述,但是PixelBox并沒有內(nèi)存管理的功能,它只能通過保存的內(nèi)存指針來操作數(shù)據(jù)。象素盒中
提供了通過深度,高度,寬度來索引象素的方法,若一維紋理沒有高度和深度時,就將其參數(shù)補(bǔ)1。如下:(width, 1,
1),二維的紋理(width, height, 1)
象素緩沖區(qū)的更新
Ogre提供了兩種更新象素緩沖區(qū)的方法。
1:手動建立一個紋理并將一個圖片放入這個紋
理中。我們可以如下代碼Image img; img.load(“xxx.jpg”, “General”); Texture pTex =
Texture::getSingleton().createManual( …. );
pTex->GetBuffer(0,0)->blitFromMemory( );
2:對一個象素緩沖區(qū)加鎖之后對其進(jìn)行讀取和寫入。
Buffer->Lock(HarewareBuffer::HBL_DISCARD);
const PixelBox &pb = buffer->getCurrentLock(); // 鎖好了之后進(jìn)行處理
for (int I = 0; I < pb.GetWindth(); ++I)
{
For( int j = 0; j < GetHeight(); ++j)
{
Static_cast<unit32*>(pb.data) // 數(shù)據(jù)獲得,隨便處理
}
}
Buffer->unlock(); //最后記得解鎖。
6:外部紋理源
·定義。
我們讀取一個紋理,通常是從一個.jpg.png.bmp等格式的圖形文件中進(jìn)行讀取,但有些時候我們需要從avi.mpeg等電影格式文件,flv文件,實時渲染產(chǎn)生的來源中讀取紋理,這些渠道來源就被稱為外部紋理源。
·處理外部紋理源。
我們?nèi)绾翁幚硗獠考y理源?本身Ogre是沒有寫的。不過它提供了方法的接口,以便我們寫出需要的插件。
·外部紋理源插件編寫方法
我們構(gòu)建的插件必須繼承于ExternalTextureSource類。它提供了一個通用的框架。
另外,當(dāng)我們開始需要獲取外部紋理源的時候可以使用ExternalTextureSourceManager類中的函數(shù)來獲得。典型的函數(shù)可以如
下:AdvanceTextureManager::GetSingleton().GetCurrentPlugIn()
->CreateDefinedTexture(sMaterialName);
·外部紋理源腳本
Material Example/MyVideoExample
{
Technique
{
Pass
{
Texture_unit
{
Texture_source video
{
Filename MyMovie.avi
Play_mode play
Sound_mode Off // 注意:這些屬性根據(jù)插件不同而且不同
}
}
}
}
}
7:陰影
·啟動陰影
1:默認(rèn)時陰影是被關(guān)閉的。我們要使用陰影就必須使陰影有效,而這個操作必須極其優(yōu)先處理,因為,是否開啟陰影會影響模型讀取的方式。如:
M_SceneMgr->SetShadowTechnique( SHADOWTYPE_STENCIL_ADDITIVE ); //開啟一個模板陰影。
2:關(guān)閉部分不支持投射陰影的光源。(有些光源并不支持投影)
Light::SetCastsShadow(false)
3:關(guān)閉那些不需要投射陰影的物體。(有些透明物體可能不需要投影)
MovableObject::SetCastsShadow(false)
4:設(shè)置投影的最遠(yuǎn)距離。(為了性能考慮,需要設(shè)置)
5:關(guān)閉那些不需要接受陰影的物體。(透明材質(zhì),自發(fā)光材質(zhì)通常是不能接收投影的)
Material::SetReciveShadow(false )
8:動畫
Ogre默認(rèn)支持四種腳本動畫。
1) 骨骼動畫。使用骨骼結(jié)構(gòu)來定義網(wǎng)格數(shù)據(jù)。
a) Ogre的骨骼和動畫信息被保存在 .skeleton 的腳本文件中。
b) 我們進(jìn)行動畫操作時,需要創(chuàng)建一個叫動畫狀態(tài)的對象來控制該動畫的狀態(tài)。我們可以通過Entity::getAnimationState()來獲得一個指向動畫狀態(tài)的指針,之后我們在frameStarted時間中,通過動畫狀態(tài)指針來進(jìn)行動畫更新。
2) 頂點動畫。保存頂點快照來決定網(wǎng)格數(shù)據(jù)如何改變。
3) 場景節(jié)點動畫。按照預(yù)先定義的路徑,來操作場景節(jié)點上掛接的實體進(jìn)行移動產(chǎn)生動畫。
a) 我們可以為每個SceneNode創(chuàng)建一個對應(yīng)的NodeAnimationTrack
4) 數(shù)值動畫。使用Ogre的接口類AnimableObject來繼承擴(kuò)展。這樣就可以自定義其對象屬性。