为啥我的三角形在镶嵌后不显示? OpenGL

Posted

技术标签:

【中文标题】为啥我的三角形在镶嵌后不显示? OpenGL【英文标题】:Why is my triangle not displayed after tessellation? OpenGL为什么我的三角形在镶嵌后不显示? OpenGL 【发布时间】:2020-03-29 16:21:12 【问题描述】:

我开始学习 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】:

您已通过glPatchParameteri 指定将用于构成单个补丁图元的顶点数:

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

此外,您还必须将颜色一路传递,通过所有着色器阶段,从顶点着色器到片段着色器:

Tessellation Control Shader 的输入是补丁,输出也是补丁。但是输入补丁大小可以与输出补丁大小不同。输入补丁大小由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;

Tessellation Evaluation Shader 执行插值。镶嵌控制着色器的输出补丁的属性根据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);

【讨论】:

非常感谢,但还是不行,可能是我的显卡有问题? @Michal566 不,我不这么认为。您的应用程序中可能还有另一个错误。 @Michal566 首先建议评估,成功编译和链接着色器程序。有关示例代码,请参阅 thisthis 问题的答案。

以上是关于为啥我的三角形在镶嵌后不显示? OpenGL的主要内容,如果未能解决你的问题,请参考以下文章

为啥三角形没有显示在屏幕上(OpenGL 3.3)?

寻找三角形镶嵌的最近邻

为啥这个在opengl中绘制三角形的着色器不会多次运行

为啥我的 OpenGL 对象绘制相对于最后绘制的对象?

为啥 glColorPointer 不给三角形着色 - 以及 opengl es 的其他奇怪的东西

为啥我的三角形对象没有被绘制?