Home Game Development opengl – Switched from immediate mode to VBOs, game runs slower

opengl – Switched from immediate mode to VBOs, game runs slower

0
opengl – Switched from immediate mode to VBOs, game runs slower

[ad_1]

I’m trying to improve the draw performance on my c++, OpenGL, SDL game.

Back in school we mostly learned immediate mode, so that’s how my drawing was originally implemented. When I started reading up online about improving performance, I read about VBOs and how they are ‘so much better’ and use the graphics card memory, etc.

So I took a couple of nights and converted to them. When I tested the game, it actually ran slower (draw method went from ~7 to ~10 ticks).

Did I do something wrong or are VBOs only more efficient in certain situations?

Here’s my class for tessellated polygons after adding VBOs (my game draws a lot of flat 2D shapes in a 3D world, sort of papermario-style)

#include "Tesselator.h"

Tesselator::Tesselator(std::vector<b2Vec2> vertices, Gradient* gradient) {
    this->vertices = vertices;
    this->gradient = gradient;
    tesselator = gluNewTess();
    gluTessCallback(tesselator, GLU_TESS_BEGIN_DATA, (void(CALLBACK*)())beginCallback);
    gluTessCallback(tesselator, GLU_TESS_VERTEX_DATA, (void(CALLBACK*)())vertexCallback);
    gluTessCallback(tesselator, GLU_TESS_END, (void(CALLBACK*)())endCallback);
    int vertcount = (int)vertices.size();
    GLdouble vertarray[vertcount][3];
    for (int i = 0; i < vertices.size(); i++) {
        vertarray[i][0] = vertices[i].x;
        vertarray[i][1] = vertices[i].y;
        vertarray[i][2] = 0;
    }
    gluTessBeginPolygon(tesselator, this);
    gluTessBeginContour(tesselator);
    for (int i = 0; i < vertices.size(); i++) {
        gluTessVertex(tesselator, vertarray[i], vertarray[i]);
    }
    gluTessEndContour(tesselator);
    gluTessEndPolygon(tesselator);
    gluDeleteTess(tesselator);
    for (int i = 0; i < triangles.size(); i++) {
        triangleVBOs.push_back(new VertexBufferObject(triangles[i]));
    }
    for (int i = 0; i < trianglefans.size(); i++) {
        triangleFanVBOs.push_back(new VertexBufferObject(trianglefans[i]));
    }
    for (int i = 0; i < trianglestrips.size(); i++) {
        triangleStripVBOs.push_back(new VertexBufferObject(trianglestrips[i]));
    }
}
Tesselator::~Tesselator() {
    for (int i = 0; i < triangleVBOs.size(); i++) {
        delete triangleVBOs[i];
    }
    for (int i = 0; i < triangleFanVBOs.size(); i++) {
        delete triangleFanVBOs[i];
    }
    for (int i = 0; i < triangleStripVBOs.size(); i++) {
        delete triangleStripVBOs[i];
    }
    triangleVBOs.clear();
    triangleFanVBOs.clear();
    triangleStripVBOs.clear();
}
void Tesselator::draw(float z) {
    Drawing::applyZTranslation(z);
    for (int i = 0; i < triangleVBOs.size(); i++) {
        triangleVBOs[i]->draw(GL_TRIANGLES);
    }
    for (int i = 0; i < triangleFanVBOs.size(); i++) {
        triangleFanVBOs[i]->draw(GL_TRIANGLE_FAN);
    }
    for (int i = 0; i < triangleStripVBOs.size(); i++) {
        triangleStripVBOs[i]->draw(GL_TRIANGLE_STRIP);
    }
    Drawing::applyZTranslation(-z);
}
void Tesselator::addTriangle() {
    std::vector<b2Vec2> triangleVertices;
    triangles.push_back(triangleVertices);
}
void Tesselator::addTriangleFan() {
    std::vector<b2Vec2> triangleFanVertices;
    trianglefans.push_back(triangleFanVertices);
}
void Tesselator::addTriangleStrip() {
    std::vector<b2Vec2> triangleStripVertices;
    trianglestrips.push_back(triangleStripVertices);
}
void Tesselator::addVertex(b2Vec2 vertex) {
    if (currentType == GL_TRIANGLES) {
        triangles.back().push_back(b2Vec2(vertex.x, vertex.y));
    }
    else if (currentType == GL_TRIANGLE_FAN) {
        trianglefans.back().push_back(b2Vec2(vertex.x, vertex.y));
    }
    else if (currentType == GL_TRIANGLE_STRIP) {
        trianglestrips.back().push_back(b2Vec2(vertex.x, vertex.y));
    }
}
void CALLBACK Tesselator::beginCallback(GLenum type, GLvoid * tessdata) {
    Tesselator* tess = (Tesselator*) tessdata;
    tess->currentType = type;
    if (type == GL_TRIANGLES) {
        tess->addTriangle();
    }
    else if (type == GL_TRIANGLE_FAN) {
        tess->addTriangleFan();
    }
    else if (type == GL_TRIANGLE_STRIP) {
        tess->addTriangleStrip();
    }
}
void CALLBACK Tesselator::vertexCallback(GLdouble* vertex, GLvoid* tessdata) {
    Tesselator* tess = (Tesselator*) tessdata;
    tess->addVertex(b2Vec2(*(vertex), *(vertex + 1)));
}
void CALLBACK Tesselator::endCallback() {
}

and here is my vertex buffer object class

#include "VertexBufferObject.h"

VertexBufferObject::VertexBufferObject(std::vector<b2Vec2> shapeVertices) {
    numberOfCoordinateValues = 0;
    for (int i = 0; i < shapeVertices.size(); i++) {
        numberOfCoordinateValues = numberOfCoordinateValues + 2;
    }
    float coordinateValues[numberOfCoordinateValues];
    int coordinateValueArrayIndex = 0;
    for (int i = 0; i < shapeVertices.size(); i++) {
        coordinateValues[coordinateValueArrayIndex] = shapeVertices[i].x;
        coordinateValueArrayIndex++;
        coordinateValues[coordinateValueArrayIndex] = shapeVertices[i].y;
        coordinateValueArrayIndex++;
    }
    glGenBuffers(1, &id);
    glBindBuffer(GL_ARRAY_BUFFER, id);
    glBufferData(GL_ARRAY_BUFFER, sizeof(coordinateValues),     coordinateValues, GL_STATIC_DRAW);
}
VertexBufferObject::~VertexBufferObject() {
    glDeleteBuffers(1, &id);
}
void VertexBufferObject::draw(GLenum mode) {
    glBindBuffer(GL_ARRAY_BUFFER, id);
    glVertexPointer(2, GL_FLOAT, 0, NULL);
    glEnableClientState(GL_VERTEX_ARRAY);
    glDrawArrays(mode, 0, numberOfCoordinateValues/2);
    glDisableClientState(GL_VERTEX_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

and heres what the draw method for Tesselator used to look like before adding VBOs

void Tesselator::draw(float z) {
    for (int i = 0; i < triangles.size(); i++) {
        Drawing::drawTriangles(triangles[i], z, gradient);
    }
    for (int i = 0; i < trianglefans.size(); i++) {
        Drawing::drawTriangleFan(trianglefans[i], z, gradient);
    }
    for (int i = 0; i < trianglestrips.size(); i++) {
        Drawing::drawTriangleStrip(trianglestrips[i], z, gradient);
    }
}

and in Drawing.cpp:

void Drawing::drawTriangles(std::vector<b2Vec2> vertices, float z, Gradient* gradient) {
    glBegin(GL_TRIANGLES);
    for (int i = 0; i < vertices.size(); i++) {
        addVertex(vertices[i].x, vertices[i].y, z, gradient);
    }
    glEnd();
}
void Drawing::drawTriangleFan(std::vector<b2Vec2> vertices, float z, Gradient* gradient) {
    glBegin(GL_TRIANGLE_FAN);
    for (int i = 0; i < vertices.size(); i++) {
        addVertex(vertices[i].x, vertices[i].y, z, gradient);
    }
    glEnd();
}
void Drawing::drawTriangleStrip(std::vector<b2Vec2> vertices, float z, Gradient* gradient) {
    glBegin(GL_TRIANGLE_STRIP);
    for (int i = 0; i < vertices.size(); i++) {
        addVertex(vertices[i].x, vertices[i].y, z, gradient);
    }
    glEnd();
}

[ad_2]