如何在cocos2d中着色灰度CCSprite?

时间:2013-01-28 05:44:14

标签: cocos2d-iphone shader grayscale colorize

我想通过编程为cocos2d中的灰度CCSprite着色,例如,灰度CCSprite是:

http://cc.cocimg.com/bbs/attachment/Fid_18/18_171059_43b48b6f1bc40a5.png

输出CCSprite是:

http://cc.cocimg.com/bbs/attachment/Fid_18/18_171059_574b2f34cb78b49.png

但我无法得到正确的结果。

如果我使用[CCSprite setColor],我的CCSprite是黑暗的 我使用了CCRenderTexture并尝试了两种不同的blendFunc,

-(CCSprite *) try1:(CCSprite *)gray color:(ccColor3B) color
{
    CCRenderTexture *rtx = [CCRenderTexture renderTextureWithWidth:gray.contentSize.width height:gray.contentSize.height];
    ccColor4F c = ccc4FFromccc3B(color);
    [rtx beginWithClear:c.r g:c.g b:c.b a:c.a];
    gray.position = ccp(gray.contentSize.width/2, gray.contentSize.height/2);
    gray.blendFunc = (ccBlendFunc){GL_ONE_MINUS_SRC_COLOR, GL_SRC_COLOR};
    [gray visit];
    [rtx end];

    CCSprite *sp = [CCSprite spriteWithTexture:rtx.sprite.texture];
    sp.flipY = YES;
    return sp;
}

另一个是:

-(CCSprite *) try2:(CCSprite *)gray color:(ccColor3B) color
{
    CCRenderTexture *rtx = [CCRenderTexture renderTextureWithWidth:gray.contentSize.width height:gray.contentSize.height];
    ccColor4F c = ccc4FFromccc3B(color);
    [rtx beginWithClear:c.r g:c.g b:c.b a:0];
    gray.position = ccp(gray.contentSize.width/2, gray.contentSize.height/2);
    gray.blendFunc = (ccBlendFunc){GL_SRC_COLOR, GL_SRC_ALPHA};
    [gray visit];
    [rtx end];

    CCSprite *sp = [CCSprite spriteWithTexture:rtx.sprite.texture];
    sp.flipY = YES;
    return sp;
}

我甚至试过着色器:

#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D u_texture;
varying vec2 v_texCoord;
varying vec4 v_fragmentColor;

uniform vec4 u_fillcolor;

#pragma debug(on)

void main(void)
{
    vec4 c = texture2D(u_texture, v_texCoord);

    float r;
    float g;
    float b;

    r = u_fillcolor.r + (2.0 * c.r - 1.0);
    g = u_fillcolor.g + (2.0 * c.g - 1.0);
    b = u_fillcolor.b + (2.0 * c.b - 1.0);

    gl_FragColor = vec4(r,g,b, c.a);
}

但输出不正确。

你能帮我找到输出正确CCSprite的方法吗?

感谢。

(我是stackoverflow的新用户,我的声誉不足以添加图片,因此我必须将图片添加为链接。)

1 个答案:

答案 0 :(得分:0)

如果您不经常更改颜色,此方法将起作用。

typedef struct _SOARGB {
    unsigned char a;
    unsigned char r;
    unsigned char g;
    unsigned char b;
} SOARGB;

+(CGImageRef)colorizeImage:(CGImageRef)image {
    CGContextRef contextRef = [self createARGBBitmapContext:image];
    NSAssert(contextRef != nil, @"Failed to create context");
    // Get image width, height. We'll use the entire image.
    size_t width = CGImageGetWidth(image);
    size_t height = CGImageGetHeight(image);
    CGRect rect = {{0,0},{width,height}};

    // Draw the image to the bitmap context.
    CGContextDrawImage(contextRef, rect, image);

    // Get a pointer to the image data associated with the bitmap context.
    SOARGB *data = (SOARGB*)CGBitmapContextGetData (contextRef);
    NSAssert(data != NULL, @"Could not retrieve pixel data from context");

    //
    // Do the colorization job.
    //

    // This colorization method is ONLY an example and
    // should probably be changed!
    SOARGB tint;
    tint.r = 255;
    tint.g = 0;
    tint.b = 0;
    tint.a = 0;

    for (int i = 0; i < width*height; i++) {
        SOARGB *c = &data[i];
        CGFloat alpha = c->r / 255.0;
        c->r -= (c->r - tint.r)*0.3*alpha*alpha;
        c->g -= (c->g - tint.g)*0.3*alpha*alpha;
        c->b -= (c->b - tint.b)*0.3*alpha*alpha;
    }

    // End of coloriation job

    // Create image from modified context
    return CGBitmapContextCreateImage(contextRef);
}

+(CGContextRef)createARGBBitmapContext:(CGImageRef)inImage {
    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    void *          bitmapData;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;

    // Get image width, height. We'll use the entire image.
    size_t pixelsWide = CGImageGetWidth(inImage);
    size_t pixelsHigh = CGImageGetHeight(inImage);

    // Declare the number of bytes per row. Each pixel in the bitmap in this
    // example is represented by 4 bytes; 8 bits each of red, green, blue, and
    // alpha.
    bitmapBytesPerRow   = (pixelsWide * 4);
    bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

    // Use the generic RGB color space.
    colorSpace = CGColorSpaceCreateDeviceRGB();
    if (colorSpace == NULL)
    {
        fprintf(stderr, "Error allocating color space\n");
        return NULL;
    }

    // Allocate memory for image data. This is the destination in memory
    // where any drawing to the bitmap context will be rendered.
    bitmapData = malloc( bitmapByteCount );
    if (bitmapData == NULL)
    {
        fprintf (stderr, "Memory not allocated!");
        CGColorSpaceRelease( colorSpace );
        return NULL;
    }

    // zeroing out the data
    memset(bitmapData, 0, bitmapByteCount);

    // Create the bitmap context. We want pre-multiplied ARGB, 8-bits
    // per component. Regardless of what the source image format is
    // (CMYK, Grayscale, and so on) it will be converted over to the format
    // specified here by CGBitmapContextCreate.
    context = CGBitmapContextCreate (bitmapData,
                                     pixelsWide,
                                     pixelsHigh,
                                     8,      // bits per component
                                     bitmapBytesPerRow,
                                     colorSpace,
                                     kCGImageAlphaPremultipliedFirst);
    if (context == NULL)
    {
        free (bitmapData);
        fprintf (stderr, "Context not created!");
    }

    // Make sure and release colorspace before returning
    CGColorSpaceRelease( colorSpace );

    return context;
}

使用上述方法加载精灵:

UIImage *image = [UIImage imageNamed:@"myImage.png"];
CGImageRef colorizedImageRef = [self colorizeImage:image.CGImage];
CCSprite *colorizedSprite = [CCSprite spriteWithCGImage:colorizedImageRef key:@"myImage"];

希望这有帮助。