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 May 11 '16 at 17:08
  • \$\begingroup\$ per vertex, I put it in the VBO \$\endgroup\$ – user83339 May 11 '16 at 17:36
  • \$\begingroup\$ how would I go about doing that per sprite? \$\endgroup\$ – user83339 May 11 '16 at 20:27
  • \$\begingroup\$ On second thought I may have misunderstood you. Ignore comment. Is GLSL version 1.30 a must have? \$\endgroup\$ – Andreas May 13 '16 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\$ – Pixel Aug 7 at 8:48

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 May 22 '16 at 22:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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