OpenGL几何着色器三角形不会没有错误地绘制

Posted

技术标签:

【中文标题】OpenGL几何着色器三角形不会没有错误地绘制【英文标题】:OpenGL Geomentry Shader triangle wont draw with no errors 【发布时间】:2017-01-17 05:35:08 【问题描述】:

我正在尝试编写一个几何着色器,它采用单个 vec4 位置并创建一个三角形。程序链接正确,但是当绘制调用发生时,屏幕上没有显示任何内容。

我有一个工作版本,在我自己计算三角形后将顶点提供给 OpenGL,但我希望让着色器工作,以便可以在 gpu 上创建三角形(以及最终其他形状)反而。这是我的代码:

void TriSprite::v_InitShader(void)

    if(_shaderProgram != NULL) return;

    //=====Vertex Shaders=====
    //This is used when only colors, not textures are used to render
    //a pirmitive
    static const GLchar* _vertexShaderSource[] = 
    
        "#version 430 core                                                              \n"
        "                                                                               \n"
        "layout (location = 0) in vec4 position;                                        \n"
        "layout (location = 1) in vec4 color;                                           \n"
        "layout (location = 2) in float width;                                          \n"
        "layout (location = 3) in float height;                                         \n"                 
        "uniform mat4 transform_mat;                                                    \n"
        "                                                                               \n"
        "out vec4 vs_color;                                                             \n"
        "out vec4 vs_dimnsions;                                                         \n"
        "                                                                               \n"
        "void main(void)                                                                \n"
        "                                                                              \n"
        //=====Top=====
        "   gl_Position = transform_mat * position;                                     \n"
        "   vs_color = color;                                                           \n"
        "   vs_dimnsions = vec4(width, height, 0.0, 0.0);                               \n"
        "                                                                              \n"
    ;

    //=====Geomtry Shader=====
    static const GLchar* _geometryShaderSource[] =
    
        "#version 430 core                                                              \n"
        "                                                                               \n"
        "layout(points) in;                                                             \n"
        "layout(triangle_strip, max_vertices = 2) out;                                  \n"
        "                                                                               \n"
        "in vec4 vs_color[1];                                                           \n"
        "in vec4 vs_dimnsions[1];                                                       \n"
        "                                                                               \n"
        "out vec4 gs_color;                                                             \n"
        "                                                                               \n"
        "void main()                                                                    \n"
        "                                                                              \n"
        //Bottom Right
        "   gl_Position = gl_in[0].gl_Position + vec4(vs_dimnsions[0].x, -vs_dimnsions[0].y, 0, 0);         \n"
        "   EmitVertex();                                                                                   \n"
        //Top
        "   gl_Position = gl_in[0].gl_Position + vec4(0.0, vs_dimnsions[0].y, 0.0, 0.0);                    \n"
        "   EmitVertex();                                                                                   \n"
        //Bottom Left
        "   gl_Position = gl_in[0].gl_Position + vec4(-vs_dimnsions[0].x, -vs_dimnsions[0].y, 0.0, 0.0);    \n"
        "   EmitVertex();                                                                                   \n"
        "                                                                               \n"
        "   EndPrimitive();                                                             \n"
        "   gs_color = vs_color[0];                                                     \n"
        "                                                                              \n"
    ;


    //=====Fragment Shaders=====
    //This is used when only colors, not textures are used to render
    //a pirmitive
    static const GLchar* _fragmentShaderSource[] = 
    
        "#version 430 core                                                              \n"
        "                                                                               \n"
        "in vec4 gs_color;                                                              \n"
        "out vec4 color;                                                                \n"
        "                                                                               \n"
        "void main(void)                                                                \n"
        "                                                                              \n"
        "   color = gs_color;                                                           \n"
        "                                                                              \n"
    ;

    //=====Compile Shaders=====
    GLuint vertextShaderProgram;
    GLuint geometryShaderProgram;
    GLuint fragmentShaderProgram;

    vertextShaderProgram = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertextShaderProgram, 1, _vertexShaderSource, NULL);
    glCompileShader(vertextShaderProgram);

    geometryShaderProgram = glCreateShader(GL_GEOMETRY_SHADER);
    glShaderSource(geometryShaderProgram, 1, _geometryShaderSource, NULL);
    glCompileShader(geometryShaderProgram);

    fragmentShaderProgram = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShaderProgram, 1, _fragmentShaderSource, NULL);
    glCompileShader(fragmentShaderProgram);

    _shaderProgram = glCreateProgram();
    glAttachShader(_shaderProgram, vertextShaderProgram);
    glAttachShader(_shaderProgram, geometryShaderProgram);
    glAttachShader(_shaderProgram, fragmentShaderProgram);
    glLinkProgram(_shaderProgram);

    GLint isLinked = 0;
    glGetProgramiv(_shaderProgram, GL_LINK_STATUS, &isLinked);

    //=====Error Checking=====
    if(isLinked == GL_FALSE)
    
        GLint maxLength = 0;
        glGetProgramiv(_shaderProgram, GL_INFO_LOG_LENGTH, &maxLength);

        //The maxLength includes the NULL character
        std::vector<GLchar> infoLog(maxLength);
        glGetProgramInfoLog(_shaderProgram, maxLength, &maxLength, &infoLog[0]);

        for(auto i = infoLog.begin(); i != infoLog.end(); ++i)
        
            std::cout << *i ;
        

        std::cout << "\n";

        //The program is useless now. So delete it.
        glDeleteProgram(_shaderProgram);

    

    //=====Clean up=====
    glDeleteShader(vertextShaderProgram);
    glDeleteShader(geometryShaderProgram);
    glDeleteShader(vertextShaderProgram);

以及渲染调用:

    void Renderer::AddToBatch(GLuint shader, Vec2& pos, U32 w, U32 h, Col& c)

    if(_currentShader != shader)
    
        Draw();
        _currentShader = shader;

        glUseProgram(_currentShader);
    

    if(_currentBatchSize + 1 >= _maxBatchSize)  Draw(); 

    _vertices.push_back(pos.GetX());
    _vertices.push_back(pos.GetY());
    _vertices.push_back(pos.GetZ());
    _vertices.push_back(pos.GetW());

    _xDimensions.push_back((F32)w);
    _yDimensions.push_back((F32)h);


    _colors.push_back(c.GetRed());
    _colors.push_back(c.GetGreen());
    _colors.push_back(c.GetBlue());
    _colors.push_back(c.GetAlpha());

    ++_currentBatchSize;


    void Renderer::Draw(void)

    if(_currentBatchSize == 0) return;

    GLuint buffers[4];
    glGenBuffers(4, buffers);

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _vertices.size()), &_vertices[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _colors.size()), &_colors[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, NULL);


    glBindBuffer(GL_ARRAY_BUFFER, buffers[2]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(U32) * _xDimensions.size()), &_xDimensions[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, NULL);


    glBindBuffer(GL_ARRAY_BUFFER, buffers[3]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(U32) * _yDimensions.size()), &_yDimensions[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, NULL);


    glDrawArrays(GL_TRIANGLES, 0, _currentBatchSize);

    _currentBatchSize = 0;

任何见解或帮助将不胜感激。

static const GLchar* _vertexShaderSource[] = 
    
        "#version 430 core                                                              \n"
        "                                                                               \n"
        "layout (location = 0) in vec4 position;                                        \n"
        "layout (location = 1) in vec4 color;                                           \n"                 
        "uniform mat4 transform_mat;                                                    \n"
        "                                                                               \n"
        "out vec4 vs_color;                                                             \n"
        "                                                                               \n"
        "void main(void)                                                                \n"
        "                                                                              \n"
        "   gl_Position = transform_mat * position;                                     \n"
        "   vs_color = color;                                                           \n"
        "                                                                              \n"
    ;

static const GLchar* _fragmentShaderSource[] = 
    
        "#version 430 core                                                              \n"
        "                                                                               \n"
        "in vec4 vs_color;                                                              \n"
        "out vec4 color;                                                                \n"
        "                                                                               \n"
        "void main(void)                                                                \n"
        "                                                                              \n"
        "   color = vs_color;                                                           \n"
        "                                                                              \n"
    ;

您会注意到,在此示例中,我直接为着色器提供顶点,并且基本上只是转换它们。这个版本有效。这是基于 cmets 的更新版本。这仍然不起作用:

static const GLchar* _vertexShaderSource[] = 
    
        "#version 430 core                                                              \n"
        "                                                                               \n"
        "layout (location = 0) in vec4 position;                                        \n"
        "layout (location = 1) in vec4 color;                                           \n"
        "layout (location = 2) in float width;                                          \n"
        "layout (location = 3) in float height;                                         \n"                 
        "uniform mat4 transform_mat;                                                    \n"
        "                                                                               \n"
        "out vec4 vs_color;                                                             \n"
        "out vec4 vs_dimensions;                                                        \n"
        "                                                                               \n"
        "void main(void)                                                                \n"
        "                                                                              \n"
        "   gl_Position = transform_mat * position;                                     \n"
        "   vs_color = color;                                                           \n"
        "   vs_dimensions = transform_mat * vec4(width, height, 0.0, 0.0);              \n"
        "                                                                              \n"
    ;

static const GLchar* _geometryShaderSource[] =
    
        "#version 430 core                                                              \n"
        "                                                                               \n"
        "layout(points) in;                                                             \n"
        "layout(triangle_strip, max_vertices = 3) out;                                  \n"
        "                                                                               \n"
        "in vec4 vs_color[1];                                                           \n"
        "in vec4 vs_dimensions[1];                                                      \n"
        "                                                                               \n"
        "out vec4 gs_color;                                                             \n"
        "                                                                               \n"
        "void main()                                                                    \n"
        "                                                                              \n"
        "   gs_color = vs_color[0];                                                     \n"
        //Top
        "   gl_Position = gl_in[0].gl_Position + vec4(0.0, vs_dimensions[0].y, 0.0, 0.0);                   \n"
        "   EmitVertex();                                                                                   \n"
        //Bottom Right
        "   gl_Position = gl_in[0].gl_Position + vec4(vs_dimensions[0].x, -vs_dimensions[0].y, 0, 0);       \n"
        "   EmitVertex();                                                                                   \n"
        //Bottom Left
        "   gl_Position = gl_in[0].gl_Position + vec4(-vs_dimensions[0].x, -vs_dimensions[0].y, 0.0, 0.0);  \n"
        "   EmitVertex();                                                                                   \n"
        "                                                                               \n"
        "   EndPrimitive();                                                             \n"
        "

static const GLchar* _fragmentShaderSource[] = 
    
        "#version 430 core                                                              \n"
        "                                                                               \n"
        "in vec4 gs_color;                                                              \n"
        "out vec4 color;                                                                \n"
        "                                                                               \n"
        "void main(void)                                                                \n"
        "                                                                              \n"
        "   color = gs_color;                                                           \n"
        "                                                                              \n"
    ;


void Renderer::Draw(void)

    if(_currentBatchSize == 0) return;

    GLuint buffers[4];
    glGenBuffers(4, buffers);

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _vertices.size()), &_vertices[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _colors.size()), &_colors[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, NULL);


    glBindBuffer(GL_ARRAY_BUFFER, buffers[2]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(U32) * _xDimensions.size()), &_xDimensions[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, NULL);


    glBindBuffer(GL_ARRAY_BUFFER, buffers[3]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(U32) * _yDimensions.size()), &_yDimensions[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, NULL);


    glDrawArrays(GL_TRIANGLES, 0, _currentBatchSize);

    _currentBatchSize = 0;

【问题讨论】:

你有什么样的变换矩阵?是透视变换吗?你确定宽度和高度传递正确吗? 这是一个正交投影,据我所知,它们正在被传入。在 AddToBatch 调用中正确设置了这些值。对于此测试,w = 200,h = 200。 【参考方案1】:

在单步执行代码并花一些时间查看进出几何着色器的内容后,我发现了我的问题。这是语法错误、普遍缺乏理解和一些逻辑错误的组合。这是所有工作的最终代码:

static const GLchar* _vertexShaderSource[] = 
    
        "#version 430 core                                                              \n"

        "layout (location = 0) in vec4 position;                                        \n"
        "layout (location = 1) in vec4 color;                                           \n"
        "layout (location = 2) in vec2 dimensions;                                      \n"

        "uniform mat4 transform_mat;                                                    \n"

        "out vec4 gs_color;                                                             \n"
        "out vec4 gs_dimensions;                                                        \n"

        "void main(void)                                                                \n"
        "                                                                              \n"
        "   gl_Position = transform_mat * position;                                     \n"
        "   gs_color = color;                                                           \n"
        "   gs_dimensions = transform_mat * vec4(dimensions.x, dimensions.y, 0.0, 0.0);                                 \n"
        "                                                                              \n"
    ;

//=====Geomtry Shader=====
    static const GLchar* _geometryShaderSource[] =
    
        "#version 430 core                                                              \n"

        "layout(points) in;                                                             \n"
        "layout(triangle_strip, max_vertices = 3) out;                                  \n"

        "in vec4 gs_color[];                                                            \n"
        "in vec4 gs_dimensions[];                                                       \n"

        "out vec4 fs_color;                                                             \n"

        "void main()                                                                    \n"
        "                                                                              \n"
        "   fs_color = gs_color[0];                                                     \n"
        //Top
        "   gl_Position = gl_in[0].gl_Position + vec4(0.0, gs_dimensions[0].y, 0.0, 0.0);                   \n"
        "   EmitVertex();                                                                                   \n"
        //Bottom Right
        "   gl_Position = gl_in[0].gl_Position + vec4(-gs_dimensions[0].x, -gs_dimensions[0].y, 0, 0);      \n"
        "   EmitVertex();                                                                                   \n"
        //Bottom Left
        "   gl_Position = gl_in[0].gl_Position + vec4(gs_dimensions[0].x, -gs_dimensions[0].y, 0.0, 0.0);   \n"
        "   EmitVertex();                                                                                   \n"

        "   EndPrimitive();                                                             \n"
        "                                                                              \n"
    ;


    //=====Fragment Shaders=====
    //This is used when only colors, not textures are used to render
    //a pirmitive
    static const GLchar* _fragmentShaderSource[] = 
    
        "#version 430 core                                                              \n"

        "in vec4 fs_color;                                                              \n"
        "out vec4 color;                                                                \n"

        "void main(void)                                                                \n"
        "                                                                              \n"
        "   color = fs_color;                                                           \n"
        "                                                                              \n"
    ;

下面是 draw 和 AddToBatch 函数的样子:

void Renderer::AddToBatch(GLuint shader, Vec2& pos, U32 w, U32 h, Col& c)

    if(_currentShader != shader)
    
        Draw();
        _currentShader = shader;

        glUseProgram(_currentShader);

        _SetOrthoProjection();
    

    if(_currentBatchSize + 1 >= _maxBatchSize)  Draw(); 

    _vertices.push_back(pos.GetX());
    _vertices.push_back(pos.GetY());
    _vertices.push_back(pos.GetZ());
    _vertices.push_back(pos.GetW());

    _dimensions.push_back((F32)w);
    _dimensions.push_back((F32)h);

    _colors.push_back(c.GetRed());
    _colors.push_back(c.GetGreen());
    _colors.push_back(c.GetBlue());
    _colors.push_back(c.GetAlpha());

    ++_currentBatchSize;



void Renderer::Draw(void)

    if(_currentBatchSize == 0) return;

    GLuint buffers[4];
    glGenBuffers(4, buffers);

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _vertices.size()), &_vertices[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _colors.size()), &_colors[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, NULL);


    glBindBuffer(GL_ARRAY_BUFFER, buffers[2]);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _dimensions.size()), &_dimensions[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, NULL);

    glDrawArrays(GL_POINTS, 0, _currentBatchSize);

    //=====Reset All Containers and Counters=====
    _vertices.clear();
    _dimensions.clear();
    _colors.clear();
    _uvs.clear();
    _currentBatchSize = 0;

【讨论】:

以上是关于OpenGL几何着色器三角形不会没有错误地绘制的主要内容,如果未能解决你的问题,请参考以下文章

无法获得简单的 2D 着色器以在 C++ openGL 中绘制红色三角形(无编译器错误)

绘制三角形的OpenGL程序给出了一个黄色的屏幕

片段着色器不会在 OpenGL GLSL 中创建像光一样的渐变

使用 VBO/IBO 的 OpenGL 纹理三角形

Android OpenGL学习:最小系统绘制

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