Using this tutorial https://learnopengl.com/Guest-Articles/2021/Tessellation/Tessellation and this tutorial https://www.youtube.com/watch?v=21gfE-zUym8 I implemented tessellation shaders that I haven't been able to get working after debugging for 8 hours. The error message I get is
This is what my window is looking like
This is my tessellation control shader
#version 410 core
// specify control points per output per patch
// control size of input and output arrays
layout(vertices=3) out;
// input from vertex shader
in vec2 vert_coord[];
// output to evaluation shader
out vec2 vertex_coord[];
// for tessellation
uniform mat4 view;
uniform mat4 model;
void main()
{
// pass attributes through
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];
// control tessellation
if(gl_InvocationID==0)
{
/* dynamic tessellation */
// first: define rendering constants to control tessellation
const float MIN_TESS_LEVEL = 4;
const float MAX_TESS_LEVEL = 64;
const float MIN_DISTANCE = 20;
const float MAX_DISTANCE = 800;
// second: transform each vertex into each eye
vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;
vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;
vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;
// third: distance from camera scaled between 0 and 1
float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);
float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);
float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);
// fourth: interpolate edge tessellation level based on closer vertex
float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));
float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));
float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_3));
// fifth: set the corresponding outer tessellation levels
gl_TessLevelOuter[0] = tess_level_1;
gl_TessLevelOuter[1] = tess_level_2;
gl_TessLevelOuter[2] = tess_level_3;
// sixth: set the inner tessellation levels
gl_TessLevelInner[0] = max(tess_level_1, tess_level_3);
gl_TessLevelInner[1] = max(tess_level_1, tess_level_2);
}
}
This is the tessellation evaluation shader
#version 410 core
// from control shader
layout(triangles, equal_spacing, ccw) in;
// input from control shader
in vec2 vertex_coord[];
// output vec
out vec2 vert;
// allows for object transformations and for movement
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
// patch coords
float u = gl_TessCoord.x;
float v = gl_TessCoord.y;
float w = gl_TessCoord.z;
// barycentric interpolation
vec2 tex_coord = u * vertex_coord[0] + v * vertex_coord[1] + w * vertex_coord[2];
// get control coords
vec4 pos_1 = gl_in[0].gl_Position;
vec4 pos_2 = gl_in[1].gl_Position;
vec4 pos_3 = gl_in[2].gl_Position;
// more barycentric interpolation
vec4 pos = u * pos_1 + v * pos_2 + w * pos_3;
// position
gl_Position = model * view * projection * pos;
vert = tex_coord;
}
This is the vertex shader
#version 410 core
// position of the object
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 vert;
out vec2 vert_coord;
void main()
{
// position object
gl_Position = vec4(pos, 1.0f);
vert_coord = vert;
}
This is the fragment shader
#version 410 core
out vec4 color;
void main()
{
color = vec4(0.86f, 0.74f, 0.09f, 1.0f);
}
This is the shader loader for the tessellation shaders
// tess control
tessellation_control_shader = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(tessellation_control_shader, 1, &tessellation_control_shader_text, NULL);
glCompileShader(tessellation_control_shader);
glGetShaderiv(tessellation_control_shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(tessellation_control_shader, 512, NULL, info_log);
printf("Tessellation control shader failed: %s\n", info_log);
perror(info_log);
}
// tess eval
tessellation_evaluation_shader = glCreateShader(GL_TESS_EVALUATION_SHADER);
glShaderSource(tessellation_evaluation_shader, 1, &tessellation_evaluation_shader_text, NULL);
glCompileShader(tessellation_evaluation_shader);
glGetShaderiv(tessellation_evaluation_shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(tessellation_evaluation_shader, 512, NULL, info_log);
printf("Tessellation evaluation shader failed: %s\n", info_log);
perror(info_log);
}
This is the tessellation initialization, vertices, indices and, buffers
#define NUM_PATCH_PTS 3
// shader loading
unsigned int shader_program = load_shaders("vert.glsl", "frag.glsl", "tes_ctrl.glsl", "tes_eval.glsl");
// octahedron, vertices provided by https://gamedev.stackexchange.com/users/39518/dmgregory
unsigned int draw_calls = 48;
float vertices[] = {
//top-north-east
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 0.0, 0.0,
//top-north-west
0.0, 1.0, 0.0,
-1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
//top-south-west
0.0, 1.0, 0.0,
0.0, 0.0, -1.0,
-1.0, 0.0, 0.0,
//top-south-east
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
0.0, 0.0, -1.0,
//bottom-north-east
0.0, -1.0, 0.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
//bottom-north-west
0.0, -1.0, 0.0,
0.0, 0.0, 1.0,
-1.0, 0.0, 0.0,
//bottom-south-west
0.0, -1.0, 0.0,
-1.0, 0.0, 0.0,
0.0, 0.0, -1.0,
//bottom-south-east
0.0, -1.0, 0.0,
0.0, 0.0, -1.0,
1.0, 0.0, 0.0,
};
unsigned int indices[] = {
// first triangle
0, 1, 2,
// second triangle
3, 4, 5,
// third triangle
6, 7, 8,
// fourth triangle
9, 10, 11,
// fifth triangle
12, 13, 14,
// sixth triangle
15, 16, 17,
// seventh triangle
18, 19, 20,
// eighth triangle
21, 22, 23
};
unsigned int vbo, vao, ebo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
// upload vertex data to gpu
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(double), &vertices[0], GL_STATIC_DRAW);
// upload index data to gpu
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// max tessellation points / patches
glPatchParameteri(GL_PATCH_VERTICES, NUM_PATCH_PTS);
This is the draw call
glBindVertexArray(vao);
glDrawArrays(GL_PATCHES, 0, draw_calls*draw_calls*NUM_PATCH_PTS);