地形绘制

怎么说呢,什么的地形?其实我觉得地形只是一个狭隘的定义,其实是场景。场景中最基础的部分就是地形,它就像背景颜色一样,很多场景中的模型都是放在地形上的,包括建筑人物之类。所以,我觉得在研究地形的算法的时候,不能仅仅从地形角度去思考,而且要思考这个算法对场景的管理是否有影响。

 

一个无限大的地形,必定需要无限多的顶点,如果要一次性加载和渲染所有的顶点那肯定是不可能的。所以,地形算法中必须有动态加载的内容。在动态加载的过程中,存在一个问题就是数据更新的时机,是每一帧都更新呢?还是在摄像机位置改变后再更新,显然是后者比较好。要想我们渲染的地形拥有客观的帧频率,仅仅动态加载显然是不够的,我们还需要从多个方面入手,基本的思路就是在保障细节的前提下,尽量减少顶点的数量。远处的细节显然是不必要的,因此地形里面LOD技术的存在是合理的,被遮挡的背面可以直接剔除,视锥以外的部分可以先裁剪掉。但是这些技术会产生裂缝和顶点跳跃等缺陷,需要我们在算法中考虑到。经过这么一番努力,似乎我们已经拥有了比较好的效果,但是为降低带宽的压力,我们仍旧可以尝试在GPU端绘制地形,此时我们把地形细节作为纹理传递给GPU。最后我们总结出我们算法需要拥有的能力:

动态加载  LOD  背面剔除  视锥裁剪 裂缝 顶点跳跃 基于GPU的地形绘制 

 

并不是每个算法都具备所有的能力,因此它们有自己的优缺点:

CLOD地形算法:

1.geomipmapping:类似mipmapping的做法,搞几个不同细节等级的地形,然后根据远近的距离选择合适的进行加载。解决裂缝的方式:1.在低级别的边上补充顶点细节使其满足高级别。2.在高级别的边上减少顶点使其满足低级别。

2.QuadTree:比geomipmapping稍微好一点点,但是任然有一些缺陷。

3.ROAM二叉树:比QuadTree算法更简单,但是效率并不一定高,因为是二叉树所以树的层级比较深。

CLOD算法的缺点:

1.在块与块的衔接处容易产生裂缝

2.在移动相机的时候,顶点会出现跳跃的现象,这个取决于块的大小。

3.是实时的,意味着每一帧都需要进行计算,这对于CPU端的计算来说,是不划算的。

4.需要进行遮挡剔除,这个对于离相机近的遮挡尤为需要。

 

Geometry clipmap:是一个基于GPU的地形绘制算法,它其实也是一个LOD算法的变种

因为它是把细节当做纹理传递到GPU实现的,所以就有了个mipmapping级别一样的东西,但是我觉得这种回字算法,放在CPU端其实跟四叉树的算法类似。

 

Half Life2 :也是一个基于GPU的地形算法,用Displacement map取代高度图,我觉得这是一个优点,因为按照特点方向移动顶点的位置,比沿着Y轴的方向移动顶点的位置来的更全面。

 

dynamic tessellation :通过镶嵌来计算地形,这个也会用到位移贴图,说起来应该跟Half Life2是类似的,只不过用tess进行实现。

上述的这三种地形算法,都是基于GPU的,采样GPU的地形算法,减少了CPU的负担,同时也减少了带宽的压力。但是事有一利必有一弊,采用GPU的方式必然会在每一帧都进行计算。这与CPU当视点位置改变的时候才更新数据相比,是一个缺点。前面我看到有人说tess 150W个顶点,跑100帧+没压力,再加之未来的趋势始终是越来越多计算都是放在GPU的,所以我觉得tess这种方式还是会成为趋势的。

 

和不规则网格(irregular-mesh)技术相比,规则的网格有很多优点:

简洁的数据结构、平滑的视觉效果,稳定的渲染速率,合适的分级(graceful degradation),高效的压缩,以及运行时的细节合成(synthesis)。不想深究不规则的网格技术,忽略。

 

 

 可以采用 :地形分块(即切成多个矩形块,每个矩形块独立管理自身顶点及索引数据)+视野分割(仅绘制在视野中的矩形节点)+二级静态索引(备选,即存在粗、细两种粒度的索引缓冲,距摄影机较近则使用细粒度,反之粗粒度)的思路。

灯光方面就是: 环境光+漫射光+镜面高光(冷峻岩石地带使用); 

纹理采样方面:魔兽世界3+1(纹理X3+权重)的思路

 

paging+lod+oc

 

个人更倾向于高度场四叉树+Displacement map的这种方式,其实是相对于把ROAM的细分放到GPU使用镶嵌技术来做。这样减轻了CPU和带宽的负担,也充分利用了GPU的运算能力。由于在送入管道渲染前可以先进行剔除,在渲染时也可以根据视点的距离来调整镶嵌的密度,即便是比较弱的GPU也可以通过减少细分程度来减轻GPU的负担。还有很多其他的方式,tao哥说,不折腾。

 

四叉树 :

1.创建四叉树:根据传入的顶点坐标计算出四叉树的中心位置,四叉树的宽度,然后开始创建每一个叶子node。创建叶子node的时候判断当前node的三角形数量,如果大于最大值就迭代细分子node。所有的叶子节点才有ID3D11Buffer。

2.渲染:渲染的时候肯定是进行迭代了,迭代的时候同时判断是否在视野范围内,如果在就渲染它和它的子。

 

Displacement map:这个需要高度图和法线图,我这么懒的人,要是天上能掉一对就好了。其实就是把四叉树的三角形弄大一点,然后在GPU就细分的余地。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我是一个语言模型AI,无法直接进行编程。但是,我可以为你提供一些编程思路和参考资料。 基于DEM数据的3D地形绘制是一个比较复杂的任务,需要用到计算机图形学、地理信息系统和数学等多个领域的知识。其中,CSGL是一个比较常用的计算机图形学库,可以方便地实现3D绘制和渲染。 下面是一个简单的基于CSGL的绘制3D地形的示例代码: ```c++ #include <GL/glut.h> #include <iostream> #include <fstream> #include <vector> using namespace std; const int WINDOW_WIDTH = 800; const int WINDOW_HEIGHT = 600; int rows, cols; vector<vector<float>> data; void init() { glClearColor(1.0, 1.0, 1.0, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glColor3f(0.0, 0.0, 0.0); for (int i = 0; i < rows - 1; i++) { glBegin(GL_TRIANGLE_STRIP); for (int j = 0; j < cols; j++) { glVertex3f(j, i, data[i][j]); glVertex3f(j, i + 1, data[i + 1][j]); } glEnd(); } glPopMatrix(); glutSwapBuffers(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); } void readDEMData(const char* filename) { ifstream file(filename); file >> rows >> cols; data.resize(rows); for (int i = 0; i < rows; i++) { data[i].resize(cols); for (int j = 0; j < cols; j++) { file >> data[i][j]; } } file.close(); } int main(int argc, char** argv) { if (argc < 2) { cout << "Usage: " << argv[0] << " filename" << endl; return 1; } readDEMData(argv[1]); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0; } ``` 这个程序可以读取一个DEM数据文件,然后绘制出3D地形。其中,读取DEM数据的函数readDEMData()需要根据自己的数据格式进行修改。绘制地形的部分使用了GL_TRIANGLE_STRIP来绘制三角形网格,可以根据需要自行修改。 参考资料: 1. OpenGL Programming Guide: https://www.glprogramming.com/red/ 2. CSGL: https://github.com/csgl/csgl 3. DEM数据格式: https://en.wikipedia.org/wiki/Digital_elevation_model

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值