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

            實時陰影繪制技術研究

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

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

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

            Float --> int 轉化
            值得嘗試的做法,因為這種轉化一般會更慢。我知道的這兩種方法是用#pragma和內聯函數。首先,#pragma:

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

            這種方法表現的非常好,WDISASM 表明編譯器拋棄了對__CHP的調用而內聯了這個轉化。另一種方法不使用#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);
            }

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

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

            | 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

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

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

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

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

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

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

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

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

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

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

              另一個問題是“渲染不完全”(我的術語)。這是說,你花費了太多時間在處理離屏的多邊形上。一些有幫助的因素是,場景中的可見多邊形不會明顯變化。到現在為止,你大概可以計算一個FPS中的可見多邊形集了,用玩家的方向尋找一些需要注意的多邊形,如果玩家靠的太近,就把它們變為臨界點。有效范圍例如包圍球/包圍盒在這里也能派上用場。Hierarchial模型也可能有幫助,用來決定哪部分模型是不必要的。

            總結
            這里有幾條規則,可以讓你的引擎跑得更快:

            盡可能提前計算
            不做不必要的計算
            不要重復計算同一內容
            如果可能,要利用以前計算的結果
            尋找那些可以事半功倍的場合
            在用匯編改寫你的函數前,自問“我已經找到最好的解決方法了嗎?”
            試驗!
            冒險。
            不要 重寫任何代碼僅僅因為“看起來慢”
            探索你的目標構架,了解它的特性
            posted on 2006-03-17 23:33 苦行僧 閱讀(679) 評論(0)  編輯 收藏 引用 所屬分類: 轉載
            久久笫一福利免费导航 | 久久99国产精一区二区三区| 狠狠色婷婷久久综合频道日韩 | 天天久久狠狠色综合| 国产成人精品久久亚洲高清不卡 | 国内精品免费久久影院| 久久福利资源国产精品999| 日本久久久久亚洲中字幕| 亚洲一区中文字幕久久| 国产精品久久久久蜜芽| 久久99国产精品99久久| 国产欧美久久久精品影院| 久久久国产精品福利免费| 亚洲人AV永久一区二区三区久久 | 99热都是精品久久久久久| 波多野结衣久久| 97精品伊人久久久大香线蕉| 97久久国产综合精品女不卡 | 精品多毛少妇人妻AV免费久久 | 欧洲人妻丰满av无码久久不卡| 色成年激情久久综合| 人妻无码αv中文字幕久久琪琪布 人妻无码久久一区二区三区免费 人妻无码中文久久久久专区 | 亚洲欧美久久久久9999| 久久亚洲精品成人av无码网站| 欧美大战日韩91综合一区婷婷久久青草| 精品久久久无码人妻中文字幕豆芽| 无码8090精品久久一区 | 日本欧美国产精品第一页久久| 九九久久自然熟的香蕉图片| 亚洲精品美女久久久久99小说| 国产午夜福利精品久久| 久久777国产线看观看精品| 欧洲精品久久久av无码电影| 精品国产乱码久久久久久人妻| 亚洲精品无码久久久| 久久综合伊人77777| 久久精品国产亚洲Aⅴ香蕉| 久久性精品| 亚洲欧洲精品成人久久奇米网| 久久久久亚洲精品无码网址| 久久精品一区二区影院|