A Monochromatic OpenGL ES 2.0 Filter for Cocos2d Sprite Effects

Cocos2d 2.x is based on OpenGL ES 2.0 which allows custom vertex and fragment shaders for realtime sprite texture effects.

To render a sprite in grayscale, follow these steps.

1) Add a C file to your project to your Cocos2d project in XCode (Let’s call it CCMonochromeKBFilter.fsh)

This will be the fragment shader that applies the color effect. Cocos2d already has a vertex shader that has the requirements for this effect, in ccShader_PositionTextureA8Color_vert.h

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D u_texture;

void main()
{
    vec4 normalColor = texture2D(u_texture, v_texCoord);
    highp float grey = dot(normalColor.rgb, vec3(0.299, 0.487, 0.114));
    gl_FragColor = vec4((normalColor.r * grey), (normalColor.g * grey), (normalColor.b * grey), normalColor.a);
}

The values 0.299, 0.487, 0.114 are the hue shift. You can shift the hue in any which way. For example, 0.9, 1.1, 1.2 would represent a sepia image effect.

2) Drop the C file in XCode -> Project -> Targets -> “Copy Bundle Resources”.

Copy Bundle Resources, XCode 4.5
Copy Bundle Resources, XCode 4.5

3) Add it to the shader cache.

[[CCShaderCache sharedShaderCache] addProgram:[[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTextureA8Color_vert fragmentShaderByteArray:(GLchar*) [[NSString stringWithContentsOfFile:[[CCFileUtils sharedFileUtils] fullPathFromRelativePath:@"CCMonochromeKBFilter.fsh"] encoding:NSUTF8StringEncoding error:nil] UTF8String]] forKey:@"monochromekb"];

4) Tell the sprite to use the shader from the shader cache

 spr.shaderProgram = shader;
[spr.shaderProgram addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position];
[spr.shaderProgram addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords];
 [spr.shaderProgram link];
[spr.shaderProgram updateUniforms];

Leave a Reply

HTML tags are not allowed.