Qt OpenGL drawElements崩溃

时间:2014-03-19 18:06:22

标签: c++ qt opengl

我创建了一个包装好的QGLWidget类,并尝试创建一个访问它的基本精灵工厂样式类。在我的SpriteMachine(思考精灵工厂)类中,我尝试使用VBO进行所有精灵绘图,以及glDrawElements调用(在我的代码中只是drawElements,访问父调用glDrawElements的包装函数)。我在drawElements上遇到访问冲突,我无法弄清楚原因。

我检查过,我几乎可以肯定我的顶点数据格式正确。此外,我在任何绘图发生之前在父窗口小部件的initializeGL方法中调用initializeGlFunctions,所以我不认为我不正确地初始化了所有内容。首先,这是执行绘图的sprite类中的代码:

void Machine::sync(){
#define ADD_ATTRIBUTE_LOCATION(ATTRNAME, ASIZE, OFFSET)                                                                         \
    (                                                                                                                           \
        (attrLoc = flat_shader.attributeLocation(ATTRNAME)),                                                                    \
        (flat_shader.enableAttributeArray(attrLoc)),                                                                            \
        (parent->vertexAttribPointer(attrLoc, ASIZE, GL_FLOAT, GL_FALSE, sizeof(VertexAttribArray), (const void*) offset)),     \
        (offset += OFFSET),                                                                                                     \
        (void)0                                                                                                                 \
    )

    int i;
    int q;
    int oldSize;
    int size;
    int width;
    int height;
    qreal texInvW;
    qreal texInvH;
    qreal scaledCoords[4];
    GLuint vbo[2];
    quintptr offset;
    int attrLoc;
    QPair<SpriteProperties*, BoundingBox> spriteData;
    VertexAttribArray* verts;
    GLushort*          indices;

    parent->makeCurrent();

    glEnable(GL_TEXTURE_2D);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    offset = 0;

    flat_shader.bind();
    flat_shader.setUniformValue("mvp_matrix", parent->getOrtho());
    flat_shader.setUniformValue("texture", 0);
    ADD_ATTRIBUTE_LOCATION("a_position", 3, sizeof(float) * 3);
    ADD_ATTRIBUTE_LOCATION("a_texcoord", 2, sizeof(float) * 2);
    ADD_ATTRIBUTE_LOCATION("a_scale", 2, sizeof(float) * 2);
    ADD_ATTRIBUTE_LOCATION("a_scale_lo", 2, sizeof(float) * 2);
    ADD_ATTRIBUTE_LOCATION("a_scale_hi", 2, sizeof(float) * 2);

    parent->genBuffers(2, vbo);
    oldSize = 0;
    for(i = 0; i < spriteToSync.size(); i++){
        size = spriteToSync[i].size();
        if(size > 0){
            parent->bindTexture(atlasList[i]);

            texInvW = 1.0 / atlasList[i].width();
            texInvH = 1.0 / atlasList[i].height();
            if(size > oldSize){
                if(oldSize != 0){
                    delete[] verts;
                    delete[] indices;
                }
                verts   = new VertexAttribArray[4 * size];
                indices = new GLushort[4 * size];
            }
            for(q = 0; q < size; q++){
                spriteData = spriteToSync[i][q];
                width  = spriteData.first->location.x1 - spriteData.first->location.x0;
                height = spriteData.first->location.y1 - spriteData.first->location.y0;
                scaledCoords[0] = spriteData.first->location.x0 * texInvW;
                scaledCoords[1] = spriteData.first->location.y0 * texInvH;
                scaledCoords[2] = spriteData.first->location.x1 * texInvW;
                scaledCoords[3] = spriteData.first->location.y1 * texInvH;

                if(spriteData.first->flags & DRAW_TILED){
                    verts[q * 4 + 0].p = QVector3D(spriteData.second.x1, spriteData.second.y0,UNIFORM_DEPTH);
                    verts[q * 4 + 0].t = QVector2D(scaledCoords[2], scaledCoords[1]);
                    verts[q * 4 + 0].s = QVector2D(((qreal) (spriteData.second.x1 - spriteData.second.x0)) / width,
                                                   ((qreal) (spriteData.second.y1 - spriteData.second.y0)) / height);
                    verts[q * 4 + 0].s_lo = QVector2D(scaledCoords[0], scaledCoords[1]);
                    verts[q * 4 + 0].s_hi = QVector2D(scaledCoords[2] - scaledCoords[0], scaledCoords[3] - scaledCoords[1]);

                    verts[q * 4 + 1].p = QVector3D(spriteData.second.x0, spriteData.second.y0, UNIFORM_DEPTH);
                    verts[q * 4 + 1].t = QVector2D(scaledCoords[0], scaledCoords[1]);
                    verts[q * 4 + 1].s = verts[q * 4 + 0].s;
                    verts[q * 4 + 1].s_lo = verts[q * 4 + 0].s_lo;
                    verts[q * 4 + 1].s_hi = verts[q * 4 + 0].s_hi;

                    verts[q * 4 + 2].p = QVector3D(spriteData.second.x0, spriteData.second.y1, UNIFORM_DEPTH);
                    verts[q * 4 + 2].t = QVector2D(scaledCoords[0], scaledCoords[3]);
                    verts[q * 4 + 2].s = verts[q * 4 + 0].s;
                    verts[q * 4 + 2].s_lo = verts[q * 4 + 0].s_lo;
                    verts[q * 4 + 2].s_hi = verts[q * 4 + 0].s_hi;

                    verts[q * 4 + 3].p = QVector3D(spriteData.second.x1, spriteData.second.y1, UNIFORM_DEPTH);
                    verts[q * 4 + 3].t = QVector2D(scaledCoords[2], scaledCoords[3]);
                    verts[q * 4 + 3].s = verts[q * 4 + 0].s;
                    verts[q * 4 + 3].s_lo = verts[q * 4 + 0].s_lo;
                    verts[q * 4 + 3].s_hi = verts[q * 4 + 0].s_hi;
                }
                else{
                    verts[q * 4 + 0].p = QVector3D(spriteData.second.x0 + width, spriteData.second.y0,UNIFORM_DEPTH);
                    verts[q * 4 + 0].t = QVector2D(scaledCoords[2], scaledCoords[1]);
                    verts[q * 4 + 0].s = QVector2D(1, 1);
                    verts[q * 4 + 0].s_lo = QVector2D(scaledCoords[0], scaledCoords[1]);
                    verts[q * 4 + 0].s_hi = QVector2D(scaledCoords[2] - scaledCoords[0], scaledCoords[3] - scaledCoords[1]);

                    verts[q * 4 + 1].p = QVector3D(spriteData.second.x0, spriteData.second.y0, UNIFORM_DEPTH);
                    verts[q * 4 + 1].t = QVector2D(scaledCoords[0], scaledCoords[1]);
                    verts[q * 4 + 1].s = verts[q * 4 + 0].s;
                    verts[q * 4 + 1].s_lo = verts[q * 4 + 0].s_lo;
                    verts[q * 4 + 1].s_hi = verts[q * 4 + 0].s_hi;

                    verts[q * 4 + 2].p = QVector3D(spriteData.second.x0, spriteData.second.y0 + height, UNIFORM_DEPTH);
                    verts[q * 4 + 2].t = QVector2D(scaledCoords[0], scaledCoords[3]);
                    verts[q * 4 + 2].s = verts[q * 4 + 0].s;
                    verts[q * 4 + 2].s_lo = verts[q * 4 + 0].s_lo;
                    verts[q * 4 + 2].s_hi = verts[q * 4 + 0].s_hi;

                    verts[q * 4 + 3].p = QVector3D(spriteData.second.x0 + width, spriteData.second.y0 + height, UNIFORM_DEPTH);
                    verts[q * 4 + 3].t = QVector2D(scaledCoords[2], scaledCoords[3]);
                    verts[q * 4 + 3].s = verts[q * 4 + 0].s;
                    verts[q * 4 + 3].s_lo = verts[q * 4 + 0].s_lo;
                    verts[q * 4 + 3].s_hi = verts[q * 4 + 0].s_hi;
                }
                indices[q * 4 + 0] = q * 4 + 0;
                indices[q * 4 + 1] = q * 4 + 1;
                indices[q * 4 + 2] = q * 4 + 2;
                indices[q * 4 + 3] = q * 4 + 3;
            }

            parent->bindBuffer(GL_ARRAY_BUFFER, vbo[0]);
            parent->bufferData(GL_ARRAY_BUFFER, size * 4 * sizeof(VertexAttribArray), verts, GL_STATIC_DRAW);
            parent->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[1]);
            parent->bufferData(GL_ELEMENT_ARRAY_BUFFER, size * 4 * sizeof(GLushort), indices, GL_STATIC_DRAW);

            parent->drawElements(GL_QUADS, 4 * size, GL_UNSIGNED_SHORT, 0);

            oldSize = size;
            spriteToSync[i].clear();
        }
    }
    parent->deleteBuffers(2, vbo);
    if(oldSize > 0){
        delete[] verts;
        delete[] indices;
    }
}

现在这里是调用sprite类的代码:

void MyGLWidget::paintGL(){
    SpriteMachine::Machine spriteDraw(this);
    SpriteMachine::key     atlas;
    SpriteMachine::key     sprites[2];

    ortho.setToIdentity();
    ortho.ortho(0, width, height, 0, -1, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    atlas = spriteDraw.loadAtlas(":/gfx/gfx/hnight.png");

    sprites[0] = spriteDraw.create(atlas, SpriteMachine::BoundingBox(208, 64, 239, 95));
    sprites[1] = spriteDraw.create(atlas, SpriteMachine::BoundingBox(192, 96, 207, 111));

    spriteDraw.draw(sprites[0], SpriteMachine::BoundingBox(10, 10, 0, 0));

    spriteDraw.sync();
}

我已经验证我的顶点数组是使用浮点数正确格式化的,并且着色器已正确链接和加载。我知道这里的很多课程结构都不可见,但我的GL有什么明显的错误吗?

更新

我实际上没有任何类型的glEnableClientState调用,我有类似的代码,这些代码在我从未使用过的地方有效,这是否相关?

0 个答案:

没有答案