Я пытаюсь реализовать простую программу тесселяции на основе этот руководство.
Это мои шейдеры:
Vertex:
#version 410 core
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
in vec4 vPosition;
in vec3 vNormal;
// Input for the tesselation control shader
smooth out vec3 vEyePos_TCS;
smooth out vec3 vNorm_TCS;
void main()
{
vNorm_TCS = normalize(normalMatrix * vNormal);
vEyePos_TCS = vec3(mvMatrix * vPosition);
}
Контроль тесселяции:
#version 410 core
// Define the number of CPs in the output patch
layout (vertices = 3) out;
uniform vec3 eyePos;
in vec3 vEyePos_TCS[];
in vec3 vNorm_TCS[];
// Output for the tesselation evaluation shader
out vec3 vEyePos_TES[];
out vec3 vNorm_TES[];
float GetTessLevel(float dist0, float dist1)
{
float avgDist = (dist0 + dist1) / 2.0;
if (avgDist <= 10.0)
return 5.0;
else if (avgDist <= 15.0)
return 3.0;
else
return 1.0;
}
void main()
{
// Set the control points of the output patch
vEyePos_TES[gl_InvocationID] = vEyePos_TCS[gl_InvocationID];
vNorm_TES[gl_InvocationID] = vNorm_TCS[gl_InvocationID];
// Calculate the distance from the camera to the three control points
float dist0 = distance(eyePos, vEyePos_TES[0]);
float dist1 = distance(eyePos, vEyePos_TES[1]);
float dist2 = distance(eyePos, vEyePos_TES[2]);
// Calculate the tesselation levels
gl_TessLevelOuter[0] = GetTessLevel(dist1, dist2);
gl_TessLevelOuter[1] = GetTessLevel(dist2, dist0);
gl_TessLevelOuter[2] = GetTessLevel(dist0, dist1);
gl_TessLevelInner[0] = gl_TessLevelOuter[2];
}
Оценщик тесселяции:
#version 410 core
layout(triangles, equal_spacing, ccw) in;
uniform mat4 pMatrix;
in vec3 vEyePos_TES[];
in vec3 vNorm_TES[];
// Input for the geometry shader
out vec3 vEyePos_GS;
out vec3 vNorm_GS;
vec3 interpolate3D(vec3 v0, vec3 v1, vec3 v2)
{
return vec3(gl_TessCoord.x) * v0 + vec3(gl_TessCoord.y) * v1 + vec3(gl_TessCoord.z) * v2;
}
void main()
{
// Interpolate the attributes of the output vertex using the barycentric coordinates
vNorm_GS = interpolate3D(vNorm_TES[0], vNorm_TES[1], vNorm_TES[2]);
vEyePos_GS = interpolate3D(vEyePos_TES[0], vEyePos_TES[1], vEyePos_TES[2]);
gl_Position = pMatrix * vec4(vEyePos_GS, 1.0);
}
Геометрия:
#version 410
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in vec3 vEyePos_GS[];
in vec3 vNorm_GS[];
out vec3 vEyePos_FS;
out vec3 vNorm_FS;
out vec3 gTriDistance;
void main()
{
vNorm_FS = vNorm_GS[0];
vEyePos_FS = vEyePos_GS[0];
gTriDistance = vec3(1, 0, 0);
gl_Position = gl_in[0].gl_Position;
EmitVertex();
vNorm_FS = vNorm_GS[1];
vEyePos_FS = vEyePos_GS[1];
gTriDistance = vec3(0, 1, 0);
gl_Position = gl_in[1].gl_Position;
EmitVertex();
vNorm_FS = vNorm_GS[2];
vEyePos_FS = vEyePos_GS[2];
gTriDistance = vec3(0, 0, 1);
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
}
Фрагмент:
#version 410 core
uniform vec3 vLightPosition;
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
in vec3 vEyePos_FS;
in vec3 vNorm_FS;
in vec3 gTriDistance;
out vec4 fragColor;
float amplify(float d, float scale, float offset)
{
d = scale * d + offset;
d = clamp(d, 0, 1);
d = 1 - exp2(-2 * d * d);
return d;
}
void main()
{
vec3 L = normalize(vLightPosition - vEyePos_FS);
vec3 E = normalize(-vEyePos_FS);
vec3 R = normalize(-reflect(L, vNorm_FS));
//calculate Ambient Term:
vec4 Iamb = ambientColor;
//calculate Diffuse Term:
vec4 Idiff = diffuseColor * max(dot(vNorm_FS, L), 0.0);
Idiff = clamp(Idiff, 0.0, 1.0);
// calculate Specular Term:
vec4 Ispec = specularColor * pow(max(dot(R, E), 0.0), 0.3 * 128.0);
Ispec = clamp(Ispec, 0.0, 1.0);
fragColor = Iamb + Idiff + Ispec;
float d1 = min( min( gTriDistance.x, gTriDistance.y ), gTriDistance.z );
fragColor = fragColor * amplify( d1, 60, -0.5 ) ;
};
Проблема, с которой я сталкиваюсь, кажется похожей к этому, в котором, когда уровень tess становится выше, поверхность начинает мерцать. Тем не менее, я не мог решить это до сих пор.
Чтобы нарисовать, я просто делаю:
glBindVertexArray(_vao);
LoadUniformVariables();
glPatchParameteri(GL_PATCH_VERTICES, 3);
glDrawArrays(GL_PATCHES, 0, _modelCoordinates.size());
glBindVertexArray(0);
Это мои результаты:
Ну, проблема, казалось, была с моим вызовом рисования и тем, как мои данные были структурированы. Следующее работает правильно:
glBindVertexArray(_vao);
LoadUniformVariables();
glPatchParameteri(GL_PATCH_VERTICES, 3);
glDrawElements(GL_PATCHES, _modelTriangulation.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);