Gotchas: Repeating textures in Cocos2d-x

This tutorial is compatible with Cocos2d-x v3.1.

Repeating textures can be used to make tiled backgrounds, floors, and for many other purposes. The stars in the image shown above are an example of this. The easiest way to repeat a texture is to put it in a separate file with power-of-two dimensions (also known as a POT texture), and display it using a Sprite with its wrapS and wrapT TexParams values set to GL_REPEAT. This is how to do that:

Texture2D::TexParams texParams;

texParams.magFilter = GL_LINEAR;

texParams.minFilter = GL_LINEAR;

texParams.wrapS = GL_REPEAT;

texParams.wrapT = GL_REPEAT;

Sprite* bgwrap = Sprite::create(“stars.png”, Rect(0, 0, visibleSize.width, visibleSize.height));

bgwrap->getTexture()->setTexParameters(texParams);

bgwrap->setPosition(visibleSize.width * 0.5f, visibleSize.height * 0.5f));

In this case, the screen size is larger than the size of the image file, therefore (in line 6) we try to reference points in the image file that do not exist. In situations like this, OpenGL needs to know how we want it to interpret such coordinates. We tell the engine how we want it to react by setting the values of wrapS and wrapT, where S is for the x-axis and T is for the y-axis.

We can either set these values to GL_CLAMP which means we want the texture edges to be repeated, or GL_REPEAT which means we want the whole texture to be repeated.

Animating the background

With a bit of GLSL goodness, we can animate the background and bring it to life. Here’s a fragment shader code that slowly moves the background for us:

precision highp float;

varying vec4 v_fragmentColor;    

varying vec2 v_texCoord;

//CC_Time[1] is time

void main()            

{

    vec2 new_uv = v_texCoord;

    new_uv.x = fract(new_uv.x + CC_Time[1] * 0.03);

    new_uv.y = fract(new_uv.y + CC_Time[1] * 0.01);

    gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, new_uv);    

}

We just need to render our background with this program:

auto p = GLProgram::createWithFilenames(“generic.vsh”, “uv.glsl”);            

bgwrap->setGLProgram(p);

Voila, now we have a moving repeated background!

Leave a Reply