为加载了高度图的地形创建UV坐标?

时间:2019-01-10 20:02:05

标签: c++ opengl terrain

我已经使用高度图图像在OpenGL中创建了一个地形。结果是一个动态分配的数组,该数组包含地形(x,y,z)的所有顶点,步幅为3,如下所示:(firstvertexX,firstvertexY,firstvertexZ,secondvertexX,secondvertexY,thirdvertexZ ...)。

我还计算了法线(以类似的阵列)和地形的假定UV的极差近似值(使用...法线)以进行渲染。渲染完全没有问题,除了正如我说的那样,UV近似值确实很差,并且渲染的纹理在其中具有“多边形”的感觉(使用GL_TRIANGLE_STRIPS)。

我想澄清一下,我希望在OpenGl中而不是在Blender之类的任何其他程序中创建地形。所以我必须以某种方式为上面提到的包含顶点的数组中的每个顶点指定一个UV坐标。我还要说的是,即时通讯并不是在寻找完美的紫外线解决方案(即使有某种解决方案),而是一种进行粗略近似以使结果令人满意的方法。

所以我的问题是:

  1. UV坐标是否需要在0到1的范围内而不考虑地形的宽度和长度?
  2. UV坐标数组的长度必须与顶点数组的长度相同吗?
  3. 是否有任何简单的算法或方法可以指定地形的UV?

渲染的纹理:

Renderedimage

网络上的实际图片:

Actual image

指定创建数组的代码:

for (i = 0; i < terrainGridLength - 1 ; i++) { //z
     for (j = 0; j < terrainGridWidth; j++) { //x

      TerrainVertices[k] =  startW + j + xOffset;
      TerrainVertices[k + 1] =  20 * terrainHeights[(i + 1)*terrainGridWidth + (j)]  + yOffset;
      TerrainVertices[k + 2] =  startL - (i + 1) + zOffset;
      k = k + 3;


      TerrainVertices[k] =  startW +  j +xOffset;
      TerrainVertices[k + 1] = 20 * terrainHeights[(i)*terrainGridWidth + j] +yOffset;
      TerrainVertices[k + 2] =  startL - i  + zOffset;
      k = k + 3;


      float x = RandomFloat(0.16, 0.96);
      TerrainUVs[d] = x* (terrainNormals[ 3*((i+1 )*terrainGridWidth + j)]);
      TerrainUVs[d + 1] = terrainNormals[3* ((i+1 )*terrainGridWidth + j) + 2 ];

      x = RandomFloat(0.21, 0.46);
      TerrainUVs[d+2] = x*(terrainNormals[ 3*((i+1 )*terrainGridWidth + j) +1]);
      d = d + 3;


      x = RandomFloat(0.3, 0.49);
      TerrainUVs[d] = x*(terrainNormals[3* ((i  )*terrainGridWidth + j) ]);
      TerrainUVs[d + 1] = terrainNormals[ 3*((i  )*terrainGridWidth + j)+2 ];

      x = RandomFloat(0.4, 0.85);
      TerrainUVs[d + 2] = x*(terrainNormals[3* ((i )*terrainGridWidth + j) +1]);

      d = d + 3;
    }
}

1 个答案:

答案 0 :(得分:4)

我会尽力解决您所有的问题。

  

1)UV坐标是否需要在0到1的范围内,没有   是否考虑地形的宽度和长度?

UV坐标通常在0到1的空间中,但是如果传入的UV值不是0到1,则处理UV的方式将取决于您如何设置OpenGL来处理这种情况。

您可以使用以下代码告诉纹理采样器将坐标视为自动换行:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

或者,您也可以使用以下代码来钳制UV值:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

在此处查看有关纹理采样器的更多信息: https://www.khronos.org/opengl/wiki/Sampler_Object

  

UV坐标数组的长度是否必须与   顶点数组?

一般来说,是的。在对某些几何图形进行纹理化时,通常每个顶点至少需要一个UV,因此与顶点一样,UVS的数量也应相同。 但是,如果将多个纹理应用于几何图形,则可能会有更多的效果;如果通过其他方法对几何图形进行纹理化,则可能会有所减少,例如使用编写的不需要UVS的片段着色器。 如果对UVS进行索引,也可以减少索引,也就是说,当每个共享相同UV的顶点通过索引引用数组中的相同UV时。但是,如果您想使事情保持简单,只需进行1比1的操作,不要担心重复的事情。

  

有没有什么简单的算法或方法可以指定UV的   地形?

一种简单的方法是将每个三角形纹理化为四边形的一部分。地形应该只是一个四边形网格,这意味着您可以遍历顶点列表,为网格中的每个四边形分配纹理坐标,如下所示:

enter image description here

更好的是,如果您的地形网格在x和z上的尺寸为1,则只需在x和z上插入网格的世界空间坐标并设置纹理采样器即可包装,前提是您的网格未旋转。如果旋转网格,它仍然可以工作,但是纹理不会随之旋转。