Search code examples
openglopengl-escocos2d-xmarmalade

OpenGL 2.0 fragment shader not working with Cocos2d-X


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.


Solution

  • 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.