在游戏开发过程中,常常会用到使精灵变灰的功能,例如按钮的不可用,成就未达成等等。但是在cocos2dx中并没有直接提供类似的功能,但还好,基于shader也可以实现类似的效果。修改步骤如下:
首先,需要在cocos2d>>renderer目录中新建两个文件:
1:ccShader_PositionTextureGray.vert 并置入以下代码
const char* ccPositionTextureGray_vert = STRINGIFY(
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
\n#ifdef GL_ES\n
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
\n#else\n
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
\n#endif\n
void main()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
);
2:ccShader_PositionTextureGray.frag 并植入以下代码
const char* ccPositionTextureGray_frag = STRINGIFY(
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main()
{
vec4 normalColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);
// float gray = dot(normalColor.rgb, vec3(0.299 * 0.5, 0.587 * 0.5, 0.114 * 0.5));
float gray = dot(normalColor.rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(gray, gray, gray, normalColor.a);
}
);
在项目中引用这两个文件以后,则开始调用的过程
首先
在ccShaders.h中添加
extern CC_DLL const GLchar * ccPositionTextureGray_frag;
extern CC_DLL const GLchar * ccPositionTextureGray_vert;
在ccShaders.cpp中添加
#include "ccShader_PositionTextureGray.frag"
#include "ccShader_PositionTextureGray.vert"
其次
在CCGLProgram.h中添加
static const char* SHADER_NAME_POSITION_TEXTURE_GRAY;
在CCGLProgram.cpp中添加
const char* GLProgram::SHADER_NAME_POSITION_TEXTURE_GRAY = "ShaderPositionTextureGray";
最后需要更改的就是CCGLProgramCache.cpp文件了
1.在shader的枚举类型中添加
kShaderType_PositionTextureGray
2.在GLProgramCache::
loadDefaultGLPrograms()函数中添加以下代码
p = new GLProgram();
loadDefaultGLProgram(p, kShaderType_PositionTextureGray);
_programs.insert( std::make_pair( GLProgram::SHADER_NAME_POSITION_TEXTURE_GRAY, p ) );
3.在GLProgramCache::reloadDefaultGLPrograms()函数中添加以下代码
p = getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_GRAY);
p->reset();
loadDefaultGLProgram(p, kShaderType_PositionTextureGray);
4.在GLProgramCache::loadDefaultGLProgram(GLProgram*p, int type)函数中添加以下代码
case kShaderType_PositionTextureGray:
{
p->initWithByteArrays(ccPositionTextureGray_vert, ccPositionTextureGray_frag);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORD);
break;
}
以上修改完成!!!
在项目中使用的时候很简单
auto disabledSprite = Sprite::create(normalImage);
disabledSprite->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_GRAY));
以上!!!
更新:
工作中逐渐的发现了另一种简单高效的方法,封装后可以很简便的创建灰色的精灵:
Sprite* sprite = Sprite::create("fileName");
GLchar* boSource =
"#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 \
// Convert to greyscale using NTSC weightings \n \
vec4 col = texture2D(u_texture, v_texCoord); \n \
float grey = dot(col.rgb, vec3(0.299, 0.587, 0.114)); \n \
gl_FragColor = vec4(grey, grey, grey, col.a); \n \
}";
GLProgram* boProgram = new GLProgram();
boProgram->initWithByteArrays(ccPositionTextureColor_noMVP_vert, boSource);
sprite->setGLProgram(boProgram);
boProgram->release();
CHECK_GL_ERROR_DEBUG();
sprite->getGLProgram()->bindAttribLocation( GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
sprite->getGLProgram()->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
sprite->getGLProgram()->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORD);
CHECK_GL_ERROR_DEBUG();
sprite->getGLProgram()->link();
CHECK_GL_ERROR_DEBUG();
sprite->getGLProgram()->updateUniforms();
CHECK_GL_ERROR_DEBUG();
return sprite;