我正在使用曲面细分着色器和补丁在 OpenGL 上构建一个简单的地形,但我在 OpenGL 如何绘制这些补丁方面遇到了麻烦。 OpenGL 生成的三角形对于每个面片以不同的方向绘制,如图所示。
我想知道是否有一个简单的方法来解决这个问题,例如使用一些OpenGL内置参数,或者需要手动重新调整三角形的方向。
我正在使用 OpenGL 4.0。我总共创建了 8 个补丁,我的 tessLevel 设置为 64。
目前,我的代码如下所示:
曲面细分控制着色器
#version 400
layout (vertices = 4) out;
uniform int tessLevel;
#define ID gl_InvocationID
void Preset();
void main()
{
gl_out[ID].gl_Position = gl_in[ID].gl_Position;
if (ID == 0)
{
Preset();
}
}
void Preset()
{
gl_TessLevelOuter[0] = tessLevel;
gl_TessLevelOuter[1] = tessLevel;
gl_TessLevelOuter[2] = tessLevel;
gl_TessLevelOuter[3] = tessLevel;
gl_TessLevelInner[0] = tessLevel;
gl_TessLevelInner[1] = tessLevel;
}
曲面细分评估着色器
#version 400
layout(quads, equal_spacing, cw) in;
uniform vec3 lightPos;
out vec3 tesLightDirection;
vec4 CalculateInterpolatedPosition(float u, float v);
void main()
{
float u = gl_TessCoord.x;
float v = gl_TessCoord.y;
vec4 interpolatedPosition = CalculateInterpolatedPosition(u, v);
tesLightDirection = normalize(lightPos - interpolatedPosition.xyz);
gl_Position = interpolatedPosition;
}
vec4 CalculateInterpolatedPosition(float u, float v)
{
vec4 p0 = gl_in[0].gl_Position;
vec4 p1 = gl_in[1].gl_Position;
vec4 p2 = gl_in[2].gl_Position;
vec4 p3 = gl_in[3].gl_Position;
return p0 * (1 - u) * (1 - v) +
p1 * u * (1 - v) +
p3 * v * (1 - u) +
p2 * u * v;
}
我的补丁是通过以下方式在我的 C++ 程序中构建的:
void Terrain::GenerateVertices()
{
for (int i = 0; i < totalPatches + 1; i++)
{
for (int j = 0; j < totalPatches + 1; j++)
{
vertices.push_back(vec3(j, 0, i));
}
}
for (int i = 0; i < totalPatches; i++)
{
for (int j = 0; j < totalPatches; j++)
{
int startingPoint = i * (totalPatches + 1) + j;
indices.push_back(startingPoint);
indices.push_back(startingPoint + 1);
indices.push_back(startingPoint + totalPatches + 2);
indices.push_back(startingPoint + totalPatches + 1);
}
}
}
void Terrain::Render(mat4 projection, mat4 view)
{
shader.use();
mat4 VPMatrix = projection * view;
shader.setUniform("VP", VPMatrix);
shader.setUniform("M", transform.modelMatrix());
glBindVertexArray(vaoID);
glPatchParameteri(GL_PATCH_VERTICES, 4);
glDrawElements(GL_PATCHES, indices.size(), GL_UNSIGNED_INT, (GLubyte*)NULL);
glBindVertexArray(0);
}
您无法控制网格的三角测量。关于三角测量的工作原理有一些基本保证,但除此之外,这取决于实现。因此,无论您在镶嵌器中做什么,都需要能够使用any(合理的)三角测量。