0

I am developing a game using Cocos2d-X 2.2.3 and Marmalade SDK 7.4 and I have created a fragment shader to desaturate some of my sprites, or in other words to remove all color from them and show them only in shades of gray (black and white).

The shader that I wrote is this one:

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D u_texture;

void main()
{
    float grayScaleValue;
    vec3 originalColor;

    originalColor = texture2D(u_texture, v_texCoord).rgb;

    grayScaleValue = 0.21 * originalColor.r + 0.72 * originalColor.g + 0.07 * originalColor.b;

    gl_FragColor = vec4(grayScaleValue, grayScaleValue, grayScaleValue, 1);
}

I took the algorithm to calculate the grayscale values from this page.

The code that I am using to load this shader is the following:

// Please note that the class: GameObjectSprite is a subclass of CCSprite.
void GameObjectSprite::initShaders()
{
    const GLchar *shaderSource = (const GLchar*) CCString::createWithContentsOfFile("shaders/Grayscale.fsh")->getCString();

    shader = new CCGLProgram();
    shader->initWithVertexShaderByteArray(ccPositionTextureA8Color_vert, shaderSource);
    shader->addAttribute(kCCAttributeNamePosition, kCCVertexAttribFlag_Position);
    shader->addAttribute(kCCAttributeNameColor, kCCVertexAttribFlag_TexCoords);

    CHECK_GL_ERROR_DEBUG();
    shader->link();

    shader->updateUniforms();
    CHECK_GL_ERROR_DEBUG();

    this->setShaderProgram(shader);
    this->getShaderProgram()->use();
}

Unfortunately my shader is not working and the sprites are showing normal colors, just as if I didn't made any changes to their shader.

Felipe
  • 6,312
  • 11
  • 52
  • 70
  • You have to apply the shader when drawing the sprites too. Somewhere in the drawing code, you need to have a `getShaderProgram()->use();`. – glampert Sep 16 '14 at 02:31
  • Hi, actually I think that the problem was that I was using a Sprite Batch Node to render my sprites. I believe that the batch node overrides the draw call for each sprite and that is why nothing was happening. However I still have a problem, now that I am actually using my shader, all my sprites have disapeared. I changed my code so it would only have: `gl_FragColor = texture2D(u_texture, v_texCoord);` just like a normal shader, but still my sprites are missing. Note: I've also added `getShaderProgram()->use();` to the draw method. – Felipe Sep 17 '14 at 01:19
  • That might be a problem with the Vertex Shader. You have to make sure the matrices are properly set so that the vertexes get transformed. – glampert Sep 17 '14 at 01:24
  • Well I believe that I am using the standard vertex shader (`ccPositionTextureA8Color_vert`). And I am using this to send the position of the sprite to the shader: `shader->addAttribute(kCCAttributeNamePosition, kCCVertexAttribFlag_Position);`. Is there anything else that I should do? – Felipe Sep 17 '14 at 01:38
  • Yes, the position is probably multiplied by a matrix (the [MVP](http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/) matrix), which is a uniform variable of that shader. You have to set that variable before drawing. – glampert Sep 17 '14 at 01:40

1 Answers1

0

I managed to solve it. I think that as @glampert said I wasn't loading the MVP matrix correctly. Here is my new code:

void GameLayer::loadShaders()
{
    CCGLProgram *shader;
    const GLchar *fragmentShader;

    shader = new CCGLProgram();

    fragmentShader = CCString::stringWithContentsOfFile("Grayscale.fsh")->getCString();

    shader->initWithVertexShaderByteArray(ccPositionTextureA8Color_vert, fragmentShader);
    shader->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
    shader->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);

    CHECK_GL_ERROR_DEBUG();
    shader->link();

    shader->updateUniforms();
    CHECK_GL_ERROR_DEBUG();

    sprite->setShaderProgram(shader);
    sprite->getShaderProgram()->use();
}

Notice that I changed the value of the lines below from:

shader->addAttribute(kCCAttributeNamePosition, kCCVertexAttribFlag_Position);
shader->addAttribute(kCCAttributeNameColor, kCCVertexAttribFlag_TexCoords);

To:

shader->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
shader->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);    

Also, I am no longer using a sprite batch node to draw my sprites.

Felipe
  • 6,312
  • 11
  • 52
  • 70