[GLSL]渲染大规模地形(多纹理)

演示程序已上传: https://download.csdn.net/download/qq_31804159/10383143

从学习图形学开始,就想做一个关于地形方面的东西(因为看起来比较酷emmm),有一次机会了解到了基于高度图渲染地形。这是一个比较简单的方法,对新手而言比较友好的。其实这个是我好早之前做的一个东西了,但是算是真正进入图形学的一个标志吧,以后我会陆续的把我做的一些有意思的东西分享给大家,也很希望与你们共同交流进步hhh。好,开始正题!

先附我的实现

下面介绍实现原理:

所谓高度图,其实是一张简单的2D图片,由黑色,白色和之间的灰度所生成。高度图代表了我们地形的低、高点(灰度表示高度)! 通过读取一张高度图的灰度我们去构造三角形网格,模型中某点的x,y坐标可以用图像的x,y坐标表示而z坐标即表示为图像中x,y处的灰度gray(x,y)来表示。

关键代码:

//定义点和纹理数组
QVector vertex;
QVector texture;

//读取地形文件
void terrain::loadTerrain(const QString &filename)
{
   QImage image(filename);
   vertex.clear();
   texture.clear();
//构造三角网格
   for( int i = 0; i< image.height()-1; i++){

       for( int k = 0; k< image.width()-1;k++)
       {

        QVector3D v1(k+0-image.width()/2.0,QColor(image.pixel(k+0,i+0)).red(),i+0-image.height()/2.0);
        QVector3D v2(k+0-image.width()/2.0,QColor(image.pixel(k+0,i+1)).red(),i+1-image.height()/2.0);
        QVector3D v3(k+1-image.width()/2.0,QColor(image.pixel(k+1,i+1)).red(),i+1-image.height()/2.0);
        QVector3D v4(k+1-image.width()/2.0,QColor(image.pixel(k+1,i+0)).red(),i+0-image.height()/2.0);
        vertex.push_back(v1);
        vertex.push_back(v2);
        vertex.push_back(v3);
        vertex.push_back(v1);
        vertex.push_back(v3);
        vertex.push_back(v4);

       }
   }
  //绑定纹理坐标
   for( int i = 0; i < vertex.size(); i++){
       QVector2D tmp( (vertex[i].x()+image.width()/2)/image.width(), (vertex[i].z()+image.height()/2)/image.height()  );
       texture.push_back(tmp);
   }

}


下面的渲染是渲染函数,我是使用着色器渲染的。如果没有用过着色器的同学可以了解一下,或者直接跳过使用固定管线的顶点数组也可。


//渲染
void terrain::renderTerrain(QGLShaderProgram *program)
{
    program->bindAttributeLocation("a_Vertex",0);
    program->enableAttributeArray(0);

    program->bindAttributeLocation("a_TexCoord",1);
    program->enableAttributeArray(1);

    program->setAttributeArray(0,vertex.data());
    program->setAttributeArray(1,texture.data());
    glDrawArrays(GL_TRIANGLES,0,vertex.size());
}

下面简单的贴上我的着色器代码

顶点着色器:


attribute vec3 a_Vertex;
attribute vec2 a_TexCoord;
uniform mat4 MVP_matrix;
varying vec2 v_TexCoord0;
varying vec3 v_position;
void main(void)
{
    gl_Position = MVP_matrix *vec4(a_Vertex,1.0);
    v_position = a_Vertex;
    v_TexCoord0 = a_TexCoord;
}



片元着色器:


uniform sampler2D u_Texture0;
uniform sampler2D u_Texture1;
varying vec2 v_TexCoord0;
varying vec3 v_position;
void main(void)
{

    if(v_position.y > 60)
    gl_FragColor = texture2D(u_Texture0, v_TexCoord0)*0.9;
    else
    {
       float delta =  v_position.y/60;
       gl_FragColor = texture2D(u_Texture0, v_TexCoord0)*delta +
               texture2D(u_Texture1, v_TexCoord0)*(1-delta);
    }

}

在片元着色器中我实现了两个纹理混合,以上的效果图中底面的水波纹和山的纹理即为混合的效果。当然还可以拓展为多个纹理的混合。

 

 

 

你可能感兴趣的:(#,OpenGL,Qt,图形学)