类构造函数不将数据DATA发送到VBO

时间:2012-04-17 20:46:49

标签: opengl constructor vbo glew

我有一个名为Model的类,它处理绘制自身所需的所有信息。基本上它有两种方法:

1)构造函数 - 创建和启动VBO,VAO和统一的工作人员。 2)绘制 - 绑定VAO并绘制

我的问题是使用glBufferData初始化VBO。我注意到应该上传到GPU内存的数据不是那个!!我确实使用gDebugger检查了这个。还观察到,如果我尝试再次在外部和构造类之后发送数据,一切都顺利。我错过了什么???

Model的类实例化对象是一个全局变量,模板参数V和M分别为vec4和mat4。

我还在linux / Windows / NVIDIA / RADEON上测试了同样的行为。使用#verson 400 for Shaders and glew,glm math library。

以下是代码:

1)构造函数:

/** This constructor has 5 steps:
 *  1) Allocate variables
 *  2) Create, bind and Send vbo inf.
 *  3) Create, bind vao info
 *  4) Create mapping between Buffer and Attributes in GPU memory
 *  5) Get uniform variables location
 * 
 * */
template<class V, class M>
Model<V, M>::Model( GLuint size, GLuint program ){
    assert( size > 0 );

    /** BEG - 1) Allocate variables */
    /** beg - model variable initialization */
    this->vertex        = new vec4[ size ];
    this->numVertex     = size;

    this->color         = new vec4[ size ];
    this->numColor      = size;

    //this->element     => not initialized
    //this->numElem     => not initialized

    this->modelMatrix   = M(1); // Identity Matrix
    this->position      = V(0); // Orign

    // VBO - Vertex Buffer Object information
    this->vbo           = new GLuint[ this->numBuff ];
    this->vboSize       = this->numBuff;

    // VAO - Vexter Array Object information
    this->vao           = new GLuint[ 1 ];
    this->numVao        = 1;
    this->attrib        = new GLuint[ this->numBuff ];
    this->numAttrib     = this->numBuff;

    this->uniform       = new string[ this->numUni ];
    this->uniformLoc    = new GLuint[ this->numUni ];
    this->numUniform    = this->numUni;

    this->program       = program;

    //beg - Inittialization
    this->attrib[VERTEX]     = 0;
    this->attrib[COLOR]      = 1;

    this->uniform[0]         = string("modelMatrix");
    this->uniform[1]         = string("position");
    //end - Inittialization
    /** END - 1) Allocate variables */


    /** BEG - 2) Create, bind and Send vbo inf */
    // Create vbo identifier
    glGenBuffers( this->vboSize, this->vbo );
    Other<V>::checkError("glGenBuffers");

    // Bind Buffer
    glBindBuffer( GL_ARRAY_BUFFER, (this->vbo)[0] );
    Other<V>::checkError("glBindBuffer");

    // Send Data to buffer
    glBufferData(   GL_ARRAY_BUFFER, sizeof( (this->vertex)[0][0] ) * (this->vertex)[0].length() * (this->numVertex),
                    &(this->vertex[0][0]), GL_STATIC_DRAW);
    Other<V>::checkError("glBufferData");

    // Bind Buffer
    glBindBuffer( GL_ARRAY_BUFFER, (this->vbo)[1] );
    Other<V>::checkError("glBindBuffer");

    // Send Data to buffer
    glBufferData(   GL_ARRAY_BUFFER, sizeof( (this->color)[0][0] ) * (this->color)[0].length() * (this->numColor),
                    &(this->color[0][0]), GL_STATIC_DRAW);
    Other<V>::checkError("glBufferData");
    /** END - 2) Create, bind and Send vbo inf */


    /** BEG - 3) Create, bind and enable vao info */
    // Create vao identifier
    glGenVertexArrays( 1, this->vao );
    Other<V>::checkError("glGenVertexArrays");
    glBindVertexArray( (this->vao)[0] );
    Other<V>::checkError("glBindVertexArray");

    // Enable attributes
    for ( uint i=0; i<numAttrib; i++ ){
        glEnableVertexAttribArray( i );
        Other<V>::checkError("glEnableVertexAttribArray");
    }
    /** END - 3) Create and enable vao info */


    /** BEG - 4) Create mapping between Buffer and Attributes in GPU memory */
    for ( uint i=0; i<numAttrib; i++ ){
        glBindBuffer( GL_ARRAY_BUFFER, (this->vbo)[i] );
        Other<V>::checkError("glBindBuffer");
        glVertexAttribPointer( (this->attrib)[i], (this->vertex)[i].length(), GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);
        Other<V>::checkError("glBindBuffer");
    }
    /** END - 4) Create mapping between Buffer and Attributes in GPU memory */


    /** BEG - 5) Get uniform variables location */
    for ( uint i=0; i<numAttrib; i++ ){
        this->uniformLoc[i] = glGetUniformLocation( program, this->uniform[i].c_str() );
        Other<V>::checkError("glGetUniformLocation");
    }
    /** END - 5) Get uniform variables location */
}

2)画画

template<class V, class M>
void Model<V, M>::draw()
{
    //glUniformMatrix4fv( this->uniformLoc[0], 1, GL_FALSE, &(this->modelMatrix[0][0]) );
    //glUniform4fv(       this->uniformLoc[1], 1, &(this->position[0]) );

    glBindVertexArray( (this->vao)[0] );
    glDrawArrays( GL_LINE_STRIP, 0, this->numVertex);
}

在contructor之后使用sendData成员函数将数据“重新发送”到GPU:

template<class V, class M>
void Model<V, M>::sendData()
{
    glBindBuffer( GL_ARRAY_BUFFER, (this->vbo)[0] );

    // Send Data to buffer
    glBufferData(   GL_ARRAY_BUFFER, sizeof( (this->vertex)[0][0] ) * (this->vertex)[0].length() * (this->numVertex),
                        &(this->vertex[0][0]), GL_STATIC_DRAW);
}

编辑:我忘了添加sendData成员函数

2 个答案:

答案 0 :(得分:0)

在调用构造函数(称为glewInit())之前,您是否有有效的opengl上下文设置?

如果你有任何静态定义的OpenGL调用对象,它们将失败,因为它们是在main()之前构造的。如果你想在构造函数中使用带有opengl调用的对象,那么只有在初始化上下文之后才需要用new创建它。

答案 1 :(得分:0)

如果您在获取渲染上下文之前在任何地方实例化该类,例如静态初始化器或类似的,那么它将无法工作。

基本上你不应该把OpenGL操作放到类构造函数中,除非你以某种方式确定它将在有效的上下文中操作。您可以通过在另一个类的实例中封装有效的OpenGL上下文并将其作为参数传递给在上下文中运行的构造函数来实现此目的。