1
\$\begingroup\$

I'm writing an OpenGL ES (2.0) app and have a custom Quad class which draws a textured quad for my sprites.

Currently, I put the textures of any sprites of the same size into a single file or atlas, then, when drawing, I can simply specify the frame I want. It will the render the correct frame based on how many textures in the atlas and how many total frames etc. Something like so:

mySprite.x = 0;
mySprite.y = 0;
mySprite frame = 1;
drawSprite(mySprite);

The texture Atlas would look something like this: (Simplified for the purpose of this question, in the real project, there are over 200 textures arranged in neat rows/columns, but the important thing is there is order, every texture is the same size as this is necessary for the calculations).

enter image description here

So, in the example above, I can say, there are 2 columns, 1 row and a total of 2 textures.

So, if I specify 1 as my texture (2nd texture), my sprite class can work out (using the columns, rows, total textures etc..) which texture I want and how to get it. As I said this is simplified, the calculations are a little but more involved when there are multiple rows. But it makes doing animations nice and simple as I can simply increment or decrement the current frame.

However, I keep seeing sprite sheets where there is no order. There are different sized textures seemingly thrown into an atlas like so:

enter image description here

I really would like to go down this route as it means I wouldn't have to separate my sprite sheets by object size, and therefore, vastly reduce the number of separate sheets I have to use.

I can't however work out how one would write a calculation to get the correct texture just by specifying the texture number to render.

So how does this work? Do I need to manually work out the texel coordinates of each and every object (and indeed frame), manually (and maybe store this value in an array and associate it to a frame number?) or am I missing a trick here somewhere?

\$\endgroup\$
2
\$\begingroup\$

Your hunch is correct.

There must be external information mapping regions of the image to sprites unless all the information the application needs can be derived from hardcoded knowledge and regularity. Even in your regular grid-based example, you lack some information for the general case.

Common metadata for sprite sheets are:

  • origin, a location inside the sprite that indicates the logical center of it;
  • collision extents, the collision hitbox for a sprite is often smaller than the visual, to balance gameplay fairness and how much a sprite can visually penetrate something else without colliding;
  • identifier/name, for sprite sheets used for visuals for different objects, a way of finding which sprite in the sheet is the one desired is typically done via lookup by name/ID, the metadata would contain a mapping of these.
\$\endgroup\$
  • \$\begingroup\$ Thanks @LarsViklund. Can you elaborate on what you mean by "you lack some information like origin, collision extents, named identifier." - I'm guessing with collision extents you mean coordinates for collision purposes (if different from the texture coordinates) but I'm not sure about the other 2 things you mention - would be grateful if you could expand on this slightly and I'll accept the question - cheers! \$\endgroup\$ – BungleBonce Oct 25 '14 at 19:18
2
\$\begingroup\$

using a single vec4 uniform you can use arbitrary sized sprites:

uniform vec4 spriteLoc;//x and y is the relative offset and z and w is the scaling factor

varrying vec2 texCoord;//0-1 as you would without the atlas

main(){
   gl_fragColor = sampler2D(atlas, texCoord.xy*spriteLoc.zw + spriteLoc.xy);
}
\$\endgroup\$
  • \$\begingroup\$ Thanks @RatcetFreak I'm not sure I understand though. I can already size my sprites by manipulating the vertices. However, the problem to which I'm referring in this question, is specifically how to grab textures from an atlas/spritesheet. \$\endgroup\$ – BungleBonce Oct 25 '14 at 19:20
  • \$\begingroup\$ @user22241 by manipulating the spriteLoc uniform, if you want the 5 row and 2 column on a 8x8 spritesheet you can pass in, {2.0/8.0, 5.0/8.0, 8.0, 8.0} \$\endgroup\$ – ratchet freak Oct 25 '14 at 19:28
  • \$\begingroup\$ Thanks again @RatchetFreak but I want a sprite sheet with 'random' objects - ie one that doesn't conform to a strict grid (of x rows by x columns). This is what I'm asking about. Again, I may be misunderstanding you. Thanks. \$\endgroup\$ – BungleBonce Oct 25 '14 at 21:45
  • \$\begingroup\$ @user22241 well then then the spriteLoc will be {xOffset/width, yOffset/height, spriteWidth/width, spriteHeight/height} \$\endgroup\$ – ratchet freak Oct 25 '14 at 21:49

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.