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

            實時陰影繪制技術(shù)研究

            C++博客 首頁 新隨筆 聯(lián)系 聚合 管理
              48 Posts :: 20 Stories :: 57 Comments :: 0 Trackbacks
            譯者:azure
            原文地址:http://www.azure.com.cn/article.asp?id=191

            譯者序:這是一篇講解3D引擎中,某些細(xì)節(jié)優(yōu)化的文章,文中使用的方法同樣適用于其他場合。不過因為本人對這方面的技術(shù)和詞匯不是很熟悉,所以這篇翻譯可能存在很多謬誤,希望大家多加批評指正。
            原文:Speed-up & Optimization Techniques

            緒論
              在這個頁面,我收集了一些不同的加速3D引擎的小竅門。我會先介紹一些顯而易見的,因為許多人會忽視它們,接著是一些更精彩的。如果你有其他的竅門和算法,盡可以告訴我。

            Float --> int 轉(zhuǎn)化
            值得嘗試的做法,因為這種轉(zhuǎn)化一般會更慢。我知道的這兩種方法是用#pragma和內(nèi)聯(lián)函數(shù)。首先,#pragma:

            #pragma aux RoundToInt= "fistp DWORD [eax]" parm nomemory [eax] [8087] modify exact [8087];

            這種方法表現(xiàn)的非常好,WDISASM 表明編譯器拋棄了對__CHP的調(diào)用而內(nèi)聯(lián)了這個轉(zhuǎn)化。另一種方法不使用#pragma,可以被移植到其他編譯器。這由"InnerSect"提出:

            #define FIST_MAGIC ((((65536.0 * 65536.0 * 16)+(65536.0 * 0.5))* 65536.0))
            int32 QuickFist(float inval)
            {
            double dtemp = FIST_MAGIC + inval;
            return ((*(int32 *)&dtemp) - 0x80000000);
            }

            他做了一些測試,說來有趣,如果我沒記錯的話,他發(fā)現(xiàn)上面的方法更快。

            提前計算
              提前計算所有數(shù)據(jù)!你沒法提前計算太多東西。不要以為什么都能查表,那樣你會失去靈活性。關(guān)注不同的方法。首先要提前計算的是你的法向量。表面法向量和頂點法向量。對調(diào)試來說非常重要-這些向量的計算耗時驚人。一旦你提前計算了這些數(shù)值,你只要像對待對象的其他部分一樣旋轉(zhuǎn)他們就可以了。可是不要去平移或者縮放他們。它們必須保持為單位向量。如果你偶然縮放了他們,可以乘以一個相反的比例把他們還原;例如:

            | Sx 0 0 0 |
            Transform Matrix = | 0 Sy 0 0 |
            | 0 0 Sz 0 |
            | 0 0 0 0 |
            然后你需要這樣:
            NormalX *= 1 / Sx
            NormalY *= 1 / Sy
            NormalZ *= 1 / Sz

            當(dāng)你進(jìn)行裁減和計算光照的時候,你也不需要平移他們。Also you don't need to transform your normals when you perform culling or lighting. 簡單的反向平移你考慮到的其他向量,避免矩陣/向量的乘法。你反向平移可以簡單的通過重置上方3×3的矩陣來實現(xiàn):

            For every row
            For every column
            output[row][column] = input[column][row]
            End
            End

            轉(zhuǎn)換燈光,視角向量,以及任何依賴這個矩陣的向量,都因為提前計算而節(jié)省了大量工作。你只需要像往常一樣計算,用新的向量和舊的法向量。

            倒數(shù)
              如果你需要做很多次除數(shù)相同的除法,取除數(shù)的倒數(shù),變成乘法。倒數(shù)就是1/n,n是你的除數(shù)。如果你確實很聰明,你會發(fā)現(xiàn)在運行 fdiv 的時候還有其他事可做。一個不錯的竅門是預(yù)熱高速緩存,高速緩存命中失敗會導(dǎo)致從內(nèi)存中載入數(shù)據(jù)等占用很多時間。所以,當(dāng)你坐等fdiv完成的時候,為什么不讀一些內(nèi)存地址呢?那樣它們就會被載入高速緩存了。 在我的屏幕渲染的代碼里面,這樣看起來運行良好。你可以把這個技術(shù)用在透視紋理映射上。也有助于你做透視轉(zhuǎn)換。如果想還原那個倒數(shù),再做一次1/n就可以了。非常精彩。如果你喜歡冒險,你可以把數(shù)據(jù)存儲為倒數(shù),例如Z。我還沒試過-這會很難調(diào)試。

            頂點標(biāo)識
              任意給定一個需要處理的頂點列表,你會發(fā)現(xiàn)有很多-也就是說至少一半-是不可見的,在裁減區(qū)域之外。你需要快速排除它們。一個簡單的方法就是給這些頂點加一個'可見'標(biāo)志。

              進(jìn)入處理循環(huán)之前,在準(zhǔn)備期間,把這個標(biāo)志設(shè)為false。然后,進(jìn)入循環(huán)之后,如果發(fā)現(xiàn)頂點是必要的,就設(shè)為true。例如,你發(fā)現(xiàn)一個三角形可見,就把它所有的頂點可見標(biāo)志都設(shè)為true。在那之后,你可以簡單的跳過或者排除那些沒有設(shè)這個標(biāo)志的頂點。這對復(fù)雜模型非常有用,因為他們包含大量頂點。同樣可以這樣處理有很多不可見部分的很大的場景,跳過不必要的渲染。如果用于光照,那你必須得小心。如果你進(jìn)行可見性裁減的時候,沒有計算光照,你會發(fā)現(xiàn)在邊緣的地方出現(xiàn)錯誤。你在尋找已定義數(shù)據(jù)和未定義數(shù)據(jù)的交界,這很費神。。。

              一種方法識用一個計數(shù)器來標(biāo)識。方法很簡單。初始化的時候,你把計數(shù)器設(shè)置為某個非法值,例如-1 (0xFFFFFFFF).。同時,你把幀計數(shù)器設(shè)置為0。然后在你處理對象的過程中,如果你發(fā)現(xiàn)一個面/頂點需要處理,你就把它的計數(shù)器設(shè)置為和幀計數(shù)器相等。反之,不作任何設(shè)置和清除。接著,當(dāng)你實際處理的是時候,你把它和幀計數(shù)器對比,那些計數(shù)器值和當(dāng)前幀計數(shù)器相等的頂點/面片會被使用,其他的則被跳過。這在大的數(shù)據(jù)集很方便,因為那種情況下,每幀都正確清除那個標(biāo)志代價高昂。

            指針
              指針非常方便。利用它們你能實現(xiàn)精巧的數(shù)據(jù)結(jié)構(gòu),就像鏈表,二叉樹等等。你也可以利用它們快速尋址。比如說你有一個數(shù)組,每個元素都是27字節(jié)長。你可以把它們填充到32字節(jié),利用移位來計算地址。但是,數(shù)組的每個元素都浪費了5個字節(jié)。這很浪費。因此,用指針來尋址。就是說你的頂點結(jié)構(gòu)有27字節(jié)。在三角形結(jié)構(gòu)中,不要用int vertindex[3],而是用vertex *vertptr[3]。然后簡單的載入指針,尋址,就可以了。(譯者注:說實話,這段話我沒有完全理解,有不對的地方懇請讀者指正)

            三角形vs 多邊形
              三角形易于處理,渲染速度快。但是如果你有一系列6邊形構(gòu)成的表面,你很容易把它們替換為多邊形,不過對三角形渲染器來說,你得做6倍的工作。但是三角形渲染更快。個人推薦三角形,在基于三角形的環(huán)境操作起來很簡單。多邊形有它的優(yōu)勢,可能值得一試。如果有人擁有凸多邊形偏移紋理的算法,我會非常感興趣。

            過度渲染/渲染不完全
              過度渲染是速度殺手。尤其是復(fù)合渲染代碼。你繪制,再次繪制,二次重繪,三次重繪,等等。損失時間和速度。一個簡單的排除過度渲染的方法是從前到后排列你的三角形,給它們提供Z-Buffer/S-Buffer。這仍然導(dǎo)致問題。完全依賴 Z-Buffer的三角形渲染會最終變成浪費時間。掃描所有的點,而不渲染任何東西!同樣的復(fù)雜的分段插入S-Buffers代碼,也要付出一定代價。 對大的三角形 S-Buffer看起來運作良好。但是,對大量小三角形,它就沒那么吃香了;例如,我的S-buffer算法渲染一個不到3k三角形的頭部模型,只計算lambert陰影,耗費了接近30秒鐘。很明顯,三角形數(shù)量使得分段插入的代碼負(fù)載過大。我想,這里的解決方法是開發(fā)更高效的閉合和VSD算法。將來處理這個問題有很多可能性。

              另一個問題是“渲染不完全”(我的術(shù)語)。這是說,你花費了太多時間在處理離屏的多邊形上。一些有幫助的因素是,場景中的可見多邊形不會明顯變化。到現(xiàn)在為止,你大概可以計算一個FPS中的可見多邊形集了,用玩家的方向?qū)ふ乙恍┬枰⒁獾亩噙呅危绻婕铱康奶桶阉鼈冏優(yōu)榕R界點。有效范圍例如包圍球/包圍盒在這里也能派上用場。Hierarchial模型也可能有幫助,用來決定哪部分模型是不必要的。

            總結(jié)
            這里有幾條規(guī)則,可以讓你的引擎跑得更快:

            盡可能提前計算
            不做不必要的計算
            不要重復(fù)計算同一內(nèi)容
            如果可能,要利用以前計算的結(jié)果
            尋找那些可以事半功倍的場合
            在用匯編改寫你的函數(shù)前,自問“我已經(jīng)找到最好的解決方法了嗎?”
            試驗!
            冒險。
            不要 重寫任何代碼僅僅因為“看起來慢”
            探索你的目標(biāo)構(gòu)架,了解它的特性
            posted on 2006-03-17 23:33 苦行僧 閱讀(691) 評論(0)  編輯 收藏 引用 所屬分類: 轉(zhuǎn)載
            久久国产AVJUST麻豆| 996久久国产精品线观看| 久久国产午夜精品一区二区三区| 久久久久亚洲av成人网人人软件| 亚洲精品tv久久久久久久久 | 久久精品亚洲中文字幕无码麻豆| 久久久av波多野一区二区| 国内精品久久久久久久久| 久久久久青草线蕉综合超碰| 国产叼嘿久久精品久久| 无码人妻精品一区二区三区久久 | 中文字幕无码av激情不卡久久| 亚洲AV日韩精品久久久久久 | 中文字幕亚洲综合久久菠萝蜜| 亚洲中文精品久久久久久不卡| 91精品国产综合久久婷婷| 无码人妻久久一区二区三区蜜桃| 麻豆亚洲AV永久无码精品久久 | 久久WWW免费人成一看片| 久久婷婷国产麻豆91天堂| 欧美亚洲国产精品久久| 国产成人精品久久亚洲高清不卡| 国产精品久久久久免费a∨| 狠狠色综合久久久久尤物| 99国产欧美久久久精品蜜芽| 久久久久高潮综合影院| 欧美精品福利视频一区二区三区久久久精品 | 久久免费国产精品一区二区| 欧美精品国产综合久久| 国产高潮久久免费观看| 66精品综合久久久久久久| 99麻豆久久久国产精品免费| 亚洲狠狠婷婷综合久久蜜芽| 久久婷婷五月综合国产尤物app| 精品国产乱码久久久久久浪潮 | 久久成人国产精品免费软件| 久久SE精品一区二区| 亚洲中文字幕无码久久精品1| 伊人久久大香线焦AV综合影院 | 国产91色综合久久免费| 国产精品免费福利久久|