awr
awr

Reputation: 550

Implementing VBOs to render sprites in OpenGL ES 2

I'm trying to implement VBOs to increase render speed in OpenGL and while I understand the overall concept, I'm not sure how to implement in a 2D with sprites. All implementations that I find seem to be for drawing a 3D model where all the vertices are fixed relative to one another. However, in a 2D game, each sprite has its position and thus its own MVP matrix.

How it seems to be done:

Basic vertex shader:
        "uniform mat4 uMVPMatrix;   \n" +

        "attribute vec4 vPosition;" +
        "attribute vec2 texCoord;" +
        "varying vec2 vTexCoord;" +
        "void main() {" +

        // matrix must be included as part of gl_Position
        "  gl_Position = uMVPMatrix * vPosition;" +
        "  vTexCoord = texCoord;" +
        "}";

Drawing with VBOs (pseudocode)
     1. Bind vertex/texture buffers
     2. Load MVP matrix with glUniformMatrix4fv
     3. Call glDrawArrays/glDrawElements to draw the all the vertices in one call

Is there a simple way to extend the above approach to allow for the changing MVP?

Two possibles ideas:

  1. Load up the vertices into the VBOs, but draw each sprite, loading each one's MVP matrix as above. Only saving would be that you don't have to pass in vertex data each time, but you still need to call glVertexAttribPointer to index to the right position in the VBO for each sprite. I imagine speed savings would be minimal.

  2. Instead of having the MVP matrix as a uniform, define it as an attribute. Concatenate all the MVPs for each sprite into one large array and load it using glVertexAttribPointer. It doesn't seem possible to load a matrix all at once using glVertexAttribPointer (you can at most load in a vec4), so I'll have to load it column by column with 4 consecutive calls. Then I should be able to transform each sprite independently. Should get considerable speed improvements over my current implementation, though concatenating the MVPs will still take time.

Is there a simpler implementation than the above? I imagine there must be some "standard" way of doing this as batch drawing sprites.

EDIT

I've decided to go with option 2, however I'm having issues getting to work: Shader attribute mat4 not binding correctly (Opengl ES 2.0 Android)

Upvotes: 1

Views: 1086

Answers (1)

Trax
Trax

Reputation: 1910

What common 2d engines out there do is to offer a tree based rendering. A node has its model matrix, and has some children that are both affected by parent model matrix and their own matrix. At runtime visit each node and render it concatenating parent's matrix and own matrix into one matrix. Unless you are rendering thousand of nodes (sprites) you should not worry about performance issues about passing so many matrices into the driver memory.

EDIT: Also you can have an specific type of node, usually called atlas to which you add precomputed quads that are only affected by the node's model matrix (see https://github.com/cocos2d/cocos2d-iphone/blob/master-v2/cocos2d/CCAtlasNode.m or https://github.com/TraxNet/ShadingZen/blob/master/library/src/main/java/org/traxnet/shadingzen/core2d/QuadAtlas.java).

Upvotes: 2

Related Questions