1

I started learning opengl and I'm at the stage of tessellation and I have problem, my triangle won't displaying when I attach tesselation shaders to program. Shaders compile correctly and there is no linking error. Everything seems to be fine from the code side. When i only use vertex shader and fragment shader everything works good. What could be the reason?

Shaders::Shaders(const char* vertexPath, const char* fragmentPath, const char* tessControlPath, const char* tessEvaluationPath)
{
    std::string vs_str = load_file(vertexPath);
    std::string fs_str = load_file(fragmentPath);
    std::string tc_str = load_file(tessControlPath);
    std::string te_str = load_file(tessEvaluationPath);
    const char* vs_src = vs_str.c_str();
    const char* fs_src = fs_str.c_str();
    const char* tc_src = tc_str.c_str();
    const char* te_src = te_str.c_str();

    create_shader(GL_VERTEX_SHADER, vertexShader, vs_src);
    create_shader(GL_FRAGMENT_SHADER, fragmentShader, fs_src);
    create_shader(GL_TESS_CONTROL_SHADER, tessControlShader, tc_src);
    create_shader(GL_TESS_EVALUATION_SHADER, tessEvaluationShader, te_src);

    program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glAttachShader(program, tessControlShader);
    glAttachShader(program, tessEvaluationShader);
    glLinkProgram(program);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glDeleteShader(tessControlShader);
    glDeleteShader(tessEvaluationShader);

    glCreateVertexArrays(1, &vertexArrayObject);
    glBindVertexArray(vertexArrayObject);
}
void Shaders::create_shader(GLenum type, GLuint& shader, const char* src)
{
    GLint isCompiled = 0;
    shader = glCreateShader(type);
    glShaderSource(shader, 1, &src, nullptr);
    glCompileShader(shader);
    glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
    if (isCompiled == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
        std::vector<GLchar> errorLog(maxLength);
        glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
        for (int i = 0; i < errorLog.size(); i++)
        {
            std::cerr << errorLog[i];
        }
        glDeleteShader(shader);
    }
}

int main()
{
    Window* window = new Window(1200, 1000);
    Shaders* shader = new Shaders("shaders/vertex.glsl", "shaders/fragment.glsl", "shaders/tess_control.glsl", "shaders/tess_evaluation.glsl");

    while (glfwWindowShouldClose(window->get_window()) == false)
    {
        window->loop();
        const GLfloat color[]{1.0f, 0.5f, 0.5f, 1.0f};
        glClearBufferfv(GL_COLOR, 0, color);

        const GLfloat attrib[]{0.0f, 0.0f, 1.0f, 1.0f};

        glUseProgram(shader->get_program());
        glVertexAttrib4fv(0, attrib);

        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        glDrawArrays(GL_PATCHES, 0, 3);
    }

    delete window;
    delete shader;
    glfwTerminate();
}

vertex.glsl

#version 450 core

layout (location = 0) in vec4 color;

out VS_OUT
{ 
    vec4 color;
} vs_out;

void main(void)
{
    const vec4 vertices[3] = vec4[3](vec4( 0.25, -0.25, 0.5, 1.0), vec4(-0.25, -0.25, 0.5, 1.0), vec4(0.25, 0.25, 0.5, 1.0));

    gl_Position = vertices[gl_VertexID];
    vs_out.color = color;
}

fragment.glsl

#version 450 core

in VS_OUT
{
    vec4 color;
} fs_in;

out vec4 color;

void main(void)
{
    color = fs_in.color;
}

tess_control.glsl

#version 450 core

layout (vertices = 3) out;

void main(void)
{
    if (gl_InvocationID = 0)
    {
        gl_TessLevelInner[0] = 5.0;
        gl_TessLevelOuter[0] = 5.0;
        gl_TessLevelOuter[1] = 5.0;
        gl_TessLevelOuter[2] = 5.0;
    }
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}

tess_evaluation.glsl

#version 450 core

layout (triangles, equal_spacing, ccw) in;

void main(void)
{
    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position);
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Michal566
  • 13
  • 2

1 Answers1

0

You have specifies the number of vertices that will be used to make up a single patch primitive, by glPatchParameteri:

glPatchParameteri(GL_PATCH_VERTICES, 3);
glDrawArrays(GL_PATCHES, 0, 3);

Further more you have to pass the color all the way, through all the shader stages, from the vertex shader to the fragment shader:

The input to the Tessellation Control Shader is a patch and the output is patch too. But the input patch size can be different of the output patch size. While the input patch size is defined by GL_PATCH_VERTICES, the output patch size is define by layout (vertices = 3) out. Thus you have to specify, in the shader program, how the attributes of the input patch are mapped to the attributes of the output patch.

#version 450 core

layout (vertices = 3) out;

in VS_OUT
{ 
    vec4 color;
} in_data[];

out VS_OUT
{ 
    vec4 color;
} out_data[];

void main(void)
{
    out_data[gl_InvocationID].color = in_data[gl_InvocationID].color;
    if (gl_InvocationID = 0)
    {
        gl_TessLevelInner[0] = 5.0;
        gl_TessLevelOuter[0] = 5.0;
        gl_TessLevelOuter[1] = 5.0;
        gl_TessLevelOuter[2] = 5.0;
    }
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}

The Tessellation Evaluation Shader performs the interpolation. The attributes of the output patch of the tessellation control shader are interpolated dependent on gl_TessCoord.
You have to implement the algorithm which interpolates the attributes in the shader program.

#version 450 core

layout (triangles, equal_spacing, ccw) in;

in VS_OUT
{ 
    vec4 color;
} in_data[];

out VS_OUT
{ 
    vec4 color;
} out_data;

void main(void)
{
    out_data.color = in_data[0].color * gl_TessCoord.x + in_data[1].color * gl_TessCoord.y + in_data[2].color * gl_TessCoord.z;
    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position);
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Very thanks but it still doesn't work, maybe something with my graphics card? – Michal566 Mar 29 '20 at 17:19
  • @Michal566 No, I don't think so. Probably there is another bug in you application. – Rabbid76 Mar 29 '20 at 17:20
  • @Michal566 First off all recommend to evaluate, weather the shader program si compiled and linked successfully. For an example code, see the answer to **[this](https://stackoverflow.com/questions/59235204/light-shows-but-the-cube-does-not-appear/59236020#59236020)** or **[this](https://stackoverflow.com/questions/53218925/opengl-ignores-quads-and-makes-them-triangles/53220726#53220726)** question. – Rabbid76 Mar 29 '20 at 17:26