PDA

View Full Version : Rotate a subtexture from a sprite atlas to apply to a point sprite



Apollonio
06-15-2016, 12:06 PM
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

mhagain
06-15-2016, 12:37 PM
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.

Alfonse Reinheart
06-15-2016, 12:56 PM
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 (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_A RRAY_TEXTURE_LAYERS). 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.

GClements
06-15-2016, 04:08 PM
That said for rotating:
- translate the texture to its origin
- rotate around z
- translate back

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);

Apollonio
06-16-2016, 04:47 AM
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!