0

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

1) 承包商 - 创建和初始化 VBO、VAO 和制服人员。2) Draw - 绑定VAO和Draw

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

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

我还在 linux/Windows/NVIDIA/RADEON 上进行了测试,并且发生了相同的行为。将#verson 400 用于着色器和 glew、glm 数学库。

代码如下:

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

为了在构造函数之后将数据“重新发送”到 GPU,我使用了 sendData 成员函数:

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 成员函数

4

2 回答 2

0

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

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

于 2012-04-17T21:10:54.590 回答
0

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

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

于 2012-04-17T20:49:12.773 回答