产生地面纹理的方法有很多种,下面介绍一种根据地面高度产生混合纹理的方法。
准备工作:四张贴图,分别为雪地,岩石,草地,沙子。
一张高度图,也就是一张256级灰度的位图。
为简单起见,这五张图的大小最好一样。
目的:产生过渡自然的纹理和3D山脉。 原理:根据高度改变混合因子,再按该因子对贴图上对应的点进行Alpha混合。
步骤:
1.读出每张贴图对应象素的RGB值。
2.从高度图中获得对应点的高度。
3.根据高度计算混合因子,混合第一步得出的RGB值,并写入新纹理的对应位置。
4.重复步骤1,直到所有象素被处理完(如贴图的大小是256*256,则从(0,0)处理到(255,255)),
便可得到一张新的纹理。
5.根据高度图,计算多边形顶点坐标,并设置纹理坐标。
6.剩下的事就交给D3D去做了。
如何计算混合因子?
我们假定山顶是雪地,依次下来是岩石,草地,沙子。
雪地 256-192
岩石 192-128
草地 128-64
沙子 64-0
以下是计算混合因子的函数:
float texfactor(float h1, float h2)//计算雪地的权重时h1=256,岩石h1=192,
{ //草地h1=128,沙子h1=64;h2为该点的实际高度。
float percent;
percent = (64.0f - (h1 - h2)) / 64.0f;
if(percent < 0.0f) percent = 0.0f;
else if(percent > 1.0f) percent = 1.0f;
return percent;
}
以下是作混合的函数:
bitmap tex_gen(bitmap tex[4], bitmap heightmap)
{
float tex_fact[4]; //每种纹理的权重
float hmap_height; //在点(x,y)处的高度
bitmap final_tex; //最后返回的纹理
unsigned char new_r, new_g, new_b; //要返回的新的RGB值
unsigned char old_r[4], old_g[4], old_b[4]; //在点(x,y)处各种纹理的RGB值
for (int y=0; y<256; y++) //遍历256*256的位图
for (int x=0; x<256; x++)
{
hmap_height=heightmap.getheight(x,y); //取得(x,y)处的高度值
tex_fact[0]=texfactor(256, hmap_height);//计算第一种地形的权重
tex_fact[1]=texfactor(192, hmap_height);//计算第二种地形的权重
tex_fact[2]=texfactor(128, hmap_height);//[...]
tex_fact[3]=texfactor( 64, hmap_height);//[...]
for (int i=0; i<4; i++) //读出各种纹理的RGB值
tex[i].getcolor (&old_r[i], &old_g[i], &old_b[i]);
new_r=((tex_fact[0]*old_r[0]) + (tex_fact[1]*old_r[1]) + (tex_fact[2]*old_r[2]) + (tex_fact[0]*old_r[3])); //Compose new r value for final texture
new_g=((tex_fact[0]*old_g[0]) + (tex_fact[1]*old_g[1]) + (tex_fact[2]*old_g[2]) + (tex_fact[0]*old_g[3])); //Same for g
new_b=((tex_fact[0]*old_b[0]) + (tex_fact[1]*old_b[1]) + (tex_fact[2]*old_b[2]) + (tex_fact[0]*old_b[3])); //and b
final_tex.setcolor(x,y, new_r, new_g, new_b); //把新的RGB值写到新纹理对应点上
}
return final_tex;
}
多边形顶点的位置坐标同样根据高度图设置,注意纹理坐标(u,v)要跟贴图紧密对应, 否则就得不到预期的效果了。