上下文:
我正在尝试在openGL中创建一个类似于自然界的开放世界场景。长度为terrainVertices
的数组3*NUM_OF_VERTICES
包含地形的顶点数据,这是一个噪声生成的高度图。每个顶点都有x,y,z
坐标,并根据y
的值为顶点指定某种颜色,从而在深水和山峰之间产生某种平滑过渡。
问题:
当顶点附近具有y值(例如y<0
)时,形成了色淀。着色是按预期执行的,但是结果不现实。看起来像个蓝坑:
我决定解决此问题的方法是通过创建一层顶点,这些顶点出现在湖上,具有y=0
和具有低alpha值的浅蓝色,从而在下面形成一个表面错觉这就是真正的湖泊。
terrainVertices
数组由元素数组elements[NUM_OF_ELEMENTS]
索引。我遍历元素数组并尝试查找索引的三元组,这些索引对应于带有y<0
的顶点。我将与该条件匹配的每个三元组收集到一个向量中,然后创建一个新的顶点数组对象,该顶点数组对象具有与terrain相同的顶点数据,但具有我刚刚描述的新元素缓冲区对象。将位于“水下”的顶点的y值替换为0
,以便粘贴到湖面。
这是我用来完成此操作的代码:
std::vector<GLuint> waterElementsV;
//iterating over every triangle
for (int i = 0; i < NUM_OF_ELEMENTS / 3; i++) {
//accessing each vertex based on its index from the element array
//checking if its height is lower than zero
//elements[3*i+0, +1, +2] represents the indices for a triangle
//terrainVertices[index + 1] represents the height of the vertex
if (terrainVertices[3 * (elements[3 * i]) + 1] < 0 &&
terrainVertices[3 * (elements[3 * i + 1]) + 1] < 0 &&
terrainVertices[3 * (elements[3 * i + 2]) + 1] < 0) {
//since its a valid triangle, add its indices in the elements array.
waterElementsV.push_back(elements[3 * i]);
waterElementsV.push_back(elements[3 * i + 1]);
waterElementsV.push_back(elements[3 * i + 2]);
}
}
//iterating through the terrain vertices, and setting
//each appropriate vertex's y value to water surface level y = 0
for (unsigned int i = 0; i < waterElementsV.size(); i++) {
currentIndex = waterElementsV[i];
terrainVertices[3 * currentIndex + 1] = 0;
}
//get the vector's underlying array
waterElements = waterElementsV.data();
glGenVertexArrays(1, &waterVAO);
glBindVertexArray(waterVAO);
glGenBuffers(1, &waterVerticesVBO);
glBindBuffer(GL_ARRAY_BUFFER, waterVerticesVBO);
glBufferData(GL_ARRAY_BUFFER, NUM_OF_VERTICES, terrainVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
glGenBuffers(1, &waterEBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, waterEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(waterElements), waterElements, GL_STATIC_DRAW);
着色器非常简单,因为我只需要分配一个位置和一种颜色即可。没有使用世界视图投影矩阵,因为无论如何,每个对象都是相对于地形绘制的。
顶点着色器:
#version 330 core
layout (location = 0) in vec3 pos;
void main()
{
gl_Position = vec4(pos, 1.0);
}
片段着色器:
#version 330 core
out vec4 fragColor;
void main()
{
fragColor = vec4(0, 0, 0, 1);
}
结果与上图完全相同。我一直在思考发生了什么事,但似乎无法弄清楚……请注意,这些湖泊分布在随机的地方,不一定彼此相邻。
任何帮助或提示都将不胜感激:)