繁体   English   中英

glDrawArrays意外行为

[英]glDrawArrays unexpected behavior

我花了很多时间使用openGL的固定管道,最近我开始学习可编程管道。 我知道我的画家,着色器类不是问题,因为它们使用固定功能管道的东西。 我似乎无法让glDrawArrays为我的生活工作。

我不确定我的错误是在我如何设置顶点缓冲区对象,在我的着色器或其他地方。 我也调试了我的代码并在整个显示函数中设置了断点,它似乎永远不会超过glDrawArrays(),(它在glDrawArrays上遇到一个断点,但之后没有命中,不知道为什么。)

输出的只是一个白色的屏幕,没有别的。

继承我的代码:

float   vertices[] = {   0.75,  0.75, 0.0, 1.0,
                         0.75, -0.75, 0.0, 1.0,
                        -0.75, -0.75, 0.0, 1.0 };

GLuint  vertexBufferObject;
GLuint  positionLocation;
GLuint  vaoObject;

void initVertexBuffer(GLuint& vertexBufferObject, float* vertexData, unsigned int size, GLenum GL_DRAW_TYPE)
{
    glGenBuffers(1, &vertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, size, vertexData, GL_DRAW_TYPE);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void main(int argc, char* argv[])
{

    painter.initEngine(argc, argv, 500, 500, 0, 0, "2D3D");
    painter.initGlutFuncs(display, resize, Input::MouseButtonClick,   Input::MouseDrag, keyboard);

    defaultShader.init("default.vert", "default.frag"); 
    defaultShader.link();

    initVertexBuffer(vertexBufferObject, vertices, sizeof(vertices), GL_STATIC_DRAW);
    glGenVertexArrays(1, &vaoObject);
    glBindVertexArray(vaoObject);
    positionLocation = glGetAttribLocation(defaultShader.id(), "position");

    painter.startMainLoop();
}

void display()
{
    painter.clearDisplay();

    defaultShader.bind();

    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glEnableVertexAttribArray(positionLocation);
    glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
    std::cout << Framework::glErrorCheck() << std::endl;

    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableVertexAttribArray(positionLocation);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    defaultShader.unbind();

    painter.flushAndSwapBuffers();
}

顶点着色器:

#version 140

in vec4 position; 

void main()
{   
    gl_Position = position; 
}

片段着色器:

#version 140

out vec4 outColor;

void main()
{
    outColor = vec4(1.0, 0.0, 1.0, 1.0);
}

编辑:代码更新了Joey Dewd,keltar和genpfault的建议。 我不再挂在glDrawArrays,即不是白色的屏幕,我得到一个黑屏。 这让我觉得我的缓冲区仍然没有正确设置。 或者可能,我遗漏了顶点数组缓冲区初始化所需的其他内容(vaoObject)?

void initVertexBuffer(GLuint vertexBufferObject, float* vertexData, GLenum GL_DRAW_TYPE)
{
    glGenBuffers(1, &vertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_DRAW_TYPE);
                                  ^^^^^^^^^^^^^^^^^^ nnnnope
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

在这种情况下, sizeof(vertexData)并不像你希望的那样

它可能是4或8,具体取决于您的64位编辑。 即,指向浮点的指针的sizeof 不是 sizeof(vertices)

您需要传入一个单独的大小参数:

void initVertexBuffer(GLuint& vertexBufferObject, float* vertexData, unsigned int size, GLenum GL_DRAW_TYPE)
{
    glGenBuffers(1, &vertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, size, vertexData, GL_DRAW_TYPE);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

...

void main(int argc, char* argv[])
{
    ...
    initVertexBuffer(vertexBufferObject, vertices, sizeof(vertices), GL_STATIC_DRAW);
    ...    
}

或者像std::vector这样的连续(重要!)标准容器:

template< typename Container >
void initVertexBuffer(GLuint& vertexBufferObject, const Container& vertexData, GLenum GL_DRAW_TYPE)
{
    glGenBuffers(1, &vertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof( typename Container::value_type ), &vertexData[0], GL_DRAW_TYPE);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

完整示例:

#include <GL/glew.h>
#include <GL/freeglut.h>

#include <iostream>
#include <vector>
using namespace std;

struct Program
{
    static GLuint Load( const char* vert, const char* geom, const char* frag )
    {
        GLuint prog = glCreateProgram();
        if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
        if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
        if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
        glLinkProgram( prog );
        CheckStatus( prog );
        return prog;
    }

private:
    static void CheckStatus( GLuint obj )
    {
        GLint status = GL_FALSE;
        if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
        if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
        if( status == GL_TRUE ) return;
        GLchar log[ 1 << 15 ] = { 0 };
        if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
        if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
        std::cerr << log << std::endl;
        exit( -1 );
    }

    static void AttachShader( GLuint program, GLenum type, const char* src )
    {
        GLuint shader = glCreateShader( type );
        glShaderSource( shader, 1, &src, NULL );
        glCompileShader( shader );
        CheckStatus( shader );
        glAttachShader( program, shader );
        glDeleteShader( shader );
    }
};

#define GLSL(version, shader) "#version " #version "\n" #shader


void initVertexBuffer(GLuint& vertexBufferObject, float* vertexData, unsigned int size, GLenum GL_DRAW_TYPE)
{
    glGenBuffers(1, &vertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, size, vertexData, GL_DRAW_TYPE);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

GLuint prog;
GLuint vaoObject;
void init()
{
    const char* vert = GLSL
    (
        140,
        in vec4 position; 
        void main()
        {   
            gl_Position = position; 
        }
    );

    const char* frag = GLSL
    (
        140,
        out vec4 outColor;
        void main()
        {
            outColor = vec4(1.0, 0.0, 1.0, 1.0);
        }
    );

    prog = Program::Load( vert, NULL, frag );
    glUseProgram( prog );

    glGenVertexArrays(1, &vaoObject);
    glBindVertexArray(vaoObject);

    float vertices[] = 
    {   
        0.75,  0.75, 0.0, 1.0,
        0.75, -0.75, 0.0, 1.0,
        -0.75, -0.75, 0.0, 1.0 
    };
    GLuint vertexBufferObject;
    initVertexBuffer(vertexBufferObject, vertices, sizeof(vertices), GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);

    GLuint positionLocation = glGetAttribLocation(prog, "position");
    glEnableVertexAttribArray(positionLocation);
    glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram( prog );
    glBindVertexArray(vaoObject);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glutSwapBuffers();
}

int main(int argc, char **argv)
{
    glutInit( &argc, argv );
    glutInitContextVersion( 3, 1 );
    glutInitContextProfile( GLUT_COMPATIBILITY_PROFILE );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );

    glewExperimental = GL_TRUE;
    glewInit();

    init();

    glutDisplayFunc( display );
    glutMainLoop();
    return 0;
}
glGenBuffers(1, &vertexBufferObject);

将顶点缓冲区的id保存在局部变量中。 在绘制调用不再可用,此值修改全局vertexBufferObject (但缓冲区仍然存在-你只是失去了它的ID,不能再使用它甚至不能消灭它)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM