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

            永遠(yuǎn)也不完美的程序

            不斷學(xué)習(xí),不斷實(shí)踐,不斷的重構(gòu)……

            常用鏈接

            統(tǒng)計(jì)

            積分與排名

            好友鏈接

            最新評(píng)論

            聚焦3D地形編程第二章Terrain 101

             翻譯的爛,請(qǐng)見諒,期望深刻理解還請(qǐng)閱讀原著,本譯文僅供參考。
            譯:microsoftxiao@163.com 邵小寧 神殺中龍

            好,在這里——你將進(jìn)入3D地形編程的世界!本章將包括地形渲染的所有方面,在你開始有趣的紋理化/光照化技術(shù)之前,你需要知道這些,各種各樣的硬編碼地形算法。在本章,你將學(xué)習(xí)到下面的關(guān)鍵概念:

            n         什么是高度圖,怎樣創(chuàng)建它,并且怎樣加載它。

            n         怎樣使用burte force算法渲染地形

            n         怎樣使用fault formationmidpoint displacement產(chǎn)生不規(guī)則地形。

            那么,讓我們開始吧!

            Heightmaps – 高度圖

            假設(shè)你有一個(gè)規(guī)則的多邊形格子沿XZ軸展開。這種情況下你不知道我要談?wù)撌裁矗鐖D2.1可以更新你的內(nèi)存。

            現(xiàn)在那是一張漂亮但有令人討厭的圖像!我們?cè)鯓涌梢哉_的制作它呢,好,terrain-ish? 答案是使用高度圖。高度圖,在我們這兒,是一系列unsigned char變量(讓我們把值取在0-255, 這樣在灰度圖上產(chǎn)生一系列漸變灰度值)我們將實(shí)時(shí)創(chuàng)建且在繪圖程序內(nèi)。高度圖為我們的地形提供高度值,所以如果我們沿著XZ軸展開的話,高度圖定義的值將沿著Y軸展開。快舉個(gè)例子, 看如圖2.2 之后我們加載它并且把它運(yùn)用到我們的地形中,在格子2.1的格子中將變換出美麗地形(雖然它非常的缺乏顏色和光照)你看如圖2.3

            必須承認(rèn),圖2.3的地形開起來(lái)即漂亮又討厭,沒有非常酷的紋理和光照,但是我們需要從某處開始!同樣我剛剛解釋了,高度圖給我們的格子的頂點(diǎn)提高到一個(gè)宏偉的風(fēng)景,增添了力量。問(wèn)題是,嚴(yán)密的說(shuō)什么是高度圖?通常,一個(gè)高度圖是一個(gè)每像素描繪的灰度值。(在這里,高度范圍從0-255, 一系列漸變的灰度圖。)暗色描繪低海拔,那么亮色描繪高海拔。再看如圖2.22.3; notice how the 3D terrain(Figure 2.3) corresponds exactly to the heightmap in Figure 2.2, 從山頂任何一點(diǎn),到山谷,是平滑的顏色么?那么我們想要我們高度圖做什么呢:作為我們地形頂點(diǎn)的模型。

            在這里,我們高度圖的格式將是RAW格式。(雖然大部分demos動(dòng)態(tài)創(chuàng)建高度圖,我包含了加載和保存RAW格式的選項(xiàng)。) 我選擇這個(gè)格式因?yàn)樗y以置信的簡(jiǎn)單容易使用。另外,因?yàn)?/span>RAW格式僅僅包含純數(shù)據(jù),它更容易加載高度圖。(我們也要加載灰度的RAW圖,更容易制作。)在我們加載RAW圖像前,我們需要幾個(gè)東西。首先,我們需要?jiǎng)?chuàng)建一個(gè)簡(jiǎn)單的可以描繪高度圖的數(shù)據(jù)結(jié)構(gòu)。我們這個(gè)結(jié)構(gòu)是一個(gè)unsigned char類型的緩沖區(qū)(我們需要可以動(dòng)態(tài)分配內(nèi)存)并且變量可以存儲(chǔ)高度圖的大小。這足夠了么, 恩?好,這里:

            struct SHEIGHT_DATA

            {

                    unsigned char* m_pucData; // the height data

                  int           m_iSize;     // the height size(power of 2)

            };

            創(chuàng)建地形基礎(chǔ)類 The Creation of a Base Terrain Class

            我們需要從所有特定的地形引擎中(brute force, geomipmapping)創(chuàng)建基礎(chǔ)類將被繼承。我們不希望用戶創(chuàng)建這類的實(shí)例;我們僅僅想讓這個(gè)類成為我們今后開發(fā)特定實(shí)現(xiàn)的父類。看圖2.4在我們頭腦獲得一個(gè)可視化概念。

            CTERRAIN

            CBRUTE_FORCE

            CGEOMIPMAPPING

            CROAM

            CQUADTREE

            繼承自

            2.4 CTERRAIN和四個(gè)地形實(shí)現(xiàn)類的關(guān)系

            注意: CTERRAIN類是我們C++內(nèi)的一種抽象類。抽象類是給所有它的子類提供公共的接口。用途是: 一個(gè)目前有紅色頭發(fā)但是性格另人討厭。雖然所有它的孩子繼承了母親的紅色頭發(fā),但每個(gè)有獨(dú)特的性格。同樣一個(gè)抽象類;雖然一個(gè)抽象類令人討厭,its traits carry on to its children, 并且那些孩子可以被定義更多它們自己的另人激動(dòng)的行為。(即通過(guò)覆寫虛函數(shù))

            至此我們的類需要三個(gè)變量: 一個(gè)SHEIGHT_DATA的實(shí)例,一個(gè)高度縮放比列變量(將讓我們可以為地形動(dòng)態(tài)縮放高度), 和一個(gè)大小變量(可以存儲(chǔ)SHEIGHT_DATA的大小)。至于函數(shù),我們需要一些操作高度圖的函數(shù)和設(shè)置高度縮放變量的函數(shù)。這里我們展示出:

            class CTERRAIN

            {

                   protected:

                          SHEIGHT_DATA  m_heightData;       // the height data

                          Float                    m_fHeightScale;     // scaling variable

            public:

                int                        m_iSize;            // must be a power of two

                virtual void Render(void) = 0;

               bool LoadHeightMap(char* szFilename, int iSize);

                bool SaveHeightMap(char* szFilename);

                bool UnloadHeightMap(void);

            //-------------------------------------------------------------------------------------

            // Name:                 SetHeightScale – public

            // Description:             Set the height scaling variable

            // Arguments:              -fScale: how much to scale the terrain

            // Return Value: None

            //---------------------------------------------------------------------------------------

            inline void SetHeightScale(float fScale)

            { m_fHeightScale = fScale; }

            //------------------------------------------------------------------------------------------

            // Name:                   SetHeightAtPoint – public

            // Description:              Set the true height value at the given point

            // Arguments:               -unHeight: the new height value for the point

            //                         -iX, iZ: which height value to retrieve

            // Return Value:             None

            //-------------------------------------------------------------------------------------------

            inline void SetHeightAtPoint(unsigned char ucHeight, int iX, int iZ)

            { m_heightData.m_pucData[( iZ*m_iSize )+iX] = ucHeight; }

            //---------------------------------------------------------------------------------------------

            // Name:                      GetTrueHeightAtPoint – public

            // Description:      A function to get the true height value(0-255) at a point

            // Arguments:       -iX, iZ: which height value to retrieve

            // Returen Value:    An unsigned char value: the true height at

            //                 the given point

            //----------------------------------------------------------------------------------------------

            inline unsigned char GetTrueHeightAtPoint(int iX, int iZ)

            { return ( m_heightData.m_pucData[( iZ*m_iSize )+iX ]; }

            //-------------------------------------------------------------------------------------------------

            // Name:                  GetScaledHeightAtPoint – public

            // Description:              Retrieve the scaled height at a given point

            // Arguments:               -iX, iZ: which height value to retrieve

            // Return Value:             A float value: the scaled height at the given point

            //--------------------------------------------------------------------------------------------------

            inline float GetScaledHeightAtPoint( int iX, int iZ )

            { return ( ( m_heightData.m_pucData[( iZ*m_iSize )+iX])*m_fHeightScale); }

            CTERRAIN(void)

            {    }

            ~CTERRAIN(void)

            {    }

            };

            Not too shabby if I do say so myself! 好那是我們的地形父類!每個(gè)我們開發(fā)的其他實(shí)現(xiàn)從這個(gè)類派生。我為用戶添加了兩個(gè)容易使用的操作高度圖的函數(shù)。然而我們,作為開發(fā)者,將使用true函數(shù),用戶將使用被縮放了的函數(shù)來(lái)執(zhí)行碰撞檢測(cè)(我們將在第八章做, “封裝它: 特效和其他”)

            加載和卸載高度圖 Loading and Unloading a Heightmap

            我已經(jīng)談?wù)摿诉@些例程,并且我們最后要使用它們。這些例程是簡(jiǎn)單的,所以對(duì)比他們沒有任何難度。我們僅僅使用一些C風(fēng)格的文件I/O來(lái)做。

            注意: 我趨向于使用嚴(yán)格的C風(fēng)格I/O因?yàn)樗?/span>C++風(fēng)格的更容易閱讀。如果你已經(jīng)是真正的C++死忠,并且完全厭惡C做事的方式,那么可以自由改變例程為C++式的。另一方面,我確實(shí)喜歡C++風(fēng)格的內(nèi)存操作,所以,如果你是C死忠,那么你就那么做。

            我需要談?wù)撛鯓蛹虞d,保存和卸載高度圖。最好的地方是在開始時(shí)加載例程因?yàn)槟悴荒茉跊]有加載前卸載任何事物。我們需要兩個(gè)參數(shù):文件名和地圖大小。在函數(shù)內(nèi),我們想創(chuàng)建FILE的實(shí)例來(lái)加載高度圖。那么我們想確認(rèn)高度圖類的實(shí)例是否已經(jīng)加載了信息;如果是這樣,那么我們需要調(diào)用卸載例程并繼續(xù)我們操作。我們討論的代碼像這樣:

            bool CTERRAIN::LoadHeightMap(char* szFilename, int iSize)

            {

                   FILE* pFile;

            //check to see if the data has been set

            if( m_heightData.m_pucData)

                UnloadHeightMap();

            }

            其次, 我們需要打開文件并為我們的高度圖實(shí)例數(shù)據(jù)緩沖區(qū)分配內(nèi)存(m_heightData.m_pucData)我們需要確認(rèn)內(nèi)存是否被正確的分配,是否沒有發(fā)生可怕的錯(cuò)誤。

            // allocate the memory for our height data

            m_heightData.m_pucData = new unsigned char [ iSize*iSize];

            // check to see wether the memory was successfully allocated

            if (m_heightData.m_pucData == NULL)

            {

            // the memory could not bel allocated

            // something is seriously wrong here

            printf(“Could not allocate memory for%s"n”, szFilename);

            return false;
            }

            我們的加載過(guò)程繼續(xù),我們將加載實(shí)際的數(shù)據(jù)把它們放置在高度圖實(shí)例的數(shù)據(jù)緩沖區(qū)內(nèi)。然后我們將關(guān)閉文件,設(shè)置一些類成員變量,然后輸出成功消息。

            // read the heightmap into context

            fread(m_heightData.m_pucDat, 1, iSize*iSize, pFile);

            // close the file

            fclose(pFile);

            // set the size data

            m_heightData.m_iSize = iSize;

            m_iSize = m_heightData.m_iSize;

            // Yahoo! The height has been successfully loaded!

            Printf(“Loaded %s"n”, szFilename);

            Return true;

            }

            注意: 高度圖保存例程幾乎是和加載同樣的東西。基本上,我們僅僅需要替換freadfwriteThat’s all there is to it!

            那就是加載例程。讓我們?cè)谖覀冏⒁饬Ρ环稚⑶稗D(zhuǎn)到卸載例程。卸載程序是簡(jiǎn)單的。我們僅僅必須檢查內(nèi)存是否已經(jīng)被分配,然后如果分配了,我們需要?jiǎng)h除它。

            bool CTERRAIN::UnloadHeightMap(void)

            {

            // check to see if the data has been set

            if(m_heightData.m_pucData)

            {

                // delete the data

                delete[] m_heightData.m_pucData;

                // reset the map dimensions, also

                m_heightData.m_iSize = 0;

            }

            // the heightmap has been unloaded

            printf(“Successfully unloaded the heightmap"n”);

            return true;

            }

            我真的不需要檢查數(shù)據(jù)緩沖是一個(gè)NULL指針(指針是否為NULL在中心會(huì)檢查) , 所有我的檢查有點(diǎn)是多余的。這個(gè)檢查已經(jīng)成為了習(xí)慣,然而,這本書就是這么做的。你可以不檢查是否為NULL指針就刪除它。現(xiàn)在我將展示給你我們已經(jīng)討論的渲染方法。

            The Brute Force of the Matter 硬渲染

            渲染地形使用brute force算法直接而簡(jiǎn)單,而且它提供了最大化的細(xì)節(jié)。不幸的是,它是這本書里講的最慢的算法。基本上,如果你有一個(gè)64x64像素的高度圖,那么地形,當(dāng)使用brute force渲染時(shí),由64x64個(gè)頂點(diǎn)組成,規(guī)則的重復(fù)模式。如圖(2.5)

            這種情況下你不能立即重新組織它,我們將每行的頂點(diǎn)作為三角形帶渲染因?yàn)檫@是大部分渲染頂點(diǎn)的方式。你不能單獨(dú)的渲染一個(gè)三角形或使用像圖2.5那樣的方式渲染三角扇形,would you?

            這章的demo, 我留著它作為一種簡(jiǎn)單的可能。頂點(diǎn)的顏色基于它的高度,所以所有頂點(diǎn)將利用灰色著色。并且所有這些都使用brute force渲染地形。這里快速的摘錄一小片OpenGL來(lái)展示怎樣渲染地形:

            void CBRUTE_FORCE::Render(void)

            {

            unsigned char unColor;

            int iZ;

            int iX;

            // loop throught the Z axis of the terrain

            for (iZ = 0; iZ<m_iSize-1; iZ++)

            {

                   // begin a new triangle strip

                   glBegin(GL_TRIANGLE_STRIP);

                   //loop through the X axis of the terrain

                   //this is where the triangle strip is constructed

                   for(iX=0; iX<m_iSize-1;iX++)

                   {

                          //Use height-based coloring. (High-points are

                    //light, and low points are dark.)

                    ucColor = GetTrueHeightAtPoint(iX, iZ);

                          // set the color with OpenGL, and reader the point

                    glColor3ub(ucColor, ucColor, ucColor);

                    glVertex3f(iX, GetScaledHeightAtPoint(iX, iZ), iZ);

                          // Use height-based coloring. (High-points are

                    // light, and low points are dark.)

                    ucColor = GetTrueHeightAtPoint(iX, iZ+1);

                          // set the color with OpenGL, and render the point

                    glColor3ub(ucColor, ucColor, ucColor);

                    glVertex3f(iX,

            GetScaledHeightAtPoint(iX, iZ+1),

            iZ+1);

                   }

                // end the triangle strip

                glEnd();

            }
            }

            現(xiàn)在到了創(chuàng)建實(shí)際demo的時(shí)候了!拿出在CD上的demo2_1。到Cod"Chapter 2"demo2_1, Microsoft Visual C++打開工作區(qū), 然后開始娛樂!這個(gè)demo展示了我們剛剛討論的梭魚東西。如圖2.6展示了demo的截圖,如表2.1提供了控制demo的描述。移動(dòng)你的視點(diǎn),僅僅可以使鼠標(biāo)向左,右和拖拽。

            Woohoo!現(xiàn)在,我說(shuō)過(guò)我們將創(chuàng)建大量我們的動(dòng)態(tài)高度圖。你也許會(huì)問(wèn)你自己,我該怎樣做? 好的,我很高興回答你。(甚至如果你不問(wèn),我仍然要解釋它!)現(xiàn)在我們將學(xué)習(xí)怎樣以程序的方式使用兩種不規(guī)則地形產(chǎn)生技術(shù)生成高度圖。準(zhǔn)備!

            Fractal Terrain Generatoin 不規(guī)則地形生成

            Fractal terrain generation被用來(lái)產(chǎn)生地形的算法, 雖然這里,我們將高度圖作為我們地形的藍(lán)圖。但是我們將通過(guò)這里的兩個(gè)算法,第一個(gè)是fault formation和第二個(gè)midpoint displacement。我們將自始至終的使用fault formation算法在本書因?yàn)樗粫?huì)被地點(diǎn)尺寸所限制,(如果用一般高度圖將限制在0-255的高度) midpoint displacement需要2N次方才可以。(尺寸也必須是相等的,所以你可以產(chǎn)生1024x1024的高度圖,你不能產(chǎn)生產(chǎn)生一個(gè)512x1024的高度圖。)所以,不要再耽擱了,讓我們從不規(guī)則地形生成算法開始!

            Fault Formation缺點(diǎn)形成算法

            一種不規(guī)則地形生成算法叫做fault formation. Fault formation是在生成地形過(guò)程中”faults”; 大部分時(shí),它產(chǎn)生比較平滑的地形。基本上,所有我們做的隨機(jī)線在blank高度區(qū)域, 而且然后我們添加隨機(jī)高到一邊。看圖2.7如果你討厭可視化或者如果你剛剛想要證實(shí)你腦中的圖(或者, 如果你喜歡, 注意你的頭腦我很奇怪)是正確的。

            原版 43頁(yè) fault-formation algorithm

            這是整個(gè)過(guò)程的第一步,當(dāng)然。在你提高到高級(jí)階段之前,這里還有一些你需要知道的算法。首先,更早時(shí)我談?wù)撨^(guò)需要減少每次反復(fù)。你也許會(huì)問(wèn)為什么?好,如果你不減少每個(gè)高度,你最后使用的高度將像2.8。看2.9的高度圖。

            注意, 在圖2.8, /暗斑點(diǎn)是多么的不和諧就是這個(gè)原因;他們僅僅在所有地方被展開。這就好像一個(gè)混亂的地形,但是我們像創(chuàng)建一個(gè)平滑的,起伏的小山。不要擔(dān)心;解決這個(gè)問(wèn)題相當(dāng)簡(jiǎn)單。我們想用線性遞減高度值沒有在0結(jié)束。這么做,我們將使用下面的等式(拿出demo2_2):

            iHeight = iMaxDelta – ((iMaxDelta-iMinDelta)*iCurrentIteration)/iIterations;

            iMinDelta, iMaxDelta, iIterations作為函數(shù)參數(shù)提供。 iMinDeltaiMaxDelta描繪了最低值和最高值,你想要當(dāng)新faults時(shí)的高度。我趨向于嚴(yán)格的一個(gè)0作為iMinDelta255作為iMaxDeltaiIterations 我之前說(shuō)過(guò),描繪fault passes一系列過(guò)程(多么不同的時(shí)間被劃分)。最后,but certainly not least, iCurrentIteration描繪了當(dāng)前iteration值。

            我早說(shuō)過(guò),我們就年斤毫年 想提升一邊,然后我們想升起每個(gè)邊線點(diǎn)的高度值。因此,我們將循環(huán)處理整個(gè)高度圖的所有高度。所有這些容易實(shí)現(xiàn);它僅僅是解決一個(gè)簡(jiǎn)單的數(shù)學(xué)問(wèn)題。我有一個(gè)vector在我們線的方向上(我們之前創(chuàng)建了兩個(gè)隨機(jī)點(diǎn),那么它的方向被存儲(chǔ)在(iDirX1, iDirZ1)。下一個(gè)vector我們想創(chuàng)建一個(gè)從最初隨機(jī)點(diǎn)(iRandX1, iRandZ1)到當(dāng)前循環(huán)點(diǎn)(x, z) 之后完成,我們需要找到Z分量的叉乘, 然后如果它比0大,那么我們需要增加當(dāng)前點(diǎn)。所有之前的解釋都將從這的代碼展示出來(lái)。

            // iDirX1, iDirZ1 is a vector going the same direction as the line

            iDirX1 = iRandX2 – iRandX1;

            iDirZ1 = iRandZ2 – iRandZ1;

            for(x = 0; x<m_iSize;x++)

            {

                   for(z=0; z<m_iSize; z++)

                   {

                          // iDirX2, iDirZ2 is a vector from iRandX1, iRandZ1 to the

                          // current point (in the loop).

                          iDirX2 = x-iRandX1;

                         iDirZ2 = z-iRandZ1;

                          // if the result of (iDirX2*iDirZ1 – iDirX1*iDirZ2) is “up”

                          //(above 0), then raise this point by iHeight

                          if((iDirX2*iDirZ1 – iDirX1*iDirZ2) > 0)

                                 fTempBuffer[( z*m_iSize)+x]+=(float)iHeight;

                   }

            }

            注意: demo2_2這兩段你看到了fault formationmidpoint displacement代碼在demo2_2內(nèi)的兩個(gè)片段,你也許注意到我怎樣創(chuàng)建臨時(shí)緩沖區(qū),fTempBuffer, 所有的高度值嚴(yán)格用浮點(diǎn)表示。如果你記得,雖然,我談?wù)撨^(guò)我們的高度圖是一個(gè)unsigned char類型的數(shù)組。為什么我在這種情形使用浮點(diǎn)變量?我這么做是因?yàn)樗惴ㄐ枰任覀兊哪J(rèn)unsigned char高度緩沖區(qū)有更高的精確性。之后我們創(chuàng)建整個(gè)高度圖并規(guī)格化,我從fTempBuffer傳送所有信息到CTERRAIN類內(nèi)的高度緩沖區(qū), m_heightData

            檢查圖2.9看一些使用fault formation產(chǎn)生的高度圖,和各種fault-line iterations. 緊接著, 我們也還沒有完成這個(gè)算法!萬(wàn)一你沒注意, 地圖看起來(lái)像之前的圖(-terrainish)(新世界)。我們需要經(jīng)過(guò)一個(gè)腐蝕(erosion)過(guò)濾器來(lái)過(guò)濾整個(gè)地圖直到我們形成一個(gè)新的平滑的值的。這個(gè)過(guò)程非常好, 如果不精確, 像經(jīng)過(guò)污點(diǎn)過(guò)濾器通過(guò)你喜歡的繪圖程序來(lái)處理下。 如果它幫助你理解了下面的解釋, 正好是這樣的理解。

            我們將要應(yīng)用一個(gè)簡(jiǎn)單的FIR過(guò)濾器, 作為Jason Shankel的建議。 這個(gè)過(guò)濾器意味著模擬地形侵蝕(erosion),就像自然界頻繁發(fā)生的那種。你曾經(jīng)在自然界里看到過(guò)的一系列的高山看起來(lái)如圖2.9?) 我們將獲得波形(bands)數(shù)據(jù),勝于立刻過(guò)濾整個(gè)高度圖。過(guò)濾函數(shù)看起來(lái)像這樣:

            void CTERRAIN::FilterHeightBand( float* fpBand, int iStride, int iCount, float fFilter)

            {

                   float v = ucpBand[0];

                   int j = iStride;

                   int i;

                   // Go through the height band and apply the ersion filter

                   for(i = 0; i < iCount-1; i++ )

                   {

                          ucpBand[j] = fFilter*v + (1-fFilter)*ucpBand[j];

                          v = ucpBand[j];

                          j+= iStride;

                   }

            }

            這個(gè)函數(shù)獲取高度值的單個(gè)邊并且goes through them value by value, 通過(guò)iStride規(guī)定在每次循環(huán)內(nèi)的向前的值日。iStride也規(guī)定出我們過(guò)濾整個(gè)高度圖從上到下的方向,從下到上,從坐到右,從右到左。整個(gè)函數(shù)最重要的是這行:

            ucpBand[j] = fFilter*v + (1-fFilter)*ucpBand[j];

            這行是涂污/侵蝕。 各種各樣的值為了fFilter影響模糊。0.0f是根本不模糊, 1.0f是最模糊。通常,我們想要值在0.3f0.6f之間,這依賴于你想要地形的平滑程度。現(xiàn)在,例如, 我們說(shuō)出過(guò)濾器的值0.25f, 且當(dāng)前邊值為0.9f。前一個(gè)等式看起來(lái)像這樣:

            ucpBand[j] = 0.25f*v + (1-0.25f)*0.9f;

            之后我們執(zhí)行初始化計(jì)算, 之前的等式將簡(jiǎn)單化為這樣:

            ucpBand[j] = 0.25f*v + 0.675f;

            0.675f是高度圖像素被模糊的新值, 但是現(xiàn)在它需要被和之前的像素值進(jìn)行插值。(我們將給出像素值為0.87f)。我們應(yīng)用0.25模糊過(guò)濾器到該像素且加上非插值的像素值到此像素,以致于我們有這樣的計(jì)算。

            ucpBand[j] = 0.25f*0.87f + 0.675f;

            執(zhí)行最后的計(jì)算, 我們得到0.8925f的最終值。 所以,你看, 所有我們真實(shí)的行動(dòng)這里混合成了當(dāng)前像素到前一像素間的值。拿出圖2.10看我們之前討論的每像素過(guò)濾看起來(lái)是非常大攀登。

            玩弄下demo2_2. 我為高度圖操作制作了菜單, 并且現(xiàn)在你可以動(dòng)態(tài)創(chuàng)建新的高度圖。如果你找到了,僅僅選擇保存當(dāng)前選項(xiàng), 那么高度圖將被保存到程序目錄下。當(dāng)你選擇Fault Formation選項(xiàng)時(shí),彈出一個(gè)對(duì)話框你可以輸入細(xì)節(jié)值。這個(gè)值是一個(gè)整數(shù),取值范圍為1-100。現(xiàn)在該介紹些有趣的midpoint displacement(中點(diǎn)位移)的時(shí)候了。

            Midpoint Displacement 中點(diǎn)位移算法

            Fault formation在一些小場(chǎng)景組成一些小山工作的非常好,但是如果你想產(chǎn)生一些比這混亂的,甚至像山脈那樣的地貌, Fault formation就不行了。好,繼續(xù)看。Midpoint displacement將可以滿足你的期待!這個(gè)算法也被認(rèn)為是plasma fractaldiamond-square算法。然而,midpoint displacement發(fā)出的聲音更酷,并且它提供給讀者(就是你)一個(gè)繼續(xù)整個(gè)過(guò)程更好的觀點(diǎn),所以我將堅(jiān)持大部分時(shí)間使用這一術(shù)語(yǔ)。

            注意: 重要的是注意midpoint displacement算法有一個(gè)輕微的缺點(diǎn): 算法僅可以生成方形的高度圖,并且尺寸必須似乎2N次方。這不像fault formation算法,你可以指定任何你想要的尺寸。

            我們將完成這個(gè)算法,本質(zhì)上,它是對(duì)單條邊的中點(diǎn)進(jìn)行位移。讓我給你一個(gè)一維空間的概念。如果我們有一條線,像如圖2.11 AB 我們找到它的重點(diǎn),標(biāo)記出來(lái)為C。并且移動(dòng)它。現(xiàn)在,我們將位移線中點(diǎn)的高度值,我們叫fHeight吧。(看圖2.12)我們將使得產(chǎn)生的兩條線相等,并且我們將在-fHeight/2fHeight/2到范圍內(nèi)位移中點(diǎn)。(我們想要每次細(xì)分出(subdivide)兩條線,而且我們將要將其位移到線的某個(gè)高度在一定范圍內(nèi)。

            之后我們需要遞減fHeight的直到我們期望的粗糙程度。就這么做,我們簡(jiǎn)單的用2-fRoughness來(lái)進(jìn)行乘法, fRoughness是未加工地形的一個(gè)常量值。用戶將指定該值存儲(chǔ)到fRoughtness內(nèi),所以你需要知道一點(diǎn)關(guān)于你可以設(shè)置各種值的信息。這個(gè)值是可以的,從技術(shù)上講,任何可以是你任何期望的浮點(diǎn)值,但是最好的結(jié)果應(yīng)該是0.25f1.5f。看圖2.13,可視化的指示出各種可以達(dá)到的粗糙程度的情形。

            正如你看到的,這個(gè)值即fRoughness對(duì)高度圖的影響相當(dāng)大。值小于1.0f將創(chuàng)建一個(gè)無(wú)序地形,值正好為1.0將是平行的,大于1.0f將創(chuàng)建一個(gè)平滑的地形。現(xiàn)在讓我們繼續(xù)深入解釋二維的情形。

            1D的解釋留在你的大腦中,我們將改變到2D因?yàn)槟銊倓倢W(xué)習(xí)了單條線的相關(guān)概念。有個(gè)例外是這樣的,代替單線的中點(diǎn)計(jì)算,我們現(xiàn)在必須計(jì)算四條不同邊的中點(diǎn),平均它們,然后為正方形的中心的高度值增加這個(gè)值。如圖2.14所示的正方形(ABCD)開始。

            像我之前說(shuō)的第二點(diǎn),我們必須計(jì)算所有四邊的中點(diǎn)(AB, BD, DC, CA)結(jié)果點(diǎn)為E, 將直接在正方形的中心。然后位移EABCD高度值的平均值,并加上在-fHeight/2fHeight/2范圍內(nèi)的隨機(jī)值。結(jié)果將如圖2.15所示。

            這還僅僅是第一次位移的一半階段。現(xiàn)在我們必須計(jì)算出每個(gè)中點(diǎn)的高度值,是我們先前找到的那個(gè)。跟我們之前做的是相似的,;我們僅僅平均圍繞頂點(diǎn)的高度值并加上-fHeight/2fHeight/2范圍內(nèi)隨機(jī)值日。最后將如圖2.6所示。

            然后你可以繼續(xù)找到下一個(gè)矩形執(zhí)行同樣的處理。如果你理解了1D解釋,然而,你確定理解了2D解釋并實(shí)習(xí)那代碼,demo2_2, 找到CD內(nèi)Code"Chapter 2"demo2_2

            編譯信息,照常,提供了文本文件在demo的目錄下。去查看這個(gè)demo。控制與最后一次的(2.1提示)的相同,但是這次,當(dāng)你點(diǎn)下細(xì)節(jié)區(qū)域的重點(diǎn)時(shí),你想要的值范圍為0(真是無(wú)序的地形)150(簡(jiǎn)單地形 ). 真有趣。

            摘要

            本章,你收到了進(jìn)入地形編程的入門級(jí)訓(xùn)練。你學(xué)到了所有關(guān)于高度圖的信息: 它們是,怎樣產(chǎn)生它們,還有怎樣加載/卸載它們。然后你學(xué)習(xí)了怎樣使用burte force渲染那些高度圖,是市面上最簡(jiǎn)單的地形渲染算法。最后,你學(xué)習(xí)兩種程序式產(chǎn)生高度圖的算法。下兩章,我們將學(xué)習(xí)所有和地形的紋理化和光照化的有趣技術(shù)。

            參考

            1 Shankel, Jason, “Fractal Terrain Generation – Fault Formation. “

            Game Programming Gems. Rockland, Massachusetss: Charles River Media, 2000. 499-502.

            2. Shankel, Jason. “Fractal Terrain Generation – Midpoint Displacement. “ Game Programming Gems. Rockland, Massachusetts:

            Charles River Media, 2000. 503-507.

            posted on 2008-09-23 17:03 狂爛球 閱讀(650) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 圖形編程

            99国内精品久久久久久久| 久久AⅤ人妻少妇嫩草影院| 色综合久久中文综合网| 久久人妻少妇嫩草AV无码专区| 久久人人爽人爽人人爽av| 国产一区二区精品久久岳| 99久久婷婷国产一区二区| segui久久国产精品| 国产精品熟女福利久久AV| 久久精品亚洲欧美日韩久久| 久久精品国产精品亚洲下载| 日韩欧美亚洲综合久久影院Ds | AAA级久久久精品无码区| 久久精品国产91久久综合麻豆自制| 久久久久久久久无码精品亚洲日韩| 99久久做夜夜爱天天做精品| 亚洲欧洲精品成人久久曰影片| 尹人香蕉久久99天天拍| 久久精品国产久精国产一老狼| 久久九九精品99国产精品| 精品久久久久久综合日本| 91亚洲国产成人久久精品| 一本色道久久88综合日韩精品 | 女人香蕉久久**毛片精品| 久久精品免费一区二区三区| 国产成人99久久亚洲综合精品| 久久这里有精品视频| 久久精品人人做人人爽电影| 国产精品久久久天天影视| 亚洲?V乱码久久精品蜜桃| 无码精品久久久天天影视| 91久久精品电影| 久久99久国产麻精品66 | av无码久久久久不卡免费网站| 国产亚州精品女人久久久久久 | 欧美综合天天夜夜久久| 久久影院午夜理论片无码| 国产午夜福利精品久久2021| 久久无码人妻精品一区二区三区 | 精品综合久久久久久97超人| 久久人人爽人人爽人人片AV麻豆|