OpenGL newbie here.

So I'm trying to implement sprite batching to draw ~100 sprites per draw call. I've created a VBO that contains texture coordinates, vertex coordinates, color data (for tinting), and a mat4 matrix for transforms.

So far, so good, right? Well, everything is working but the transform portion of my VBO. My theory is that I could push a mat4 with all of the rotation, scaling, flipping, and world location data applied to it, so that it gets multiplied in with viewports (see glsl code below).

#version 130

//Vertex position attribute
in vec2 vertexPos;

//Texture coordinate attribute
in vec2 texCoordIn;
out vec2 texCoord;

// Vertex color
in vec4 textureColorIn;
out vec4 textureColor;

// Matrix transformations for the sprite
in mat4 transformation;

void main()
    //Process texCoord
    texCoord = texCoordIn;

    // Process texture color
    textureColor = textureColorIn;

    //Process vertex
    gl_Position =  gl_ProjectionMatrix * gl_ModelViewMatrix * vec4( vertexPos.x, vertexPos.y, 0.0, 1.0 ) * transformation;

So here's my question, if you were to send transform data to the GPU, how would you do it? Sending a mat4 over the wire per vertex seems like overkill.

  • \$\begingroup\$ You send one transformation for each sprite, not vertex, right? \$\endgroup\$
    – Andreas
    Commented May 11, 2016 at 17:08
  • \$\begingroup\$ per vertex, I put it in the VBO \$\endgroup\$
    – user83339
    Commented May 11, 2016 at 17:36
  • \$\begingroup\$ how would I go about doing that per sprite? \$\endgroup\$
    – user83339
    Commented May 11, 2016 at 20:27
  • \$\begingroup\$ On second thought I may have misunderstood you. Ignore comment. Is GLSL version 1.30 a must have? \$\endgroup\$
    – Andreas
    Commented May 13, 2016 at 16:10
  • \$\begingroup\$ Why not just send (angle, tx, ty, scaleFactor) to the GPU as a vec4 and compute the matrix there... just trying to figure this stuff out myself. This might be useful: paroj.github.io/gltut/Positioning/… \$\endgroup\$
    – user24493
    Commented Aug 7, 2019 at 8:48

1 Answer 1


Transform them in software using the CPU and give the GPU only the final vertex coordinates.

The savings in bus bandwidth by reducing the VBO size will be greater than the cost of the transform on the CPU which can be greatly simplified by combining the sprite expansion and transform into a single step, no heavy matrix multiplication needed.

2D rotation, scaling, flipping only needs two 2D vectors: up and right.

vertex[0] = center + up - right;
vertex[1] = center - up - right;
vertex[2] = center - up + right;
vertex[3] = center + up + right;

right is equivalent to the first row of the 4x4 matrix you would have sent over to the GPU, up the 2nd row of the same matrix, center is the 3rd row (translation) of the 4x4 matrix

up and right are not normals, they are half-sizes vectors of the sprite's up direction (half height) and right direction (half width).

enter image description here

  • \$\begingroup\$ Worked like a charm, I ended up using more expensive matrix multiplications to get my vector (mat4::rotate, translate, etc) \$\endgroup\$
    – user83339
    Commented May 22, 2016 at 22:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .