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

            修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(轉(zhuǎn))

            本文主要講的是《天龍八部》游戲的地形和一部分場(chǎng)景的具體實(shí)現(xiàn),使用C++, Ogre1.6,我摸索了段時(shí)間,可能方法用的并不是最好的,但好歹實(shí)現(xiàn)了。文章可能講得有點(diǎn)羅嗦,很多簡(jiǎn)單的東西都講了。我是修改了ETM(Editable Terrain Manager)實(shí)現(xiàn)的地形,其實(shí)單單實(shí)現(xiàn)天龍八部的地形場(chǎng)景等的載入根本不需要使用ETM,直接用Ogre的頂點(diǎn)->索引->紋理就可以搞定地形,但我要做的是可以實(shí)時(shí)編輯的,所以用了ETM,場(chǎng)景其由于很重要的粒子和model等部分我還沒(méi)去看,所以等以后看了再詳細(xì)寫(xiě)關(guān)于場(chǎng)景的部分,但這個(gè)Demo已經(jīng)實(shí)現(xiàn)了基本的場(chǎng)景的載入。光,霧,環(huán)境,靜態(tài)物等都能載入。

            修改過(guò)的ETM和這個(gè)場(chǎng)景的Demo代碼可以通過(guò)文章底下的鏈接下載。

            Demo截圖如下:(少林)

            這個(gè)Demo比較簡(jiǎn)單,只能移動(dòng)攝像機(jī)看看場(chǎng)景。

            我研究這些的動(dòng)機(jī)是當(dāng)前在學(xué)校做一個(gè)網(wǎng)游項(xiàng)目,想做得類似于《Second Life》,苦于沒(méi)有游戲美工,最近有馬上要二期驗(yàn)收了,為了讓游戲看上去光鮮一點(diǎn),無(wú)奈之下只好借《天龍八部》的資源來(lái)用了。看了不少大牛的博客,將得感覺(jué)都有點(diǎn)不是很詳細(xì),只是大概把文件格式講了一下而已,具體怎么實(shí)現(xiàn)說(shuō)得不多(可能是覺(jué)得實(shí)現(xiàn)太容易,懶得多說(shuō)了吧...)最主要的是,似乎沒(méi)看到有人發(fā)完整的代碼。

            實(shí)際項(xiàng)目中用的程序代碼我就不放出來(lái)了,場(chǎng)景部分差不多,只是多了個(gè)內(nèi)建的編輯器,人物移動(dòng)和網(wǎng)絡(luò)通信部分等。

            編輯器的截圖曬一下,功能還不全 :-)

             

            言歸正傳,先簡(jiǎn)單地說(shuō)一下載入一個(gè)天龍八部場(chǎng)景的大致過(guò)程:

            • 讀取.Scene文件
            • 根據(jù)<Texture>讀取.Terrain文件
            • 讀取地磚大小(<tileSize>) 地形大小(xsize, ysize),縮放值(<scale>),地圖中心坐標(biāo)(<center>)。
            • 讀取所有要用的地形貼圖(<textures>中各項(xiàng))。
            • 讀取.gridinfo 文件,此文件中存放著每個(gè)格子對(duì)應(yīng)的紋理坐標(biāo)。
            • 根據(jù)3,4,5步的信息用修改過(guò)的ETM創(chuàng)建Terrain。
            • 讀取lightmap, 是png格式的預(yù)處理的場(chǎng)景陰影圖。
            • 讀取場(chǎng)景中的各種模型等,并插入到場(chǎng)景Root中。

            (注:天龍八部的場(chǎng)景包含很多個(gè)文件,用“劒蚩”的資源提取工具提取出來(lái),文件夾下的基本都是,但我暫時(shí)不考慮尋路,碰撞等,所以就地形來(lái)講只研究.Terrain文件,.Gridinfo文件。 資源提取的問(wèn)題可訪問(wèn)http://www.cnitblog.com/sword/category/5167.htmlScene )

             

            下面我分幾個(gè)部分來(lái)具體講如何實(shí)現(xiàn)天龍八部的場(chǎng)景Demo。

            讀取高度圖

            做地形首先肯定是要讀取高度圖,《天龍八部》的高度圖是保存在.Heightmap文件中,讀取的方法是跳過(guò)前面8個(gè)字節(jié),讀地形的width和height,然后讀取width*height個(gè)float型數(shù)據(jù),上面說(shuō)到.Terrain文件中有地形大小(xsize, ysize),縮放值(<scale>),地圖中心坐標(biāo)(<center>),<scale>中有xyz 3個(gè)值(一般情況下是100,100,100),分別是x,y,z軸的放大系數(shù),用ETM創(chuàng)建地形的時(shí)候,直接用讀取到的float型數(shù)據(jù)作為高度圖數(shù)據(jù),然后再用上面那些值作為參數(shù),定義地形的大小,縮放值,和偏移。

            這是讀取高度圖的代碼,heightMapData是float型的數(shù)組,存放原始的高度圖信息。

            void TileTerrainInfo::LoadHightMap( const char* fileName, const char* type )
            {
            FILE* pf = fopen( fileName, "rb" );
            fseek( pf, 8, SEEK_SET );
            int height, width;
            fread( &width, 4,1, pf );
            fread( &height, 4,1, pf );
            assert( height = this->height+1 );
            assert( width == this->width+1 );
            if( heightMapData )
            delete []heightMapData;
            heightMapData = new float[height*width];
            for( int i = 0; i < height; ++i )
            {
            for( int j  = 0; j < width; ++j )
            {
            float data;
            fread( &data, 4,1,pf );
            heightMapData[i*width+j] = data;
            }
            }
            fclose( pf );
            }
             

            材質(zhì)文件的分析

            我想先講一下地形的材質(zhì),因?yàn)橛脛e人的資源,首先要知道怎么用這些資源,一般情況下材質(zhì)信息可以明顯地反映出如何使用紋理資源(不排除有可能用代碼動(dòng)態(tài)生成材質(zhì))。

            在每個(gè).Terrain文件的最下面,有這些內(nèi)容。

              <materials>
                <template material="Terrain/OneLayer" name="OneLayer"/>
                <template material="Terrain/OneLayerLightmap" name="OneLayerLightmap"/>
                <template material="Terrain/TwoLayer" name="TwoLayer"/>
                <template material="Terrain/TwoLayerLightmap" name="TwoLayerLightmap"/>
                <fog_replacement exp="Terrain/OneLayer_ps%fog_exp" exp2="Terrain/OneLayer_ps%fog_exp2" linear="Terrain/OneLayer_ps%fog_linear" none="Terrain/OneLayer_ps"/>
                <fog_replacement exp="Terrain/TwoLayer_ps%fog_exp" exp2="Terrain/TwoLayer_ps%fog_exp2" linear="Terrain/TwoLayer_ps%fog_linear" none="Terrain/TwoLayer_ps"/>
                <fog_replacement exp="Terrain/OneLayerLightmap_ps%fog_exp" exp2="Terrain/OneLayerLightmap_ps%fog_exp2" linear="Terrain/OneLayerLightmap_ps%fog_linear" none="Terrain/OneLayerLightmap_ps"/>
                <fog_replacement exp="Terrain/TwoLayerLightmap_ps%fog_exp" exp2="Terrain/TwoLayerLightmap_ps%fog_exp2" linear="Terrain/TwoLayerLightmap_ps%fog_linear" none="Terrain/TwoLayerLightmap_ps"/>
              </materials>

            定義了一些材質(zhì)模板。

            我沒(méi)有深究其他的,只考慮TwoLayerLightmap這個(gè)材質(zhì)。

            不記得是在哪個(gè)文件夾下,有一個(gè)文件FairyTerrain.material,其中就是地形的材質(zhì)。

            我修改了一些內(nèi)容,將<lightmap>設(shè)tex_coord = 0. <layer0>設(shè)tex_coord=1,<layer1>設(shè)tex_coord=2。這是因?yàn)槲蚁胱孍TM原有的地形和天龍八部的地形共存,而原有地形紋理坐標(biāo)剛好和<lightmap>紋理坐標(biāo)相符合,所以設(shè)為同一層。

            這是我改過(guò)的材質(zhì)

            material Terrain/TwoLayerLightmap

               technique
                {
                    pass
                    {
                        fragment_program_ref Terrain/TwoLayerLightmap_ps
                        {
                        }

                        texture_unit
                        {
                            texture_alias <layer0>
                            texture <layer0>
                            tex_address_mode clamp
                 tex_coord_set 1
                        }

                        texture_unit
                        {
                            texture_alias <layer1>
                            texture <layer1>
                            tex_address_mode clamp
                            tex_coord_set 2
                        }

                        texture_unit
                        {
                            texture_alias <lightmap>
                            texture <lightmap>
                            tex_address_mode clamp
                            tex_coord_set 0

                        }
                    }
                }

            }

            <layer0>,<layer1>,<lightmap>是一個(gè)pass中的3個(gè)texture_unit.也就是3層紋理。顧名思義<layer0>是第一層紋理,<layer1>是第二層紋理,<lightmap>是光照?qǐng)D紋理(陰影圖),具體如何使用,如何使天龍八部的地形貼圖資源對(duì)應(yīng)到layer0,layer1,我下面會(huì)講到。

            從FairyTerrain.cg中我們可以找到對(duì)應(yīng)的shader。
            void TwoLayerLightmap_ps(
                in float2 uv0 : TEXCOORD0,
                in float2 uv1 : TEXCOORD1,
                in float2 uvLightmap : TEXCOORD2,
                in uniform sampler2D layer0,
                in uniform sampler2D layer1,
                in uniform sampler2D lightmap,
                in float4 diffuse : COLOR0,
                in float4 specular : COLOR1,
                out float4 oColour : COLOR)
            {
                float4 c0 = tex2D(layer0, uv0);
                float4 c1 = tex2D(layer1, uv1);
                float3 texturedColour = lerp(c0.rgb, c1.rgb, c1.a);
                float4 lightmapColour = tex2D(lightmap, uvLightmap);
                float4 baseColour = diffuse * lightmapColour;
                float3 finalColour = baseColour.rgb * texturedColour + specular.rgb * (1-c0.a) * (1-c1.a) * lightmapColour.a;
                float3 resultColour = Fogging(finalColour);
                oColour = float4(finalColour, baseColour.a);
            }

            很容易看出其大致思路是<layer1>的alpha值控制<layer0>和<layer1>進(jìn)行混合。

            可見(jiàn),天龍八部的地形應(yīng)該是部分像魔獸一樣的格子式地形,部分權(quán)重圖地形,也就是ETM原有的那種貼圖模式,很多層紋理,然后又1-2層手動(dòng)生成的紋理數(shù)據(jù)控制各層紋理的alpha值,達(dá)到混合的效果,只不過(guò)這里是只有一個(gè)alpha通道來(lái)控制紋理混合。

            兩層紋理的效果比單獨(dú)一層紋理好的多,我用OneLayerLightmap材質(zhì)試過(guò),效果比較赫人...

             

            地形紋理的實(shí)現(xiàn)

            <lightmap>紋理很明顯,是一整張紋理貼到整個(gè)地形,沒(méi)什么好說(shuō)的。

            但<layer0> <layer1>這兩層地形紋理應(yīng)該怎么貼上去呢?

            對(duì)于材質(zhì)中的這兩層紋理,有兩種可能。

            1.<layer0>,<layer1>本身只是材質(zhì)模板中紋理的名字,沒(méi)有實(shí)際意義,在實(shí)際的程序中會(huì)為每一塊地形從材質(zhì)模板繼承一個(gè)模板,然后修改材質(zhì)中紋理的名稱。

            2.在程序中手動(dòng)創(chuàng)建<layer0>,<layer1>。

             

            先說(shuō)兩種不能實(shí)現(xiàn)的方法:

            1. 在程序中手動(dòng)創(chuàng)建<layer0>,<layer1>, 為極大極大的貼圖(和真實(shí)的地形一樣大),該貼圖根據(jù).Terrain和.Gridinfo中的信息來(lái)組成,和lightmap一樣,整個(gè)貼到地形上。

            在小游戲,只有可能一個(gè)屏幕那么大的地形,也許可以用,而且效果可能不錯(cuò),但在這種地形相對(duì)較大的游戲中是不可能的,首先,極大的浪費(fèi)資源,一個(gè)地磚的紋理,可能被用到幾十次幾百次,那么在這個(gè)大紋理中,就會(huì)有幾百個(gè)地磚紋理的拷貝,其次,不可能創(chuàng)建這么大的紋理(硬件不支持?反正我試過(guò)創(chuàng)建不出來(lái)..)

            2. 像ETM一樣,將所有要用到的紋理(假設(shè)有n張)一個(gè)一個(gè)作為texture_unit放在材質(zhì)里面,然后用n/4張手動(dòng)生成的紋理去控制這些紋理的alpha值。這個(gè)方法不是對(duì)于天龍八部的地形不是很現(xiàn)實(shí),一般每個(gè)天龍八部的地形有大概十幾個(gè)不同的紋理,如果用這個(gè)方法,每個(gè)pass一般支持8個(gè)texture_unit,十幾個(gè)紋理,加n/4張控制紋理需要3-4個(gè)pass,效率似乎... 而且我們通過(guò)天龍的材質(zhì)文件可以看出,游戲應(yīng)該不是用的這個(gè)方法來(lái)實(shí)現(xiàn)的。

            3. 每一個(gè)格子都有自己獨(dú)自的材質(zhì),修改每個(gè)格子材質(zhì)中的<layer0>, <layer1>, 改為它需要的材質(zhì)文件,如 "05武當(dāng)\褐色土地底層.jpg” 相當(dāng)于將每一個(gè)格子作為單獨(dú)的mesh。這個(gè)是可以實(shí)現(xiàn)的,我試過(guò),將ETM的TileSize設(shè)為1,然后生成每個(gè)Tile的時(shí)候修改其材質(zhì),成功了,地形也顯示出來(lái)了,完全正確,但幀率..... 呵呵,debug模式下fps 大于0小于1... 到release也許可以到十幾吧,我沒(méi)試,顯然是不能這樣搞的... 

            我最后實(shí)現(xiàn)地形貼圖用的是texture atlas,手動(dòng)創(chuàng)建一張紋理,將所有要用到的地形紋理組合成一張大紋理,然后每一個(gè)頂點(diǎn)設(shè)基于這張大紋理的UV坐標(biāo),texture atlas比每個(gè)格子設(shè)材質(zhì)更好的原因很顯而易見(jiàn),具體可以參考附件中所帶的文章,《“Batch, Batch, Batch:”What Does It Really Mean?》中的第30頁(yè):Batch Breaker: Texture Change.

            下圖就是將wudang.Terrain中

            <textures>

              <textures>

                <texture filename="03南海/巖石海礁01.jpg" type="image"/>

                <texture filename="03南海/巖石海礁03.jpg" type="image"/>

                <texture filename="05武當(dāng)/褐色土地底層.jpg" type="image"/>

                <texture filename="05武當(dāng)/褐色土地上層.tga" type="image"/>

                <texture filename="05武當(dāng)/青磚地底層.tga" type="image"/>

                <texture filename="13鏡湖/鏡湖桃花瓣.tga" type="image"/>

                ... ...

              </textures>

            所定義的所有紋理組合成的一張大紋理。

            可以發(fā)現(xiàn),天龍八部中的地形貼圖大小是不同的,但最大是256x256(就我目前所知),所以我干脆將每一格劃為256x256,共可容納有ROW_SIZExCOL_SIZE張小貼圖,這樣大貼圖的大小應(yīng)該是256*COL_SIZE x 256*ROW_SIZE。 

            我這臺(tái)機(jī)器支持的最大紋理大小似乎為4096x4096,那么理論上因該可以最多容納16*16張小貼圖,綽綽有余了。這樣雖然浪費(fèi)一點(diǎn)空間,但可以很方便地通過(guò)ID索引貼圖坐標(biāo)。

            比如 <pixmap bottom="0.2480469" left="0.00390625" right="0.4960938" textureId="2" top="0.001953125"/> 通過(guò)這樣一塊pixmap的定義,我們可以根據(jù)textureId=2找到它所所在的位置。

            其所在行為textureId/COL_SIZE,所在列為textureId%COL_SIZE。如上面那張大紋理的COLE_SIZE = 8(一行有8張小貼圖)

            所以textureId=2的這張小貼圖所在行row=0,坐在列col=2.

            我們知道紋理坐標(biāo)范圍為0.0f-1.0f,所以textureId=2的小貼圖左上角的UV坐標(biāo)為U = (float)col/COL_SIZE = 0.25f , V = (float)row/ROW_SIZE = 0.0f.

            再根據(jù)pixmap中的信息left ,right, top, bottom 可以計(jì)算出小貼圖四個(gè)點(diǎn)的坐標(biāo)。在創(chuàng)建頂點(diǎn)時(shí)將紋理坐標(biāo)附上即可。

            具體的過(guò)程應(yīng)該是

            1.手動(dòng)創(chuàng)建名字為<layer0>的texture

            代碼如下:

            TexturePtr layer0 = TextureManager::getSingletonPtr()->createManual(
               "<layer0>", "General",TEX_TYPE_2D,
               layerTextureWidth,layerTextureHeight, 1, 3, PF_BYTE_RGBA, TU_WRITE_ONLY );

            2. 將材質(zhì)中的texture_unit <layer1>中的texture_name 由<layer1>改為<layer0>,因?yàn)槲覀儍蓪佑玫氖峭粡埣y理,沒(méi)必要復(fù)制一遍,直接改名指向同一張紋理就行了。

            代碼如下:

            MaterialPtr material (MaterialManager::getSingleton().getByName("Terrain/TwoLayerLightmap"));
            material->getTechnique(0)->getPass(0)->getTextureUnitState( 1 )->setTextureName( "<layer0>");

            3.讀取.Texture文件,將要用到的紋理拼接為大紋理,如上面那張圖。

             

            地形的頂點(diǎn)與索引

             

            若地圖為192x192,它就是應(yīng)該有192*192個(gè)格子。一般情況下的做法下,它應(yīng)該有193*193個(gè)頂點(diǎn),織成一個(gè)網(wǎng)狀,但由于我用的atlas,

            可以知道,每一個(gè)非邊緣的頂點(diǎn)將會(huì)有4個(gè)紋理坐標(biāo)(左上,右上,左下,右下 )

            如下圖

            中間的頂點(diǎn)要同時(shí)負(fù)責(zé)A塊的右下,B塊的左下,C塊的右上,D塊的左上。

            話說(shuō)一個(gè)頂點(diǎn)確實(shí)是同時(shí)又多個(gè)紋理坐標(biāo)的,只要設(shè)置不同的tex_coord。但天龍八部地形貼圖一般有3層,<layer0>,<layer1>,<lightmap>,分別是兩層地形,一層預(yù)處理的陰影。

            一層<lightmap>不用多說(shuō)的,就是一張大紋理,每個(gè)頂點(diǎn)的坐標(biāo)是u=col/terrainColSize, v=row/terrainRowSize.

            另外兩層就是我們需要考慮的,因?yàn)橛袃蓪樱@樣每個(gè)點(diǎn)不止同時(shí)負(fù)責(zé)4塊,要同時(shí)負(fù)責(zé)兩層共8塊,這樣這個(gè)pass的8個(gè)texture_unit都滿了,必須再用一個(gè)pass來(lái)做<lightmap>那一層,效率不行。

            所以只好用另一方法,就是在非邊緣的每一個(gè)位置,將4個(gè)頂點(diǎn)重合在一起,這4個(gè)頂點(diǎn)的紋理坐標(biāo)不同,但位置相同,即每一個(gè)格子都有四個(gè)獨(dú)立的頂點(diǎn),相鄰的兩個(gè)格子有兩個(gè)點(diǎn)重合。

            也就是說(shuō)192x192的地圖,需要有192*192*4個(gè)頂點(diǎn)。索引方式還是差不多,每一個(gè)格子需要6個(gè)索引,所以一共要192*192*6個(gè)索引。

            這樣,ETM中生成頂點(diǎn)和索引的部分代碼都需要改,生成頂點(diǎn)的代碼在void Tile::createVertexData(size_t startx, size_t startz)中,生成索引的代碼在void Tile::createIndexData()中。

            天龍八部的.Terrain文件一般有這么一行<scale x="100" y="100" z="100"/>,說(shuō)明地形在3個(gè)方向都是放大100倍,x,z本是一格大小為1x1為單位的,放大后即為100x100,

            一個(gè)192x192的地形實(shí)際游戲中的大小應(yīng)該為19200*19200,而天龍的坐標(biāo)系是正中間坐標(biāo)為.Terrain文件中的<center>的值,若不存在則中心為(0,0), 正方向?yàn)檎?fù)方向?yàn)樨?fù),所以當(dāng)<center>值為(0,0),192x192的地形實(shí)際坐標(biāo)范圍應(yīng)該是 (-9600,-9600)到(9600,9600)。

            要注意的是不是將所有頂點(diǎn)作為一個(gè)mesh,而是應(yīng)該根據(jù).Terrain文件中的<tileSize>規(guī)定每一個(gè)TerrainTile的大小,每個(gè)TerrainTile中包含tileSize x tileSize 個(gè)地形網(wǎng)格,一個(gè)TerrainTile作為一個(gè)Entity插入到一個(gè)場(chǎng)景節(jié)點(diǎn)。

            頂點(diǎn)位置和索引考慮完了,該是要考慮每個(gè)頂點(diǎn)的紋理坐標(biāo)的問(wèn)題了。

            要給每個(gè)頂點(diǎn)設(shè)UV必須用到.Gridinfo文件中的信息,該文件中定義了每一個(gè)格子對(duì)應(yīng)的紋理信息。

            具體的文件格式可參考,我在這就不贅述了。

            http://m.shnenglu.com/mybios/archive/2009/07/26/91267.html

            此處是正解,其他地方似乎多多少少都有錯(cuò),特別是op=8的時(shí)候,要注意是與對(duì)角線兩邊的兩個(gè)點(diǎn)(不是對(duì)角線上的點(diǎn))從上面復(fù)制到下面。

            如圖1應(yīng)該是將左上角的頂點(diǎn)紋理坐標(biāo)復(fù)制到右下角

            圖2應(yīng)該是將右上角的紋理坐標(biāo)復(fù)制到左下角。         

                    圖1                   圖2

            但還有一處我有不同,op=4的時(shí)候,我覺(jué)得應(yīng)該是順時(shí)針轉(zhuǎn)90度,測(cè)試下來(lái)似乎沒(méi)問(wèn)題。

            這是我的根據(jù)op操作UV坐標(biāo)的代碼,op=4的時(shí)候我貌似確實(shí)是在順時(shí)針轉(zhuǎn)吧……

            void changeGridInfoUV( AutoTexCoord& leftTop, AutoTexCoord& rightTop, AutoTexCoord& leftBottom, AutoTexCoord& rightBottom, uchar state, bool bIndex )
            {
            //0 不變
            //1 圖片水平翻轉(zhuǎn)
            //2 圖片垂直翻轉(zhuǎn)
            //4 順時(shí)針旋轉(zhuǎn)度
            //8 對(duì)角線上方頂點(diǎn)紋理坐標(biāo)復(fù)制到對(duì)角線下方頂點(diǎn)。(與對(duì)角線垂直的兩個(gè)頂點(diǎn))
            uchar res1 = state&1;
            uchar res2 = state&2;
            uchar res3 = state&4;
            uchar res4 = state&8;
            if( res1 != 0 )
            {
            leftTop.Exchange( rightTop );
            leftBottom.Exchange( rightBottom );
            }
            if( res2 != 0 )
            {
            leftTop.Exchange( leftBottom );
            rightTop.Exchange( rightBottom );
            }
            if( res3 != 0 )
            {
            leftTop.Exchange( rightTop );
            leftBottom.Exchange( rightTop );
            rightBottom.Exchange( rightTop );
            }
            if( res4 != 0 )
            {
            // 非正常索引
            if( bIndex ) {
            (leftBottom.setX( rightTop.getX) );
            leftBottom.setY( rightTop.getY() );
            }
            // 正常索引
            else {
            rightBottom.setX( leftTop.getX() );
            rightBottom.setY( leftTop.getY() );
            }
            }
            }

            讀取場(chǎng)景環(huán)境與模型

             

            先階段我讀取了一部分場(chǎng)景,包括環(huán)境和一些模型,粒子等部分還沒(méi)看,所以這個(gè)場(chǎng)景是不完整的,不過(guò)大概的輪廓都出來(lái)了。

            讀取場(chǎng)景其實(shí)就是用TinyXML讀取.Scene中的各種XML項(xiàng),然后根據(jù)讀取的數(shù)據(jù)創(chuàng)建相應(yīng)的場(chǎng)景節(jié)點(diǎn),或設(shè)置相應(yīng)的場(chǎng)景環(huán)境,如霧,skydome等。
            具體代碼下載附件看吧,有點(diǎn)無(wú)聊,都是switch-case語(yǔ)句。
            但有一點(diǎn)一定要注意,在讀取資源前一定要先調(diào)用一個(gè)函數(shù)
            setlocale( LC_CTYPE, "" );
            不然中文路徑或文件名的.mesh文件是讀不了的。
            地形和場(chǎng)景都搞定了,可以看看結(jié)果了!然而,悲劇出現(xiàn)了!
            遠(yuǎn)景的效果圖,很明顯,地形一格一格像有裂縫一樣……

             

            近處的效果圖, 近了以后,就沒(méi)地形的裂縫了……

             

             

            地形裂縫問(wèn)題

            問(wèn)了一下我的一個(gè)學(xué)長(zhǎng),自己也思考些時(shí)間。估計(jì)是由于是用的atlas texture, 然后一定距離后的mipmap和texture filtering,產(chǎn)生了裂縫的問(wèn)題。

            通過(guò)附件中的《Improve Batching Using Texture Atlases 》在Applying Texture Filtering To Atlases節(jié)可以看討論到texture filtering對(duì)texture atlas造成的影響,但是解決方案只是理論上的,并沒(méi)有實(shí)現(xiàn),一個(gè)是寫(xiě)shader,在不同的mipmap下調(diào)整紋理坐標(biāo),另一個(gè)是預(yù)留紋理,就是在已有紋理上加一圈和邊緣相同的像素。文章中還提到:enabling anisotropic filtering minimizes these errors,我試了一下,設(shè)置了filtering anisotropic , 并且將anisotropic_max 設(shè)為最大,結(jié)果卻是略有好轉(zhuǎn),但幀率損失了50fps左右… 也許是我的顯卡太水了?我最后還是沒(méi)采用這個(gè)解決方案。

            我最后的解決方案是

            1,手動(dòng)創(chuàng)建紋理的時(shí)候,設(shè)置其mipmap的級(jí)別最多為3,這樣就不會(huì)有更高級(jí)別的mipmap,導(dǎo)致更嚴(yán)重的失真。

            2,手動(dòng)創(chuàng)建mipmap,而不是讓其自動(dòng)生成。比如原來(lái)是1024*1024大小的貼圖,1級(jí)mipmap的大小應(yīng)該為512*512,默認(rèn)它是自動(dòng)生成的,我設(shè)為手動(dòng)生成,先把個(gè)小貼圖縮小為50%,再把他們組成一張512x512的貼圖作為原來(lái)的貼圖的mipmap,一次類推手動(dòng)生成3層mipmap.這樣情況稍微有了點(diǎn)改善。

            3,小貼圖合成大貼圖之前,將他們統(tǒng)一resize到256*256的大小,在組合成大貼圖,這樣后感覺(jué)裂縫問(wèn)題好轉(zhuǎn)了不少。

            4,預(yù)留紋理坐標(biāo),雖然天龍八部開(kāi)始就預(yù)留了紋理坐標(biāo),可以.Terrain文件中的紋理坐標(biāo)很多都不是絕對(duì)的0.0f 0.25f 0.5f 等,都是一些 0.2480469 ,0.00390625,0.4960938等,我不知道它本是出于什么原因。但我用了這樣的坐標(biāo)還是不行,還是要把它設(shè)地更加靠?jī)?nèi)才能避免裂縫。

            所以讀取紋理坐標(biāo)的時(shí)候加上了一個(gè)fixFloat的過(guò)程,這個(gè)過(guò)程很不科學(xué),但我試了一下似乎有點(diǎn)用處就用上了。

            static void fixFloat( float& f )
            {
            if( f < 0.01f )
            f = 0.005f;
            else if( f > 0.24f && f < 0.25f )
            f = 0.245f;
            else if( f > 0.25f && f < 0.26f )
            f = 0.255f;
            else if( f > 0.49f && f < 0.50f )
            f = 0.495f;
            else if( f > 0.5f && f < 0.51f )
            f = 0.505f;
            else if( f > 0.74f && f < 0.75f )
            f = 0.745f;
            else if( f > 0.75f && f < 0.76f )
            f = 0.755f;
            else if( f > 0.99f )
            f = 0.995f;
            }

             

            這樣也在一定程度上改善了裂縫的問(wèn)題,但有的貼圖看上去會(huì)不太吻合,但總比裂縫好。

            隨后地形基本上看不出有裂縫了,但還是有一點(diǎn)痕跡。

             

            這個(gè)地形裂縫的問(wèn)題困擾了我許久,最后的解決方案我也覺(jué)得不甚滿意,不知道有哪位有好點(diǎn)的解決方案請(qǐng)告訴我。


             

            posted on 2010-02-16 22:15 狂爛球 閱讀(4010) 評(píng)論(12)  編輯 收藏 引用 所屬分類: 圖形編程

            評(píng)論

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(附源碼)(轉(zhuǎn)) 2010-03-05 23:20 流浪の念楓雪

            完整帶資源版本下載( TTLBSceneDemo.rar 162.12M ) 請(qǐng)發(fā)22521973@qq.com,謝謝。  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(附源碼)(轉(zhuǎn)) 2010-03-08 13:49 OGRE 小白

            大哥牛人~小弟剛剛開(kāi)始學(xué)習(xí)OGRE不久,想?yún)⒖家幌履愕挠螒驁?chǎng)景。
            能否傳一份完整版的到我的QQ郵箱~萬(wàn)分感謝!
            369806514@qq.com  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(附源碼)(轉(zhuǎn)) 2010-03-12 22:19 活著的木乃伊

            @OGRE 小白
            124740523@qq.com幫忙傳一份,謝謝了  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(附源碼)(轉(zhuǎn)) 2010-03-19 21:40 壞壞

            370865225@qq.com  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(附源碼)(轉(zhuǎn)) 2010-03-21 20:16 梁藹然

            各位,這篇文章是轉(zhuǎn)載的,代碼我沒(méi)有,要的話去原作者那里問(wèn)。  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(附源碼)(轉(zhuǎn)) 2010-05-06 11:56 lzhkpt

            幫忙傳一份學(xué)習(xí)喔,謝謝  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(附源碼)(轉(zhuǎn)) 2010-05-06 11:56 lzhkpt

            @lzhkpt
            額,剛才忘了留mail了。。。lzhkpt@gmail.com  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(附源碼)(轉(zhuǎn)) 2010-05-22 16:44 zyo

            10189471@qq.com  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(附源碼)(轉(zhuǎn)) 2010-05-25 08:23 aliu

            大俠,傳一份~~aliu927@126.com  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(轉(zhuǎn)) 2011-08-04 01:11 OlegIsakov33

            раскрутка сайта, <a href="http://top5.com.ua">оптимизация</a>, продвижение  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(轉(zhuǎn)) 2012-06-01 20:24 os

            您好,我也在做地形,麻煩給我也發(fā)一份資源加源碼完整版,向高手學(xué)習(xí)一下~
            348732178@qq.com  回復(fù)  更多評(píng)論   

            # re: 修改ETM,用Ogre實(shí)現(xiàn)《天龍八部》地形與部分場(chǎng)景詳解(轉(zhuǎn))[未登錄](méi) 2012-08-04 22:59 ds

            dsf  回復(fù)  更多評(píng)論   

            亚洲国产成人久久一区WWW| 久久天天日天天操综合伊人av| 777久久精品一区二区三区无码| 1000部精品久久久久久久久| 亚洲一区精品伊人久久伊人| 97久久国产亚洲精品超碰热| 狠狠色丁香久久婷婷综合五月 | 国产精品美女久久久网AV| 欧美粉嫩小泬久久久久久久| 色天使久久综合网天天| 亚洲中文字幕无码久久2020| 麻豆精品久久久久久久99蜜桃| 亚洲国产成人久久一区久久| 久久国产欧美日韩精品| 日韩十八禁一区二区久久| 人妻精品久久无码区| 久久99精品国产麻豆婷婷| 新狼窝色AV性久久久久久| 久久亚洲2019中文字幕| 91精品国产色综合久久| 久久久久久亚洲精品影院| 久久久91人妻无码精品蜜桃HD| 国产精品久久久久aaaa| 一本色综合网久久| 久久久久亚洲AV无码观看| 人人狠狠综合久久亚洲| Xx性欧美肥妇精品久久久久久| 久久亚洲精品无码AV红樱桃| 久久亚洲AV成人无码| 欧美一区二区久久精品| 无码任你躁久久久久久久| 久久青青草原精品影院| 亚洲乱亚洲乱淫久久| 国产精久久一区二区三区| 伊人久久综合热线大杳蕉下载| 久久人人爽人人爽人人片AV不| 亚洲乱码精品久久久久..| 99久久国产精品免费一区二区| 久久久久亚洲av综合波多野结衣| 久久丫忘忧草产品| 漂亮人妻被黑人久久精品|