Почему мой треугольник не отображается после тесселяции? OpenGL - PullRequest
1 голос
/ 29 марта 2020

Я начал изучать opengl, и я нахожусь на стадии тесселяции, и у меня есть проблема, мой треугольник не будет отображаться, когда я присоединяю шейдеры тесселяции к программе. Шейдеры компилируются правильно, и нет ошибок компоновки. Кажется, все хорошо со стороны кода. Когда я использую только вершинный шейдер и фрагментный шейдер, все работает хорошо. В чем может быть причина?

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;
}

фрагмент.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);
}

1 Ответ

0 голосов
/ 29 марта 2020

Вы указываете количество вершин, которые будут использоваться для создания одного примитива патча, с помощью glPatchParameteri:

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

Более того, вы должны передать цвет на всех этапах шейдера, от вершинного шейдера до фрагментного шейдера:

Вход для Тесселяционного управляющего шейдера - это патч, а на выходе тоже патч. Но размер входного патча может отличаться от размера выходного патча. В то время как размер входного патча определяется GL_PATCH_VERTICES, размер выходного патча определяется layout (vertices = 3) out. Таким образом, вы должны указать в программе шейдера, как атрибуты входного патча отображаются на атрибуты выходного патча.

#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;
}

Шейдер оценки тесселяции выполняет интерполяцию. Атрибуты выходного патча шейдера управления тесселяцией интерполируются в зависимости от gl_TessCoord.
Необходимо реализовать алгоритм, который интерполирует атрибуты в программе шейдера.

#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);
}
...