科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件GIS三维地景仿真设计之雾化和纹理

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

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

通过本系列前几篇文章的介绍,读者已经能够实现一个功能基本完备的数字高程模型(DEM)OpenGL三维仿真软件。

作者:青岛郎锐 来源:天极开发 2007年10月16日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
 使用纹理

  由于任何真实场景都是有着复杂纹理的,因此为了达到具有真实感效果的仿真程度还必须对纹理的使用进行处理。这里使用的纹理必须是长、宽相等且均为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]); // 选择纹理
float float_x; // 用来将纹理分割成很小的三角网格
float float_y;
float float_xb;
float float_yb;
// 每一个小网格分别映射纹理的对应三角形区域(顺序同地景网格创建顺序)
for (int i = 0; i < m_nDemX - 1; i++) {
 for (int j = 0; j < m_nDemY - 1; j++) {
  glBegin(GL_TRIANGLE_STRIP); // 开始三角带
  float_x = float(i) / float(m_nDemX);
  float_y = float(j) / float(m_nDemY);
  float_xb = float(i + 1) / float(m_nDemX);
  float_yb = float(j + 1) / float(m_nDemY);
  glTexCoord2f(float_x, float_y); // 第一个纹理坐标 (左下角)
  glVertex3d(m_pDemX[j * m_nDemX + i], m_pDemY[j * m_nDemX + i], m_pDemH[j * m_nDemX + i]);
  glTexCoord2f(float_x, float_yb); // 第二个纹理坐标 (左上角)
  glVertex3d(m_pDemX[(j + 1) * m_nDemX + i], m_pDemY[(j + 1) * m_nDemX + i], m_pDemH[(j + 1) * m_nDemX + i]);
  glTexCoord2f(float_xb, float_y); // 第三个纹理坐标 (右下角)
  glVertex3d(m_pDemX[j * m_nDemX + i + 1], m_pDemY[j * m_nDemX + i + 1], m_pDemH[j * m_nDemX + i + 1]);
  glTexCoord2f(float_xb, float_yb); // 第四个纹理坐标 (右上角)
  glVertex3d(m_pDemX[(j + 1) * m_nDemX + i + 1], m_pDemY[(j + 1) * m_nDemX + i + 1], m_pDemH[(j + 1) *  m_nDemX + i + 1]);
  glEnd(); // 停止定义三角带
 }
}
}

  其中,glTexCoord2f()定义的是在纹理中的坐标,glVertex3d()定义的是在网格模型中的坐标,通过这两组坐标的定义将纹理和与之对应的网格绑定起来。使用了纹理的地景模型不仅更加逼真,而且可以通过使用不同类型的纹理而获取到不同的信息。下图给出的是经过纹理贴图后的地景模型。其中左图采用的纹理是由法国SPOT遥感卫星PAN全色波段采集的该地区平面遥感影象,通过纹理贴图,可以三维仿真的形式观看该地区的卫星遥感效果。右图将该地区的地图作为纹理使用,贴图后的地景模型可以作为三维电子沙盘使用。

点击放大此图片

  小结

  本文在前面几篇文章的基础之上进一步实现了雾化、纹理贴图等OpenGL高级技术。通过给出的仿真结果可以看出这些高级技术的应用极大改善了地景模型三维仿真的真实感,有效增加了对地景信息的综合利用价值。通过对本系列文章的介绍,读者应当能够对此类三维地景仿真软件的实现、设计过程有一个基本的认识,并可在此基础之上根据具体需求编写出适合自己的GIS应用程序。本文所述程序在Windows 2000 Professional + SP4下由Microsoft Visual C++ 6.0编译通过。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章