glDrawArrays意外行为

时间:2014-03-23 23:59:16

标签: c++ opengl

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

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

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

继承我的代码:

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

Fragment Shader:

#version 140

out vec4 outColor;

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

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

2 个答案:

答案 0 :(得分:4)

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

根据你的64位编辑,它可能是4或8。即,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;
}

答案 1 :(得分:2)

glGenBuffers(1, &vertexBufferObject);

将顶点缓冲区的id保存在局部变量中。这个值在绘图调用中不再可用,并且修改全局vertexBufferObject(但缓冲区仍然存在 - 您只是丢失了它的ID并且不能再使用它了。甚至无法破坏它)