I'm trying to do some basic tessellation, but I've ran into a strange problem. My glsl code compiles fine, but when I try to render some geometry with it, I get the invalid operation error. I tried to debug this issue with gdebugger, and interestingly it gives me a AP_PROGRAM_LINK_FAILED_ERROR. This is strange because I do check if the linking went right (GL_LINK_STATUS), and I get no errors even if I directly check the linking with glGetError. The geometry that I tried to render works fine with other shaders.
I followed this tutorial: http://prideout.net/blog/?p=48
Here's the glsl code:
[vertex shader]
#version 410
in vec4 in_vertex; //incoming vertex attribute in object space
out cross_shader_data
{
vec3 position;
} o;
void main()
{
o.position = in_vertex.xyz; //pass the data to the TC shader
}
[tessellation control shader]
#version 410
layout(vertices = 3) out; //a patch should consist of 3 vertices, thus essentially defining a vertex
in cross_shader_data
{
vec3 position;
} i[];
out cross_shader_data
{
vec3 position;
} o[];
uniform float tess_level_inner;
uniform float tess_level_outer;
void main()
{
o[gl_InvocationID].position = i[gl_InvocationID].position; //pass the vertex data to the TE shader
if(gl_InvocationID == 0) //define tessellation levels
{
gl_TessLevelInner[0] = tess_level_inner;
gl_TessLevelOuter[0] = tess_level_outer;
gl_TessLevelOuter[1] = tess_level_outer;
gl_TessLevelOuter[2] = tess_level_outer;
}
}
[tessellation evaluation shader]
#version 410
layout(triangles, equal_spacing, ccw) in; //process triangles, using equal spacing, and they'll be in counter-clockwise order
in cross_shader_data
{
vec3 position;
} i[];
out cross_shader_data
{
vec3 position;
vec3 patch_distance;
} o;
uniform mat4 modelviewproj;
void main()
{
vec3 p0 = gl_TessCoord.x * i[0].position;
vec3 p1 = gl_TessCoord.y * i[1].position;
vec3 p2 = gl_TessCoord.z * i[2].position;
o.patch_distance = gl_TessCoord;
o.position = normalize(p0 + p1 + p2); //create the new vertex
gl_Position = modelviewproj * vec4(o.position, 1); //do the transformation before passing to the geometry shader
}
[geometry shader]
#version 410
layout(triangles) in; //process triangles
layout(triangle_strip, max_vertices = 3) out; //spit out triangle strips that consist of max 3 vertices
in cross_shader_data
{
vec3 position;
vec3 patch_distance;
} i[3];
out cross_shader_data
{
vec3 face_normal;
vec3 patch_distance;
vec3 tri_distance;
} o;
uniform mat3 normal_mat;
void main()
{
vec3 a = i[2].position - i[0].position;
vec3 b = i[1].position - i[0].position;
o.face_normal = normal_mat * normalize(cross(a, b)); //transform face normal into view space
o.patch_distance = i[0].patch_distance;
o.tri_distance = vec3(1, 0, 0);
gl_Position = gl_in[0].gl_Position;
EmitVertex();
o.patch_distance = i[1].patch_distance;
o.tri_distance = vec3(0, 1, 0);
gl_Position = gl_in[1].gl_Position;
EmitVertex();
o.patch_distance = i[2].patch_distance;
o.tri_distance = vec3(0, 0, 1);
gl_Position = gl_in[2].gl_Position;
EmitVertex();
}
[pixel shader]
#version 410
in cross_shader_data
{
vec3 face_normal;
vec3 tri_distance;
vec3 patch_distance;
} i;
out vec4 color;
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 n = normalize(i.face_normal);
vec3 l = vec3(0, 1, 0);
float ndotl = max(dot(n, l), 0);
vec3 result = ndotl * vec3(1, 1, 1); //do some lighting
float d1 = min(min(i.tri_distance.x, i.tri_distance.y), i.tri_distance.z);
float d2 = min(min(i.patch_distance.x, i.patch_distance.y), i.patch_distance.z);
result *= amplify(d1, 40, -0.5) * amplify(d2, 60, -0.5); //just some edge outlining
color = vec4(result, 1);
}
Best regards,
Yours3!f