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

麒麟子

~~

導(dǎo)航

<2009年5月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

統(tǒng)計(jì)

常用鏈接

留言簿(12)

隨筆分類

隨筆檔案

Friends

WebSites

積分與排名

最新隨筆

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

OGRE主要渲染流程簡(jiǎn)介

OGRE主要渲染流程簡(jiǎn)介

                                    謝偉亮       feiyurainy@163.com

                               轉(zhuǎn)載請(qǐng)注明出處

    很早以前就想寫一些關(guān)于OGRE的文章了,一直沒機(jī)會(huì)。

    理解一個(gè)渲染引擎,我覺得最重要的是先抓住了它的主架構(gòu),它的主線,渲染流程,不然的話,一個(gè)引擎幾萬行,甚至幾十萬行的代碼,光是打開solution就能嚇你一跳了,OGRE也有十幾萬行的代碼量,我一開始看它的時(shí)候也是無從下手,感覺代碼太多了,不知道從哪開始看好,這個(gè)class看看,那個(gè)class看看,由于對(duì)整個(gè)引擎沒有一個(gè)清晰的認(rèn)識(shí),看過了也印象不深,所以,最后,還是決定先找出它的主線,了解它的渲染流程,這樣才能有機(jī)地把各個(gè)部分聯(lián)系起來。

    這篇短文也是對(duì)OGRE的主要渲染流程的一個(gè)介紹,可能對(duì)一些class不會(huì)太多地去介紹具體的實(shí)現(xiàn)細(xì)節(jié)。我所用的代碼都是取自于OGRE的最新的CVS版本。

    讀者最好對(duì)OGRE有一定的了解,至少得看懂它的example,不然可能一些東西理解起來比較困難。對(duì)D3DOPENGL有一定了解更好。

    如果你看過D3D SDK中帶的例子,你一定知道一個(gè)比較簡(jiǎn)單的3D程序要運(yùn)行起來,至少都會(huì)涉及以下的幾部分:

    首先是數(shù)據(jù)的來源,包括頂點(diǎn)數(shù)據(jù),紋理數(shù)據(jù)等,這些數(shù)據(jù)可以從文件中讀取,也可以在程序運(yùn)行時(shí)生成。

    接下來,我們會(huì)建立頂點(diǎn)緩沖區(qū)把頂點(diǎn)保存起來,建立texture對(duì)象來表示texture,對(duì)頂點(diǎn)組成的物體設(shè)置它在世界坐標(biāo)系下的坐標(biāo),設(shè)置攝像機(jī)的位置,視點(diǎn),設(shè)置viewport的位置和大小,然后就可以在渲染循環(huán)中開始調(diào)用渲染操作了,經(jīng)過了front bufferback buffer的交換,我們就能在屏幕上看到3D圖形了,偽代碼如下:

      setupVertexBuffer

      setWorldTransform

      setCamera

      setProjectionTransform

      setViewport

       beginFrame

      setTexture

      drawObject

      endFrame 

     以下就是渲染一個(gè)物體的主要步驟,在我看來,這就是3D程序的主線,同樣道理,無論你多復(fù)雜的渲染引擎,都得實(shí)現(xiàn)上述的這些步驟,其他的一些效果如陰影,光照等,都是附著在這條主線上的,所以,如果你能在你所研究的渲染引擎上也清晰地看到這條主線,可能對(duì)你深入地研究它會(huì)大有幫助,下面,我們就一起來找到OGRE中的這條主線。

     OGRE的渲染循環(huán)都是起源于Root::renderOneFrame,這個(gè)函數(shù)在OGRE自帶的example中是不會(huì)顯式調(diào)用的,因?yàn)?/span>example都調(diào)用了Root::startRendering,由startRendering來調(diào)用renderOneFrame,如果你用OGRE來寫真正的游戲,或者編輯器,你可能就需要在的消息主循環(huán)中調(diào)用renderOneFrame了,顧名思義,這個(gè)函數(shù)就是對(duì)整個(gè)OGRE進(jìn)行一幀的更新,包括動(dòng)畫,渲染狀態(tài)的改變,渲染api的調(diào)用等,在這個(gè)函數(shù)中,會(huì)包括了我們上述偽代碼的幾乎全部?jī)?nèi)容,所以是本文的重點(diǎn)所在。

     進(jìn)入renderOneFrame,可以看到頭尾兩個(gè)fire函數(shù),這種函數(shù)在OGRE中經(jīng)常出現(xiàn),一般都是fire…startfire…end一起出現(xiàn)的,在這些函數(shù)中,可能會(huì)處理一些用戶自定義的操作,如_fireFrameStarted就會(huì)對(duì)所以的frameListener進(jìn)行處理,這些fire函數(shù)可以暫時(shí)不用理會(huì),繼續(xù)看_updateAllRenderTargets,在這個(gè)函數(shù)中,會(huì)委派當(dāng)前所用的renderer對(duì)所有創(chuàng)建出來的render target進(jìn)行updaterender target也就是渲染的目的地,一般會(huì)有兩種,一種是render texture,一種是render buffer,接著進(jìn)入RenderSystem::_updateAllRenderTargets,可以看到在render system中,對(duì)創(chuàng)建出來的render target是用RenderTargetPriorityMap來保存的,以便按照一定的順序來對(duì)render target進(jìn)行update,因?yàn)樵阡秩疚矬w到render buffer時(shí),一般會(huì)用到之前渲染好的render texture,所以render texture形式的render target需要在render buffer之前進(jìn)行更新。

     進(jìn)入render targetupdate,可以看到,它仍然把update操作繼續(xù)傳遞下去,調(diào)用所有掛在這個(gè)render target上的viewportupdate

     Viewport其實(shí)就是定義了render target上的一塊要進(jìn)行更新的區(qū)域,所以一個(gè)render target是可以掛多個(gè)viewport的,以實(shí)現(xiàn)多人對(duì)戰(zhàn)時(shí)分屏,或者是畫中畫等效果,可以把OGRE中的viewport看成是保存camerarendertarget這兩者的組合,把viewport中所定義的camera所看到的場(chǎng)景內(nèi)容渲染到viewport所定義的render target的區(qū)域里。

     Viewport還有一個(gè)重要信息是ZOrder,可以看到RenderTarget中的ViewportList帶有一個(gè)比較函數(shù),所以在RenderTarget::update中,ZOrder越小的,越先被渲染,所以,如果兩個(gè)viewport所定義的區(qū)域互相重疊了,而且ZOrder又不一樣,最終的效果就是ZOrder小的viewport的內(nèi)容會(huì)被ZOrder大的viewport的內(nèi)容所覆蓋。

     繼續(xù)進(jìn)入Viewport::update,就像前面所說,它調(diào)用它所引用的camera來渲染整個(gè)場(chǎng)景,而在Camera::_renderScene中,是調(diào)用SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays)SceneManager::_renderScene里就是具體的渲染流程了。從函數(shù)名稱還有參數(shù)也可以看出來,這個(gè)函數(shù)的作用就是利用所指定的cameraviewport,來把場(chǎng)景中的內(nèi)容渲染到viewport所指定的render target的某塊區(qū)域中。根據(jù)camera,我們可以定出view matrixprojection matrix,還可以進(jìn)行視錐剔除,只渲染看得見的物體。注意,我們這里只看標(biāo)準(zhǔn)的SceneManager的方法,不看BspSceneManager派生類的方法,而且,我們會(huì)拋開跟主線無關(guān)的內(nèi)容,如對(duì)shadowsetup,骨骼動(dòng)畫的播放,shader參數(shù)的傳遞等,因?yàn)槲覀冎蛔⒅劁秩镜闹髁鞒獭?/span>

     在SceneManager::_renderScene中所應(yīng)看的第一個(gè)重要函數(shù)是_updateSceneGraphOGRE對(duì)場(chǎng)景的組織是通過節(jié)點(diǎn)樹來組織的,一個(gè)節(jié)點(diǎn),你可以看成是空間中的某些變換的組合,如位置,縮放,旋轉(zhuǎn)等,這些變換,會(huì)作用到掛接在這些節(jié)點(diǎn)上的具體的物體的信息,也就是說,節(jié)點(diǎn)保存了world transform,對(duì)具體的物體,如一個(gè)人,在空間中的定位,都是通過操作節(jié)點(diǎn)來完成的。同時(shí)節(jié)點(diǎn)還保存了一個(gè)世界坐標(biāo)的AABB,這個(gè)AABB能容納所有它所掛接的物體的大小,主要是用于視錐裁減的,如果當(dāng)前攝像機(jī)看不見某個(gè)節(jié)點(diǎn)的AABB,那么說明攝像機(jī)看不見節(jié)點(diǎn)所掛接的所有物體,所以在渲染時(shí)可以對(duì)這個(gè)節(jié)點(diǎn)視而不見。

     _updateSceneGraph的內(nèi)部處理比較繁瑣,我們只需知道,經(jīng)過了_updateSceneGraph,場(chǎng)景節(jié)點(diǎn)樹中的每個(gè)節(jié)點(diǎn)都經(jīng)過了更新,包括位置,縮放,和方位,還有節(jié)點(diǎn)的包圍盒。

     繼續(xù)回到SceneManager::_renderScene,接下來要看的是setViewport,它會(huì)調(diào)用具體的renderersetviewport的操作,設(shè)置viewport中所掛接的render target為當(dāng)前所要渲染的目標(biāo),viewport中的區(qū)域?yàn)楫?dāng)前所要渲染的目標(biāo)中的區(qū)域。

     接下來要碰到OGRE渲染流程中的一個(gè)重要的概念,Render Queue。這個(gè)東西實(shí)在內(nèi)容比較多,還是以后有機(jī)會(huì)單獨(dú)提出來說吧,你可以簡(jiǎn)單把它想成是一個(gè)容器,里面的元素就是renderable,每個(gè)renderable可以看成是每次調(diào)用drawprimitive函數(shù)所渲染的物體,可以是一個(gè)模型,也可以是模型的一部分。在RenderQueue中,它會(huì)按材質(zhì)來分組這些renderable,還會(huì)對(duì)renderable進(jìn)行排序。

     在每一次調(diào)用SceneManager::_renderScene時(shí),都會(huì)調(diào)用SceneManager::prepareRenderQueue來清理RenderQueue,然后再調(diào)用SceneManager::__findVisibleObjects來把當(dāng)前攝像機(jī)所能看見的物體都加入到RenderQueue中。

     SceneManager::__findVisibleObjects是一個(gè)遞歸的處理過程,它從場(chǎng)景的根節(jié)點(diǎn)開始,先檢查攝像機(jī)是否能看見這個(gè)節(jié)點(diǎn)的包圍盒(包圍盒在_updateSceneGraph時(shí)已經(jīng)計(jì)算好了),如果看不見,那么這個(gè)節(jié)點(diǎn),還有它的子節(jié)點(diǎn)都不用管了。如果能看見,再檢測(cè)掛在這個(gè)節(jié)點(diǎn)上的所有MovableObject,如果當(dāng)前所檢測(cè)的MovableObject是可見的,就會(huì)調(diào)用它的_updateRenderQueue方法,一般在這個(gè)方法里就可以把和這個(gè)MovableObject相關(guān)的renderable送入RenderQueue了。

     這里要說說MovableObjectMovableObject主要是用于表示場(chǎng)景中離散的物體,如Entity,顧名思義,能移動(dòng)的物體,不過它的“能移動(dòng)”這個(gè)能力是要通過SceneNode來實(shí)現(xiàn)的,所以MovableObject來能顯示出來,首先得先掛接在某個(gè)場(chǎng)景節(jié)點(diǎn)上,通過場(chǎng)景節(jié)點(diǎn)來定位。你可以控制MovableObject的一些屬性,如某個(gè)MovableObject是否要顯示,是否要隱藏,都可以通過MovableObject::setVisible方法來實(shí)現(xiàn)。

     檢測(cè)完該節(jié)點(diǎn)上的MovableObject之后,就繼續(xù)調(diào)用所有子節(jié)點(diǎn)的_findVisibleObjects方法,一直遞歸下去。這樣,就能把場(chǎng)景中所有要渲染的renderable所加入到RenderQueue中了。

     至此,我們就擁有了要渲染的物體的信息了,接下來就是對(duì)這些物體進(jìn)行渲染了,你會(huì)發(fā)現(xiàn)跟D3DOpenGL的代碼很類似的調(diào)用:

       mDestRenderSystem->clearFrameBuffer

      mDestRenderSystem->_beginFrame   

       mDestRenderSystem->_setProjectionMatrix

       mDestRenderSystem->_setViewMatrix

       _renderVisibleObjects();

      mDestRenderSystem->_endFrame();

     這些api的作用和D3D中的類似調(diào)用的作用都差不多,這里再說一下_renderVisibleObjects(),在這個(gè)函數(shù)中,會(huì)對(duì)RenderQueue中的每個(gè)renderable進(jìn)行渲染,用的是visitor模式來遍歷操作每個(gè)renderable,最終在SceneManager::renderSingleObject中取出每個(gè)renderable所保存的頂點(diǎn),索引,世界矩陣等信息,來進(jìn)行渲染。這其中還包括了查找離該renderable最近的光源等操作,比較復(fù)雜。

     到這里,SceneManager::_renderScene的流程基本走完了,也就是說,OGRE一幀中的渲染流程差不多也結(jié)束了,你應(yīng)該也發(fā)現(xiàn),這個(gè)流程跟你用D3D寫一個(gè)簡(jiǎn)單程序的流程基本是一樣的,在這個(gè)流程的基礎(chǔ)上,再去看具體的實(shí)現(xiàn),如怎么樣設(shè)置紋理,怎么樣調(diào)用你熟悉的D3DOpenGLAPI來渲染物體,應(yīng)該會(huì)簡(jiǎn)單得多。

     對(duì)OGRE的渲染流程的大概介紹到這里也結(jié)束了,很多細(xì)節(jié)都沒涉及,以后有機(jī)會(huì)再寫吧。

posted on 2009-05-17 23:56 麒麟子 閱讀(906) 評(píng)論(1)  編輯 收藏 引用 所屬分類: Game and Engine

評(píng)論

# re: OGRE主要渲染流程簡(jiǎn)介 2010-05-29 15:21 小柳

很好,謝謝了!  回復(fù)  更多評(píng)論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美一级播放| 亚洲精选中文字幕| 亚洲美女黄网| 亚洲国产精品第一区二区| 亚洲欧美在线免费| 亚洲性视频网址| 欧美理论电影在线播放| 欧美成人一区二区三区片免费| 国产精品久久久久aaaa九色| 亚洲精品一区在线| 亚洲激情电影在线| 久久久久久久久综合| 久久精品国产一区二区三| 国产精品露脸自拍| 一区二区三区视频在线 | 国产精品入口| 亚洲精品日韩在线观看| 亚洲国语精品自产拍在线观看| 欧美制服丝袜| 久久综合五月| 国内精品久久久久久久影视蜜臀 | 欧美大片网址| 亚洲国产精品毛片| 免费看的黄色欧美网站| 欧美国产精品人人做人人爱| 亚洲电影免费观看高清完整版在线| 性欧美精品高清| 久久精品国产999大香线蕉| 国产精品欧美精品| 午夜激情一区| 免费亚洲一区二区| 亚洲精品欧美在线| 欧美肉体xxxx裸体137大胆| 日韩小视频在线观看专区| 亚洲素人一区二区| 国产区在线观看成人精品| 亚洲一区中文| 久久手机免费观看| 亚洲国产欧美不卡在线观看| 欧美大片网址| 在线视频精品一区| 欧美在线网址| 亚洲激情成人| 国产精品久久久对白| 欧美一区二区三区精品| 欧美刺激午夜性久久久久久久| 亚洲人www| 国产精品www| 久久国产日韩| 日韩视频一区二区| 久久国产精品毛片| 亚洲国内精品| 国产精品久在线观看| 久久久蜜桃精品| 一区二区激情视频| 免费短视频成人日韩| 在线午夜精品自拍| 黑人极品videos精品欧美裸| 欧美成年人视频网站欧美| 亚洲婷婷免费| 欧美国产视频在线| 欧美一区二区三区久久精品| 在线精品视频一区二区| 欧美日韩一区二区在线播放| 久久av免费一区| 亚洲理伦在线| 久久最新视频| 性欧美暴力猛交69hd| 亚洲国产精品久久久久久女王| 欧美无乱码久久久免费午夜一区| 久久精品人人爽| 99在线精品视频| 欧美大秀在线观看| 欧美在线视频二区| 亚洲一区二区欧美日韩| 亚洲国产高清aⅴ视频| 国产精品日韩电影| 欧美日韩大片| 美女黄网久久| 久久久久久久欧美精品| 亚洲性夜色噜噜噜7777| 亚洲精品久久嫩草网站秘色| 欧美一区二区精美| 亚洲少妇诱惑| 亚洲精品在线二区| 亚洲电影自拍| 狠狠色噜噜狠狠色综合久| 国产精品香蕉在线观看| 欧美日韩国产成人在线| 欧美成人国产va精品日本一级| 午夜电影亚洲| 亚洲免费在线观看视频| 亚洲精品你懂的| 蜜桃伊人久久| 老色鬼久久亚洲一区二区| 欧美亚洲综合另类| 亚洲欧美一区二区精品久久久| 一本色道久久综合亚洲91| 亚洲欧洲久久| 亚洲三级视频| 亚洲精品视频免费观看| 亚洲欧洲精品一区| 亚洲日韩欧美一区二区在线| 在线视频国内自拍亚洲视频| 在线电影国产精品| 国产亚洲制服色| 激情综合中文娱乐网| 黄色日韩在线| 亚洲国产日韩欧美在线99| 尤物精品国产第一福利三区 | 亚洲黄页一区| 亚洲国产色一区| 91久久精品日日躁夜夜躁国产| 欧美黄色一区二区| 亚洲人成在线播放网站岛国| 亚洲激精日韩激精欧美精品| 91久久精品国产91久久| 亚洲国产精品va在看黑人| 亚洲黄色一区| 中文欧美日韩| 午夜在线不卡| 久久久999国产| 欧美成人三级在线| 欧美日韩国产首页在线观看| 欧美午夜精品久久久久久久| 国产精品夜夜夜| 黄色av日韩| 亚洲精品色图| 欧美一级网站| 欧美粗暴jizz性欧美20| 最新精品在线| 小黄鸭精品aⅴ导航网站入口| 久久久福利视频| 欧美国产日韩xxxxx| 欧美午夜影院| 在线看片欧美| 亚洲一区成人| 久久综合网色—综合色88| 亚洲国产视频直播| 亚洲欧美中文字幕| 欧美高清在线观看| 国产日本欧美在线观看| 亚洲国产成人精品久久| 亚洲一区视频在线观看视频| 久久久久www| 一本大道久久a久久综合婷婷| 亚洲综合社区| 欧美成人蜜桃| 国产亚洲激情在线| 亚洲视频免费在线| 欧美aⅴ一区二区三区视频| 日韩视频在线观看国产| 久久av一区二区| 欧美手机在线视频| 亚洲福利一区| 欧美在线免费观看视频| 亚洲第一精品影视| 欧美亚洲在线| 欧美日韩中文字幕精品| 国内自拍一区| 香蕉成人伊视频在线观看| 欧美国产国产综合| 欧美中文字幕视频| 国产精品高潮在线| 日韩亚洲欧美综合| 欧美搞黄网站| 久久久精品日韩| 国产欧美一区二区精品性| 一本色道婷婷久久欧美| 欧美肥婆在线| 久久久久久久网| 国产综合色产在线精品| 亚洲一区二区三区四区视频| 亚洲第一网站免费视频| 欧美在线中文字幕| 国产婷婷色一区二区三区在线| 中日韩美女免费视频网站在线观看| 欧美黑人国产人伦爽爽爽| 久久九九热免费视频| 国产日韩视频| 久久成人羞羞网站| 亚洲视频在线观看三级| 欧美涩涩网站| 亚洲一区区二区| 日韩午夜免费视频| 欧美日韩午夜在线| 一区二区不卡在线视频 午夜欧美不卡在| 免费视频一区| 免费看成人av| 日韩小视频在线观看| 欧美黄色精品| 欧美国产先锋| 一本到12不卡视频在线dvd| 亚洲第一区色| 欧美理论视频| 亚洲欧美日本日韩| 亚洲欧美日韩国产中文| 国产亚洲精品aa| 欧美成人黑人xx视频免费观看| 久久综合精品一区|