How to fix jittering sprites in cocos2d-x

Introduction
When using TexturePacker with Cocos2D-x, users may sometimes encounter wobbling, shaking or jittering sprites. This can be frustrating and reduces the quality of the game. In this tutorial, we will explain the causes of wobbling sprites and provide step-by-step instructions for fixing this issue.
The Role of Shader Precision
A sprite is a two-dimensional image used in games to represent characters, objects, and other elements. To render a sprite on the screen, Cocos2D-x uses the 3D graphics hardware of the device the game is running on.
In Cocos2D-x, shaders are used to calculate the colors of pixels in a sprite for rendering on the screen. Shaders can be used with different precisions - lowp
, mediump
, or highp
. The table below shows the range of values and fractional accuracy for each level of precision:
Precision | Range of Values | Fractional accuracy |
---|---|---|
lowp | (-2,2) | 2^(-8)=0.00390625 |
mediump | (-2^(14),2^(14)) | 2^(-10)=0.0009765625 |
highp | (-2^(62), 2^(62)) | 2^(-16)=0.0000152587 |
As you can see, the lowp
precision has the smallest range of values and the least accurate calculations. The highp
precision has the largest range of values and the most accurate calculations. The mediump
precision falls in between these two levels of precision.
Cocos2D-x's standard shaders use mediump
. This can cause problems because the fractional accuracy of this precision can only address single pixels up to a texture size of 1024. With a texture size of 2048, only every 2nd pixel can be addressed precisely.
How to fix jittering sprites in cocos2d-x
To fix this issue in cocos2d-x, you have two options:
-
Reduce the sprite sheet size to 1024: This is quite surely not the solution you want to use because this size puts hard restrictions on how you use the sprite sheets.
-
Modify the shaders to use high precision: This option is easy to implement, but the shaders might not work on older devices that do not support high precision.
I was not able to get any statistics how many old devices do not support highp. However, the fact that cocos2d-x still uses the mediump in their shaders leads to the conclusion that there must be at least some...
Modifying the shaders
There are two options for modifying the shaders in cocos2d-x. The first is to modify the shaders directly in cocos2d-x, but this means that you will have to fix the shaders each time you update cocos2d in your project. The advantage of this method is that you don't have to change your source code.
The second option is to set a custom shader on the SpriteBatchNode
you are using to
render the sprites. This allows you to make changes to the shaders without affecting the
cocos2d-x code, but it means that you will have to set them everywhere you use them.
To ensure that the shaders work on as many devices as possible, you can wrap the precision settings with an if-def. This will allow the high precision settings to be used only on devices that support them, while ensuring that the shaders will still work on older devices that do not support high precision. This means that the jittering sprites may still be visible on some devices, but it is a trade-off that you may be willing to accept in order to ensure compatibility with a wider range of devices.
In the vertex shaders (found under cocos/2d/renderer/shaders) change
varying mediump vec2 v_texCoord;
to
#ifdef GL_FRAGMENT_PRECISION_HIGH
varying highp vec2 v_texCoord;
#else
varying mediump vec2 v_texCoord;
#endif
In positionTextureColor.vert which is used by the SpriteBatchNode
this would look like this:
attribute highp vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
uniform highp mat4 u_MVPMatrix;
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
varying highp vec2 v_texCoord;
#else
varying mediump vec2 v_texCoord;
#endif
varying lowp vec4 v_fragmentColor;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif
void main()
{
gl_Position = u_MVPMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
Conclusion
In conclusion, jittering sprites in Cocos2D-x can be fixed by modifying the shaders to use high precision. This can be done by modifying the shaders directly in Cocos2D-x, or by setting a custom shader on the SpriteBatchNode being used to render the sprites.
It is important to note that using high precision shaders may not work on all devices, but the esimated number of devices it does not work on should be quite small. By following the steps outlined in this tutorial, you can fix jittering sprites and improve the quality of your games.