Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm working my way through optimizing the rendering of sprites in a 2D game using OpenGL ES and I've hit the limit of my knowledge when it comes to GLSL and vertex shaders.

I have two large float buffers containing my vertex coordinates and texture coordinates (eventually this will be one buffer) for multiple sprites in order to perform a single glDrawArrays call. This works but I've hit a snag when it comes to passing the transformation matrix into the vertex shader.

My shader code is:

uniform mat4 u_MVPMatrix; 
attribute vec4 a_Position;      
attribute vec2 a_TexCoordinate; 
varying vec2 v_TexCoordinate; 

void main()
{
    v_TexCoordinate = a_TexCoordinate;
    gl_Position = u_MVPMatrix * a_Position;
}

In Java (Android) I am using a FloatBuffer to store the vertex/texture data and this is provided to the shader like so:

mGlEs20.glVertexAttribPointer(mVertexHandle, Globals.GL_POSITION_VERTEX_COUNT, GLES20.GL_FLOAT, false, 0, mVertexCoordinates);   
mGlEs20.glVertexAttribPointer(mTextureCoordinateHandle, Globals.GL_TEXTURE_VERTEX_COUNT, GLES20.GL_FLOAT, false, 0, mTextureCoordinates);

(The Globals.GL_POSITION_VERTEX_COUNT etc are just integers with the value of 2 right now)

And I'm passing the MVP (Model/View/Projection) matrix buffer like this:

GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mModelCoordinates); 

(mModelCoordinates is a FloatBuffer containing 16-float sequences representing the MVP matrix for each sprite)

This renders my scene but all the sprites share the same transformation, so it's obviously only picking the first 16 elements from the buffer which makes sense since I am passing in "1" as the second parameter. The documentation for this method says:

"This should be 1 if the targeted uniform variable is not an array of matrices, and 1 or more if it is an array of matrices."

So I tried modifying the shader with a fixed size array large enough to accomodate most of my scenarios:

uniform mat4 u_MVPMatrix[1000];

But this lead to an error in the shader:

cannot convert from 'uniform array of 4X4 matrix of float' to 'Position 4-component vector of float'

This just seems wrong anyway as it's not clear to me how the shader would know when to transition to the next matrix anyway.

Anyone have an idea how I can get my shader to pick up a different MVP matrix (i.e. the NEXT 16 floats) from my MVP buffer for every 4 vertices it encounters? (I am using GL_TRIANGLE_STRIP so each sprite has 4 vertices).

Thanks!

share|improve this question
add comment

2 Answers

You could add a vertex attribute to identify the index of the matrix to be used. Something like:

attribute int a_iMVP;
...
gl_Position = u_MVPMatrix[a_iMVP] * a_Position;

Of course, this will consume extra space in your vertex buffer and need to be generated by your application code. If your hardware supports instancing, this attribute could be in a separate, instanced vertex buffer, so you'd only need one value per 4 verts instead of a value for every vert.

share|improve this answer
add comment

If all your sprites share the same View and Projection matrices (you are doing 2D sprites and not 3D billboarding), calculate the final quads via CPU and update your vertex buffer with their positions. Here is an answer that explains how XNA does its SpriteBatch magic.

share|improve this answer
    
Thanks for your answer. I had started down this approach but was getting some weird results. Could have been my matrix manipulation that was janky. –  Carbon Crystal Oct 30 '12 at 5:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.