我创建了一个包装好的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调用,我有类似的代码,这些代码在我从未使用过的地方有效,这是否相关?