菜鸟学习OGRE和天龙八部之四: 地表贴图的实现

本文分享了天龙八部游戏地形加载的过程及遇到的问题。作者详细介绍了两种生成网格的方法及其优缺点,并探讨了四种不同的材质实现方案。此外,还提供了具体的代码示例,帮助读者更好地理解地形材质的生成流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

国庆大假,没耍成,天天写代码,悲剧...

地表我已经成功载入,也走了不少弯路...犯了很多低级错误...不然半天都可以搞定的事情,郁闷

 

天龙八部的地表算是比较难搞的了,至少我这样认为,由于自己没多少OGRE经验,不清楚地形的载入过程,于是看TSM源码,

 

发现TSM真是破,破到无法解释啊,居然只支持一个地图一个纹理,看着天龙里面几十个纹理,我只有叹气啊

 

于是打算用ETM,发现ETM用了shade,和天龙的做法完全不同,天龙的地表做法很落后...估计是为了兼容老的显卡吧,

 

没有现成的管理器可以用,就自己做啦,既然每个网格都可能有不同的材质,那就把材质相同的网格做成一个mesh

 

具体方法有2种:

 

第一种:手动生成网格mesh,把材质相同的做成一个mesh, 注意最好分tile,把一个tile内的相同材质的网格才做出一个mesh,不然会提交整个地型的顶点,关于分tile,不再多说.

 

第二种:每个网格做一个mesh,生成一个实体, 再把材质相同的实体用staticgemety合并成一个实体, staticgemety只对材质相同的实体有效果, staticgemety的划分tile也十分方便,直接调用sg->setRegionDimensions();这个函数分区就行,

 

对比2种方法,第二种操作要简单一点点,因为生成单个网格实体和分tile都很容易,

 

至于怎么生成一个mesh,也有2中方发,手动生成mesh和使用manulObject

 

显然用manulObject更简单,都不用自己去操作硬件缓存,

 

思路就这些,思路有了,做起来就不成问题了

 

-------------------------------------------------------------------------------------

然后是材质问题

 

天龙只提供了一个材质模板,意味着地形的材质要我们去继承

显然不适合写个文件去继承,只有在程序中实现了

至于方法,也有4种至少:

第一种: 最囧的,在外部做一个material脚本....

第二种: 不用模板,直接代码生成材质,再操作材质的具体数据,麻烦

第三种: 直接用做一个字符串拼接成material脚本那样的格式,载入materialManager解析

第四种: 直接代码clone材质模板,再用别名更改纹理即可,小弟用的第4种

 

 

附上源码:


  1. void
     TLBBTerrain::createLightMaterial()  
  2. {  
  3.     int tempIndex = -1;  
  4.     for(int i = 0; i < mXSize*mZSize; ++ i){  
  5.         // 如果此材质已经存在  
  6.         if((tempIndex = findSameMaterial(mGridData[i], i)) >= 0){  
  7.             // 用已有材质存入数组  
  8.             mLightMaterialData.push_back(mLightMaterialData[tempIndex]);  
  9.         }else{    
  10.   
  11.             if(mGridData[i].nSecondLayer >= 0 && mGridData[i].nFirstLayer >= 0){ // 看第二层是否存在,  
  12.                 // 拷贝第二层材质  
  13.                 MaterialPtr materialTemplate = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[3])); // 先获得材质模板  
  14.                 if(materialTemplate.isNull()){  
  15.                     OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Material "+mTemplateData[0]+"doesn't exist!","TLBBTerrain::createMaterial");  
  16.                 }else{  
  17.   
  18.                     String newMaterialName = "material"+StringConverter::toString(mMaterialNum); // 材质名字  
  19.                     MaterialPtr newMaterial = materialTemplate->clone(newMaterialName);    // 克隆材质   
  20.                     AliasTextureNamePairList aliasList;          // 存储纹理别名的二叉树   
  21.                     String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];  
  22.                     String textureName2 = mTextureData[mPixMapData[mGridData[i].nSecondLayer].textureId];  
  23.                     aliasList["<layer0>"] = textureName1;  
  24.                     aliasList["<layer1>"] = textureName2;  
  25.                     aliasList["<lightmap>"] = mLightMapName;  
  26.                     newMaterial->applyTextureAliases(aliasList); // 用纹理别名更改纹理                                    
  27.                     mLightMaterialData.push_back(newMaterialName);    // 存入材质数组  
  28.                 }  
  29.   
  30.             }else if(mGridData[i].nFirstLayer >= 0){  
  31.                 // 拷贝第一层材质  
  32.                 MaterialPtr materialTemplate = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[1])); // 先获得材质模板  
  33.                 if(materialTemplate.isNull()){  
  34.                     OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Material "+mTemplateData[0]+"doesn't exist!","TLBBTerrain::createMaterial");  
  35.                 }else{  
  36.                     String newMaterialName = "material"+StringConverter::toString(mMaterialNum);      // 材质名字  
  37.                     MaterialPtr newMaterial = materialTemplate->clone(newMaterialName);    // 克隆材质   
  38.                     AliasTextureNamePairList aliasList;           // 存储纹理别名的二叉树   
  39.                     String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];  
  40.                     aliasList["<layer0>"] = textureName1;  
  41.                     aliasList["<lightmap>"] = mLightMapName;  
  42.                     newMaterial->applyTextureAliases(aliasList);  // 用纹理别名更改纹理                                    
  43.                     mLightMaterialData.push_back(newMaterialName);     // 存入材质数组  
  44.                 }  
  45.                   
  46.             }  
  47.   
  48.             ++ mMaterialNum;  
  49.         }  
  50.     }  
  51. }  

-----------------------------------------------------------------------------------------------------------------------------------------------

然后说说图片的翻转操作问题

 

enum Operate
{
 FLIP_HORIZINTAL = 1,    // 图片水平翻转,即左右翻转
 FLIP_VERTICAL = 2,       // 图片垂直翻转,即上下翻转
 ANTICLOCKWISE_90 = 4,    // 逆时针旋转90度
 FLIP_DIAGONAL = 8       // 以三角形的对角线镜像,IndexOrder==0时就把左上的纹理坐标复制到右下,否则把右上的坐标复制到左下
};

 

1,2,4,8 这些数字的二进制的低位,就是0001   0010  0100  1000 

他们可以叠加, 但是也很容易查找到具体含有什么属性,按位与,就查找到是否具有某属性,这是游戏常用的方法

 

由于可有有多个操作叠加,所以更改纹理坐标的时候,一定要相对上一次的坐标操作,

 

 ------------------------------------------------------------------------------------------------------------------------------------

 

 

1024*768 32位模式下.debug版本截图,由于暂时没分tile,顶点数据有点多哈~~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值