GIS三维地景仿真设计之雾化和纹理

2008-04-09 04:10:28来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

  引言

  通过本系列前几篇文章的介绍,读者已经能够实现一个功能基本完备的数字高程模型(DEM)OpenGL三维仿真软件。本文作为本系列的最后一篇文章将对雾化、纹理等高级技术的使用进行介绍,通过本文,读者能够在前面的基础上实现一个完整的GIS地景仿真应用软件。

  雾化效果

  在真实世界中观察地面目标并不是在真空中进行的,而是有大气的存在,无论空气是干燥还是湿润,总会有或多或少的水蒸汽存在,而且还有少量的尘埃存在。它们的存在使得我们在观察远景目标时将不可避免地产生白茫茫的模糊效果,这种效果在OpenGL中也被称为"雾化"。虽然在现实世界中雾化现象妨碍了我们对远景目标的观察效果,但在仿真处理上如果缺少此效果反而会令人感觉不是那么真实。因此,这里就对雾化效果的实现做一个简单的介绍:

if (m_bFogMode == FALSE){
 // 雾化效果启用切换
 m_bFogMode = TRUE; // 启用雾化处理
 glEnable(GL_FOG);
 glFogi(GL_FOG_MODE, GL_LINEAR); // 采用线性变化的雾化效果
 GLfloat fogColor[] = {0.8f, 0.8f, 0.8f, 1.0}; // 指定雾化颜色
 glFogfv(GL_FOG_COLOR, fogColor);
 glFogf(GL_FOG_START, 1.0); // 指定按线性变化时计算公式的参量
 glFogf(GL_FOG_END, 10000.0);
 glHint(GL_FOG_HINT, GL_DONT_CARE); //规定雾化效果的质量
}else{
 m_bFogMode = FALSE; // 禁用雾化处理
 glDisable(GL_FOG);
}
  这段代码允许使能或禁用雾化效果。如果需要启用雾化效果,首先需要通过glEnable()函数使能雾化效果(调用GL_FOG参数),并需通过glFogi()和glFogfv()指定采用何种方式的雾化效果和雾化颜色。这里采用的是线性变化方式,因此还要通过glFogf()指定按线性变化时计算公式的参量。最后调用的glHint()函数将对雾化效果的质量作出规定。如果需要禁用雾化效果,只需简单的调用glDisable()将GL_FOG选项禁用即可。下图分别为未使用雾化效果和使用了雾化效果的场景。可以看出,启用了雾化效果后的场景更加逼真:

  使用纹理

  由于任何真实场景都是有着复杂纹理的,因此为了达到具有真实感效果的仿真程度还必须对纹理的使用进行处理。这里使用的纹理必须是长、宽相等且均为2的整数次幂的位图。通常多采用当地区域的航拍照片或当地地图等作为纹理进行贴图。下面首先介绍一下纹理贴图的一般技术实现过程。

  在使用纹理时,首先需要指定待使用的纹理图象,并通过auxDIBImageLoad()函数将其载入到内存并保留其指针。将该指针作为参数去调用glGenTextures()创建一个纹理。接下来,通过对glBindTexture()的调用使用来自位图数据生成的典型纹理,并进一步通过glTexImage2D()生成纹理,同时还必须指定当缩小的比原始纹理小时或放大的比原始纹理大时所要采取的滤波方式。最后释放纹理图象所占用的资源。为了应用纹理,还必须做一些其他的辅助性工作,如启用阴影平滑、启用纹理映射、指定前后表面的建模方式等等。下面给出这部分工作的主要实现代码:

glShadeModel(GL_SMOOTH); // 启用阴影平滑
glEnable(GL_TEXTURE_2D); // 启用纹理映射
glPolygonMode(GL_BACK, GL_FILL); // 后表面以面建模完全填充
glPolygonMode(GL_FRONT, GL_FILL); // 前表面以点建模
AUX_RGBImageRec *TextureImage[1]; // 创建纹理的存储空间
memset(TextureImage, 0, sizeof(void*) * 1); // 清除图像记录,确保其内容为空
TextureImage[0] = auxDIBImageLoad(sPath); // 载入纹理位图并返回指针
glGenTextures(1, &m_nTexture[0]); // 创建纹理
glBindTexture(GL_TEXTURE_2D, m_nTexture[0]); //使用来自位图数据生成的典型纹理
 // 生成纹理
 glTexImage2D(GL_TEXTURE_2D, // 2D纹理
 0, // 图像的详细程度
 3, // R,G,B三种数据成分
 TextureImage[0]->sizeX, // 纹理的宽度
 TextureImage[0]->sizeY, // 纹理的高度
 0, // 边框宽度
 GL_RGB, // 图像数据由红、绿、蓝三色数据组成
 GL_UNSIGNED_BYTE, // 组成图像的数据是无符号字节类型的
 TextureImage[0]->data); // 纹理数据的来源
// 缩小得比原始纹理小时采用线形滤波
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// 比放大得原始纹理大时采用线形滤波
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (TextureImage[0]) { // 检查纹理是否存在
 if (TextureImage[0]->data) {// 检查纹理图像是否存在
  free(TextureImage[0]->data); // 释放纹理图像占用的内存
 }
 free(TextureImage[0]); // 释放图像结构
}
  纹理如果创建成功,应当在重绘场景的同时完成纹理到网格单元的贴图,而且这部分工作应当在执行显示列表之前完成。这部分处理的重点在于从纹理到网格单元的贴图,如果处理不好,将会出现纹理贴反、贴倒甚至有漏贴情况出现。为了确保贴图的正确,一般可以比照初始化该模型显示列表的那部分代码,并采取与之相同的网格定义和顶点定义顺序。例如,下面这段代码使用的就是与InitTerrainList()中相同的三角带网格,并且按照左下、左上、右下、右上的次序进行贴图:

glBindTexture(GL_TEXTURE_2D, m_nTexture[0]); // 选择纹理

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:VC实现自动监测光驱状态的改变

下一篇:VC 开发BHO插件——定制你的浏览器

热门词条
热门标签