Rotate a subtexture from a sprite atlas to apply to a point sprite

Hello Guys

I have an atlas with the rotation around y-axis of a circle. I’m interest just in the lower row, 16 element (per 16 in heigth). I want then to rotate around z-axis.
So I should first offset the right sprite and rotate it.
To offset a texture, if my atlas contains 16x16 elements I should divide gl_TexCoord by numsprite (16) and add (offset/numsprite) for each further i wanna address. f.e. (offset = 0 for lower left element, 1 for the second in the row and so on)
That said for rotating:

  • translate the texture to its origin
  • rotate around z
  • translate back

I do this by combining these 3 matrix and multipling the result for the original (gl_TexCoord.xy/numsprite). The left lower sprite rotates correctly that is: subtract 0.5/numsprite to x and y texture component to center it, rotate, translate back…
But when I try to rotate the next in the row this fails…(for example offset = 1.5)
Any suggestion or alternative?

thank you

If all elements in your atlas are the same size, I suggest using a texture array instead. That way you can address the texture using standard 0…1 ranges and rotate via a standard texture matrix without worrying about offsetting.

No.

Array textures are extremely limited in size. The largest value of GL_MAX_TEXTURE_ARRAY_LAYERS for any card currently available is 16384. The value on NVIDIA hardware? 2048. And that’s for their GL 4.x hardware. Earlier hardware was limited to between 128 and 512 layers.

That’s not a lot of sprites. Given a 16x16 sprite atlas and a 4096x4069 texture, you can fit 65536 sprites on them. Give them one pixel of padding (making them 17x17 sprites) and you 58,000+ in a single array layer.

Array layers are not meant for sprite sheets. Or at least, they’re not meant to be the dividers between sprites.

If you want the unsigned unit square (0…1) in texture coordinates to map to a particular sprite within the texture, you want the equivalent of


glMatrixMode(GL_TEXTURE);
float s = 1.0/16;
glScalef(s, s, s);
glTranslatef(column+0.5, row+0.5, 0);
glRotatef(angle, 0, 0, 1);
glTranslatef(-0.5, -0.5, 0);

where column and row are integers between 0 and 15 inclusive.

If you’re creating individual matrices and multiplying them, the order is left-to-right, i.e. the scale should be leftmost.

You could also split the first translation, writing the above as


float s = 1.0/16;
glScalef(s, s, s);
glTranslatef(column, row, 0);
glTranslatef(0.5, 0.5, 0); glRotatef(angle, 0, 0, 1); glTranslatef(-0.5, -0.5, 0);

This makes it clear that it’s a a scale, a translation to the appropriate cell, then a rotation about the centre of that cell.

For the signed unit square (-1…+1):


float s = 0.5/16;
glScalef(s, s, s);
glTranslatef(column+0.5, row+0.5, 0);
glRotatef(angle, 0, 0, 1);

Thanks to everyone for the replies

GClements in particular got the gist…thank you very much! you saved me from going around in circles D:
I was not properly scaling, applying that as a simple offset without reflecting it on the rotation matrix!
Ty again!

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.