OpenGL之紋理地形

OpenGL之紋理地形

地形文檔其實就是灰度圖,每一位灰度(0~255)對應其高度值,由高度值組成的二維點,二維點以沿X軸和Z軸分佈. 而Y軸則代表地形的高度,將這些數據作為網格渲染得到大概的地貌『地形圖』,將『灰度值』剩以『地圖比例』的高地形的高度值,較亮的灰度對應於較高的地形,較暗的灰度對應於較低的地形.

『高度值=灰度值*地圖尺寸比例因子』
『地圖頂點座標=二維點索引*地圖尺寸比例因子』

渲染地形時沿著Z軸方向每個二維點使用GL_TRIANGLE_STRIP繪畫相連的三角形,沿X軸正方向移動按Z字形路線模式來繪製,當達到行的令一端時就移到下一行用同樣的方法進行繪製,如此直至完成繪畫.對地形進行紋理映射,因為紋理是正方形,所以每四個點頂點指定一個紋理,由兩個三角形組成四邊形,每個四邊形對應一個紋理.

除地形圖外還有海平面掩蓋低窪地帶,海平面由四邊形和的高度值組成,再將『水紋理』應用於四邊形使得海水具有真實感.

繪畫紋理地形的C代碼:

void Draw_Terrain(TERRAIN_PTR terrain)

{

// 繪畫紋理地形

glBindTexture(GL_TEXTURE_2D, terrain->grass.ID);

// 紋理顏色與像素顏色相剩

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

for (int z = 0; z < terrain->width – 1; ++z)

{

glBegin(GL_TRIANGLE_STRIP);// 繪畫三角形

for (int x = 0; x < terrain->width; ++x)

{// 一次渲染兩個頂點

float currScaledHeight = terrain->data[z * terrain->width + x] / terrain->scale;

float nextScaledHeight = terrain->data[(z + 1)* terrain->width + x] / terrain->scale;

float color = 0.5f + 0.5f * currScaledHeight / terrain->max_height; // 灰度值

float nextColor = 0.5f + 0.5f * nextScaledHeight / terrain->max_height; // 灰度值

glColor3f(color, color, color);

glTexCoord2f((GLfloat)x / terrain->width * 8.0f, (GLfloat)z / terrain->width * 8.0f);

glVertex3f((GLfloat)(x – terrain->width/2.0f), currScaledHeight,  (GLfloat)(z – terrain->width / 2.0f));

glColor3f(nextColor, nextColor, nextColor);

glTexCoord2f((GLfloat)x / terrain->width * 8.0f, (GLfloat)(z + 1.0f) / terrain->width * 8.0f);

glVertex3f((GLfloat)(x – terrain->width/2.0f), nextScaledHeight, (GLfloat)(z + 1.0f – terrain->width/2.0f));

}

glEnd();

}

// 繪畫水面

glBindTexture(GL_TEXTURE_2D, terrain->water.ID);// 綁定紋理

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);// 重複的紋理

glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);// 紋理座標

glVertex3f(-terrain->width / 2.1f, terrain->water_height, terrain->width / 2.1f);// 頂點座標

glTexCoord2f(terrain->width / 4.0f, 0.0f);

glVertex3f(terrain->width / 2.1f, terrain->water_height, terrain->width / 2.1f);

glTexCoord2f(terrain->width / 4.0f, terrain->width / 4.0f);

glVertex3f(terrain->width / 2.1f, terrain->water_height, -terrain->width / 2.1f);

glTexCoord2f(0.0f, terrain->width / 4.0f);

glVertex3f(-terrain->width / 2.1f, terrain->water_height, -terrain->width / 2.1f);

glEnd();

}

演示程式:下載

  1. 鼠標『左/右』鍵移動相機繞Y軸旋轉
  2. 鼠標『上/下』鍵移動相機繞X軸旋轉

評論