简体   繁体   中英

Help with Opengl es vertex batching, c++, oop

I'm experimenting with game programming and am looking for some feedback on my c++ iphone opengl es code. I am going to present code that works for me and discuss how I want to change it. What I'm trying to do is render all my hero bullets with a single draw call using oop for the bullets. The below uses a single draw call but there's no oop for the bullets yet.

Here is my rendering engine definition:

class RenderingEngine {
public:
    void Initialize(int width, int height);
    void Render();
    void UpdateAnimation(float timeStep);
    void OnFingerDown(ivec2 location);
private:
    std::vector<Vertex> vertices;
};

Here are the rendering engine methods:

void RenderingEngine::Initialize(int width, int height) {
    ...

    glViewport(0, 0, 320, 480);

    glMatrixMode(GL_PROJECTION);

    const float maxX = 2;
    const float maxY = 3;
    glOrthof(-maxX, +maxX, -maxY, +maxY, -1, 1);

    glMatrixMode(GL_MODELVIEW);
}

//here you can see the single draw call
void RenderingEngine::Render() {
    glClearColor(1, 1, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glBindTexture(GL_TEXTURE_2D, m_texture);
    glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].Position.x);
    glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].TexCoord.x);
    glDrawArrays(GL_TRIANGLES, 0, vertices.size());

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

/*since all the vertices are only for bullets at this
point, all we need to do is move each vertex up by the
same amount*/
void RenderingEngine::UpdateAnimation(float timeStep) {
    for (int i = 0; i < vertices.size(); ++i) {
        vertices[i].Position.y += timeStep*4.4f;
    }
}

/*I'm using GL_TRIANGLES, so when the user fingers
down I am pushing two triangles(six vertices) onto
the vertices vector. This only happens when the user
taps on the bottom 60 pixels of the screen.*/
void RenderingEngine::OnFingerDown(ivec2 location) {
    if (location.y >= 420) {
        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f - 32*0.0125f,
                                       -2.4f + 32*0.0125f), vec2(0, 1)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f - 32*0.0125f,
                                       -2.4f - 32*0.0125f), vec2(0, 0)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f + 32*0.0125f,
                                       -2.4f + 32*0.0125f), vec2(1, 1)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f - 32*0.0125f,
                                       -2.4f - 32*0.0125f), vec2(0, 0)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f + 32*0.0125f,
                                       -2.4f + 32*0.0125f), vec2(1, 1)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f + 32*0.0125f,
                                       -2.4f - 32*0.0125f), vec2(1, 0)));
}
}

The Vertex looks like this:

struct Vertex {
    Vertex() {}
    Vertex(vec2 position, vec2 texCoord) : Position(position), TexCoord(texCoord) {}
    vec2 Position;
    vec2 TexCoord;
};

Here is the simplified ivec2 and vec2:

template <typename T>
struct Vector2 {
    Vector2() {}
    Vector2(T x, T y) : x(x), y(y) {}
}

typedef Vector2<int> ivec2;
typedef Vector2<float> vec2;

So all of the above works for me and I have bullets shooting from the bottom of the screen to the top when a user taps the bottom of the screen. What I would like to do is add this to the rendering engine:

std::vector<HeroBullet> heroBullets;

then I would like to change my update animation method to:

void RenderingEngine1::UpdateAnimation(float timeStep) {
    for (int i = 0; i < heroBullets.size(); ++i) {
       heroBullets[i].UpdateAnimation(timeStep);
    }
}

I'm thinking this is a good idea because I don't want all the raw vertex data to be updated and managed in this single UpdateAnimation() method. But rather I'd like this UpdateAnimation() method to call UpdateAnimation() on each of my objects(right now it is only hero bullets but in the future it would be enemies, enemy bullets, etc..)

So my main question is how should I be instantiating my HeroBullet objects so that those instances will be able to access and modify their vertex data that is in the rendering engine vertices vector?

And also, I'm I doing this right? This seems like a common setup that games would need.

Looks about ok, personally I would add a few variables for all those hardcoded floats though, makes for cleaner code and easier adjustability later (and for that matter scaling if you aim for different display-sizes etc).

As for the updating, as far as I can gather, you would add extra overhead by doing all that separately from the raw data, however it might not be avoidable, in which case you might as well subclass the bullets into various subclasses that implement the various differencies, all of which inherit a common draw()-function or override a getVertices()-function (and possibly a getTexVertices()) to allow for varying implementations there. (This would mean having the various vertices in their respective subclasses instead of in the render-engine, which IMHO would be cleaner anyhow if they do independent updates to them anyhow).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM