,但由于没有引入随机分布火焰往往看上去相当单调规则,而且火焰总呈线性上升,冷却速度也严格地保持统一速率。要消除以上
问题,可通过引入随机非均匀因素来解决。一种途径是随机布置各点冷却值使火焰冷却过程非均匀化。但由于火焰的模拟过程是实时进行的,为确保动态模拟过程中能顺畅进行,最好用预先创建的冷却位图(见右图)来代替。一般采用在屏幕上随机撒布几千个亮度不同的点并对其应用平滑处理等方法对冷却位图加以填充。通过冷却图中获取的数值来代替原来固定的冷却衰减值效果要好的多,此时的冷却过程改进为Pixel(x,y)=Pixel(x,y)-Coolingmap(x,y) 这样的衰减结果将使火焰的冷却衰减效果更加真实:
p = lightBuf2+imgWidth*2;
pp = coolMap + coolMapWidth*2;
p1 = lightBuf1+imgWidth*2;
p2 = p1 - imgWidth;
p3 = p1 - 1;
p4 = p1 + 1;
p5 = p1 + imgWidth;
for(i=0;i<imgWidth*(imgHeight-4);i++){
//计算某点及其四邻像素均值
c1=(unsigned char)(((UINT)*p1+(UINT)*p2+(UINT)*p3+(UINT)*p4+(UINT)*p5)/5);
c2 = *pp;
if(c1>c2)
c1 -= c2;
*p = c1;
pp++,p++,p1++,p2++,p3++,p4++,p5++; //内存指针修正
}
由于火焰在进行冷却衰减的同时也在进行着火焰的扩散与对流因此必须使这几种效果保持同步,这需要以同对流速度相同的速度向上滚动冷却位图来实现。为减少不必要的操作,滚动是在内存中通过改变冷却位图的垂直偏移量来加以实现:
memcpy(lightBuf1,lightBuf1+imgWidth*3,imgWidth*(imgHeight-3));
经过以上几步处理虽有一定程度的改善,但仍存在一些缺陷,比如生存期、火焰上升速度恒定、在整个空间燃烧等。为使仿真效果更加逼真,可通过设置种子点来对上述缺陷加以改进。同样出于处理速度的考虑,最好将种子点也以位图的形式预先设定,在仿真时直接在内存中通过移动指针来完成对种子点的访问,其主要代码大致如下:
int t = RAND_MAX/5;
topX = (imgWidth - seedMapWidth)/2; //seedMapWidth种子位图宽度
topY = (imgHeight - seedMapHeight)/2; //seedMapHeight种子位图高度
p = lightBuf1 + (topY+2)*imgWidth + topX; //p, unsigned char型指针
ps = seedMap + seedMapWidth*2; //ps, unsigned char型指针
for(j=0;j<(seedMapHeight-4);j++) {
p1 = p; //p1, unsigned char型指针
for(k=0;k<seedMapWidth;k++){
if(*ps != 0){ //ps, unsigned char型指针
if(rand() < t)
*p1 = 255;
}
p1++,ps++; //指针修正
}
p += imgWidth; //指针修正
}
图形加速显示
前面的算法设计中一直很注意减少不必要的运算量以期获得尽可能高的处理速度,但仅靠好的算法远不能取得满意的视觉效果。不少大型游戏尽管场景非常复杂,场景变化快,但玩家很少能感觉到游戏有难以忍受的停顿感。这不仅因为游戏采取了好的算法更重要的是游戏在同玩家交互的过程中大量采用了Direct X技术,该技术是Direct Draw、Direct Sound、Direct 3D等诸多技术的总称。DirectDraw是其中最主要的一个部件,主要负责对图形的加速,并允许
程序员可以直接操作显存、硬件位图映射以及硬件覆盖和换页技术。而且该技术还支持双缓冲和图形换页、3D z-buffers (z缓存)以及z方向(z-ordering)硬件辅助覆盖等许多重要功能。可以看出,通过使用Direct Draw技术将极大改善仿真结果的图形输出效果,能非常流畅地对火焰进行实时的仿真。使用该技术之前必须先进行初试化等预处理工作:
//创建DirectDraw对象(为突出
程序流程,以下均对错误检测进行了省略)
DirectDrawCreate( NULL, &lpDD, NULL );
//取得全屏独占模式
lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN )