简体   繁体   中英

glDrawArrays unexpected behavior

I have spent a good amount of time with the fixed pipeline of openGL, and I have recently began learning the programmable pipeline. I know my painter, and shader classes are not the issue because they work with fixed function pipeline stuff. I can't seem to get glDrawArrays to work for my life.

I am not sure if my error is in how i set up the vertex buffer object, in my shader or else where. I have debugged my code also and set breakpoints throughout the display function, and it seems to never get past glDrawArrays(), (ie it hits a breakpoint at glDrawArrays, but doesn't hit any after, not sure why.)

What gets outputted is just a white screen, nothing else.

Heres my code:

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

Vertex Shader:

#version 140

in vec4 position; 

void main()
{   
    gl_Position = position; 
}

Fragment Shader:

#version 140

out vec4 outColor;

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

Edit: Code updated with Joey Dewd, keltar, and genpfault's suggestions. I'm no longer hanging at glDrawArrays, ie instead of a white screen I'm getting a black screen. This is leading me to think that my buffer is somehow still not setup correctly. Or possibly, I am missing something else needed for the vertex array buffer initialization (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) in this context is not what you seem to hope it is .

It'll probably be 4 or 8 depending on your 64-bit-edness. Ie, the sizeof a pointer-to-float. Not sizeof(vertices) .

You need to pass in a separate size argument:

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

Or a contiguous (important!) standard container like 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);
}

Full example:

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

Saves id of vertex buffer in local variable. This value no longer available in draw call and does not modify global vertexBufferObject (yet buffer still exists - you just lost its id and can't use it anymore. can't even destroy it)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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