3
\$\begingroup\$

This is a frustrating discovery. I have ported my desktop game to mobile and discovered that floating point precision in my shaders is not good.

I have large animations which I store per frame on a texture atlas. I try to keep as many non-unique frames in their own sections and piece them together e.g. a sword that doesn't animate for 4 frames is a node that attaches to the hand piece. This preserves memory.

However the texture atlases are so big that, when I use shaders, it breaks the animation completely.

Here's an example of one of the shaders that wraps the animated backgrounds (scrolling clouds)

precision highp float;
precision highp int;
precision highp sampler2D;

varying vec2 vTexCoord;
varying vec4 vColor;
uniform sampler2D texture;

// this script animates and wraps an animated background from one atlas
uniform float x; // frame start x
uniform float y; // frame start y
uniform float w; // frame width
uniform float h; // frame height
uniform float offsetx; // wrap by x amount
uniform float offsety; // wrap by y amount

void main()
{
    vec2 origin = vec2(x, y);
    vec2 size   = vec2(w, h);

    // Get the texture coordinate
    vec2 texCoord = vTexCoord;

    // Make its lower-left be at (0,0) and it's upper right be at (1,1)
    texCoord = (texCoord - origin) / size;

    // Apply the offest
    texCoord = texCoord + vec2(offsetx,offsety);

    // Apply the wrapping
    texCoord = fract(texCoord);

    // Convert back to texture atlas coordinates
    texCoord = (texCoord * size) + origin;

    gl_FragColor = texture2D(texture, texCoord) * vColor;
}

For most backgrounds, the animations are small and don't cause problems. But some backgrounds are large and their texture atlas is large. The floating point precision breaks down and the animation tears.

I don't have much mobile experience. How can I use large textures atlases for animations without the x/y coordinates breaking due to loss of floating point precision?

\$\endgroup\$
  • 1
    \$\begingroup\$ Can you demonstrate for us the specific symptoms you're observing? 32-bit float texture coordinates give you precision to within a 256th of a pixel over an atlas 32000 pixels across, and the 24.8 fixed point interpolation typically implemented by the GPU doesn't cut into this. So, floating point precision shouldn't be a limiting factor here if you're careful with it. The tearing you observe might be due to another source. \$\endgroup\$ – DMGregory May 6 at 21:56
  • \$\begingroup\$ My background in question is 2880x160 where each frame is set to 240x160. There's not much to show. Both large backgrounds and large texture atlases used by my sprites suffer from a conglomerate blocky mess when using these offset shader scripts. Small textures atlases are just fine. \$\endgroup\$ – Dan May 6 at 22:24
  • 1
    \$\begingroup\$ Can you show us a screenshot so we're completely unambiguous about what the "conglomerate blocky mess" you're seeing looks like? An animated gif can help too of the artifacts are more obvious in motion. \$\endgroup\$ – DMGregory May 6 at 22:27
  • \$\begingroup\$ Yes I can get one to you give me some time to record and edit \$\endgroup\$ – Dan May 6 at 23:43
  • 1
    \$\begingroup\$ @DMGregory here it is. You can make out that they are supposed to animate smoothly. The same code unchanged works fine on desktop. streamable.com/4k8cf \$\endgroup\$ – Dan May 7 at 0:36

Your Answer

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

Browse other questions tagged or ask your own question.