cocos2dx图片变灰

2015年02月12日 11:19 0 点赞 0 评论 更新于 2025-11-21 16:17

在cocos2dx中,实现图片变灰可以采用shader来完成,主要有以下两种方法:

  1. CCSprite一样使用create方法创建变灰的图片。
  2. 传入CCSprite对象,并传入一个用于标识图片是否变灰的标志位。具体实现可参考后续的代码及使用方法。

代码实现

GraySprite.h

//
//  GraySprite.h
//  goddess
//
//  Created by rekoo on 13-7-23.
//

#ifndef __goddess__GraySprite__
#define __goddess__GraySprite__

#include "cocos2d.h"
#include "cocos-ext.h"

USING_NS_CC;
USING_NS_CC_EXT;

class GraySprite : public CCSprite {
public:
GraySprite();
~GraySprite();

bool initWithTexture(CCTexture2D* texture, const CCRect& rect);
void draw();
void initProgram();
void listenBackToForeground(CCObject *obj);

static GraySprite* create(const char* pszFileName);
};

#endif /* defined(__goddess__GraySprite__) */

GraySprite.cpp

//
//  GraySprite.cpp
//  goddess
//
//  Created by rekoo on 13-7-23.
//
// 用shader创建灰度图, 用法跟sprite一样
//  lua用法: local sprite = GraySprite:create("pic.png")

#include "GraySprite.h"

GraySprite::GraySprite() {}

GraySprite::~GraySprite() {}

GraySprite* GraySprite::create(const char* pszFileName) {
GraySprite* pRet = new GraySprite();
if (pRet && pRet->initWithFile(pszFileName)) {
pRet->autorelease();
} else {
CC_SAFE_DELETE(pRet);
}
return pRet;
}

void GraySprite::listenBackToForeground(CCObject *obj) {
setShaderProgram(NULL);
initProgram();
}

bool GraySprite::initWithTexture(CCTexture2D* texture, const CCRect& rect) {
if (CCSprite::initWithTexture(texture, rect)) {
CCSize s = getTexture()->getContentSizeInPixels();
this->initProgram();
return true;
}
return false;
}

void GraySprite::initProgram() {
const GLchar * pfrag = "#ifdef GL_ES \n"
"    precision mediump float; \n"
"    #endif \n"
"    uniform sampler2D u_texture; \n"
"    varying vec2 v_texCoord; \n"
"    varying vec4 v_fragmentColor; \n"
"    void main(void) \n"
"    { \n"
"    float alpha = texture2D(u_texture, v_texCoord).a; \n"
"    float grey = dot(texture2D(u_texture, v_texCoord).rgb, vec3(0.299, 0.587, 0.114)); \n"
"    gl_FragColor = vec4(grey, grey, grey, alpha); \n"
"    } ";

CCGLProgram* pProgram = new CCGLProgram();
pProgram->initWithVertexShaderByteArray(ccPositionTextureColor_vert, pfrag);
setShaderProgram(pProgram);
pProgram->release();

CHECK_GL_ERROR_DEBUG();

getShaderProgram()->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
getShaderProgram()->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
getShaderProgram()->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);

CHECK_GL_ERROR_DEBUG();

getShaderProgram()->link();

CHECK_GL_ERROR_DEBUG();

getShaderProgram()->updateUniforms();
}

void GraySprite::draw() {
ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex);
ccBlendFunc blend = getBlendFunc();
ccGLBlendFunc(blend.src, blend.dst);

getShaderProgram()->use();
getShaderProgram()->setUniformsForBuiltins();

ccGLBindTexture2D(getTexture()->getName());

#define kQuadSize sizeof(m_sQuad.bl)
long offset = (long)&m_sQuad;

// vertex
int diff = offsetof(ccV3F_C4B_T2F, vertices);
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));

// texCoods
diff = offsetof(ccV3F_C4B_T2F, texCoords);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

// color
diff = offsetof(ccV3F_C4B_T2F, colors);
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

CC_INCREMENT_GL_DRAWS(1);
}

使用例子

方法一:使用create方法创建

GraySprite * gs = GraySprite::create("01.png");
// 后续操作与CCSprite相同,如设置位置、添加子节点等
gs->setPosition(ccp(100, 100));
addChild(gs);

方法二:传入CCSprite对象并设置变灰标志

CCSprite * cs = CCSprite::create("02.png");
// 变灰
GraySprite::setGray(cs, 1);
// 恢复原色
GraySprite::setGray(cs, 0);

Lua调用

GraySprite暴露给Lua后,Lua代码中可以方便地调用,示例如下:

local sprite = GraySprite:create("pic.png")

通过以上方法,我们可以在cocos2dx中轻松实现图片变灰的效果。

作者信息

boke

boke

共发布了 3994 篇文章