[GLSL]渲染大規模地形(多紋理)

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

從學習圖形學開始,就想做一個關於地形方面的東西(因爲看起來比較酷emmm),有一次機會瞭解到了基於高度圖渲染地形。這是一個比較簡單的方法,對新手而言比較友好的。其實這個是我好早之前做的一個東西了,但是算是真正進入圖形學的一個標誌吧,以後我會陸續的把我做的一些有意思的東西分享給大家,也很希望與你們共同交流進步hhh。好,開始正題!

先附我的實現

下面介紹實現原理:

所謂高度圖,其實是一張簡單的2D圖片,由黑色,白色和之間的灰度所生成。高度圖代表了我們地形的低、高點(灰度表示高度)! 通過讀取一張高度圖的灰度我們去構造三角形網格,模型中某點的x,y座標可以用圖像的x,y座標表示而z座標即表示爲圖像中x,y處的灰度gray(x,y)來表示。

關鍵代碼:

//定義點和紋理數組
QVector<QVector3D> vertex;
QVector<QVector2D> 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);
    }

}

在片元着色器中我實現了兩個紋理混合,以上的效果圖中底面的水波紋和山的紋理即爲混合的效果。當然還可以拓展爲多個紋理的混合。

 

 

 

發佈了33 篇原創文章 · 獲贊 39 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章