在cocos2d-x中有两个类CCGLProgram和CCShaderCache.CCGLProgram类来处理着色器相关操作,对当前绘图程序进行了封装.CCShaderCache通过CCGLProgram来完成对shaders的缓存和管理.这两个类的功能在项目中经常用到,比如实现图象由正常颜色变成灰色(好处是减少资源图),还有在刀塔传奇中用使人物冰封,,石化等效果都是用shader.
这里对于这两个类的功能不作深入讨论,因为本人也是刚刚接触,这里主要是介绍在Quick-cocos2dx-lua -v2.2.6版本中如何配置和使用这个功能。
因为Quick-cocos2dx-lua -v2.2.6版本中没有在tolua中导出CCGLProgram,所以lua中不能使用。
接下来就是生成可以使用CCGLProgram的framework和player
第一:找到CCGLProgram.h和CCGLProgram.cpp,:
在CCGLProgram.h中声明以下两个函数:
static CCGLProgram* createWithByteArrays(const char* vShaderByteArray, const char* fShaderByteArray);static CCGLProgram* createWithFilenames(const char* vShaderFilename, const char* fShaderFilename);
在CCGLProgram.cpp实现这两个方法(这两个方法可以参考v3.5):
CCGLProgram* CCGLProgram::createWithByteArrays(const char* vShaderByteArray, const char* fShaderByteArray){ CCGLProgram* ret = new CCGLProgram(); if(ret && ret->initWithVertexShaderByteArray(vShaderByteArray, fShaderByteArray)) { ret->autorelease(); return ret; }
CC_SAFE_DELETE(ret); return nullptr;}
CCGLProgram* CCGLProgram::createWithFilenames(const char* vShaderFilename, const char* fShaderFilename){ auto ret = new CCGLProgram(); if(ret && ret->initWithVertexShaderFilename(vShaderFilename, fShaderFilename)) { ret->autorelease(); return ret; }
CC_SAFE_DELETE(ret); return nullptr;}
注掉:CCGLProgram构造方法中两行:
// there is no need to delete the shaders. They should have been already deleted. //CCAssert(m_uVertShader == 0, "Vertex Shaders should have been already deleted"); //CCAssert(m_uFragShader == 0, "Fragment Shaders should have been already deleted");
第二:修改framework
进入lib\luabinding\cocos2dx\draw_nodes,新建文件CCGLProgram.tolua,内容如下:
class CCGLProgram : public CCObject{ static CCGLProgram* createWithByteArrays(const char* vShaderByteArray, const char* fShaderByteArray); static CCGLProgram* createWithFilenames(const char* vShaderFilename, const char* fShaderFilename); void addAttribute(const char* attributeName, GLuint index); bool link(); void use(); void updateUniforms();
}
注:这里是导出你所需要的公共方法,供在lua中调用。
修改:lib\luabinding\cocos2dx\Cocos2d.tolua,
增加 $pfile "cocos2dx/draw_nodes/CCGLProgram.tolua"
接下执行tolua指令,由quick cocos framework提供:
执行:lib\luabinding\build.bat,和\bin\compile_luabinding.bat
执行完命令后检查tolua绑定:
\lib\cocos2d-x\scripting\lua\cocos2dx_support\LuaCocos2d.cpp是否生成CCGLProgram相关绑定函数
生成:framework_precompiled.zip
执行bat:bin\make_framework_package.bat会重生生成framework_precompiled.zip
第三:生新编译生成player.exe
因为修改了cpp(LuaCocos2d.cpp,CCGLProgram.cpp),需要重新编译player.
用vs2013直接打开player\proj.win32\player.vcxproj编译就可以了。
第四:简单应用shader:
local pProgram = CCGLProgram:createWithFilenames("res/shader/IceShader.vsh","res/shader/IceShader.fsh")
self.sp = display.newSprite("house.png"):addTo(self)self.sp:setPosition(300, 100)pProgram:addAttribute("a_position", 0) –对应vs里面的顶点坐标 pProgram:addAttribute("a_color", 1) –对应vs里面的顶点颜色 pProgram:addAttribute("a_texCoord", 2)–对应vs里面的顶点纹理坐标 pProgram:link() — 因为绑定了属性,所以需要link一下,否则vs无法识别属性 pProgram:updateUniforms() — 绑定了纹理贴图 self.sp:setShaderProgram(pProgram)
注:
IceShader.fsh内容:
#ifdef GL_ESprecision mediump float;#endif
varying vec4 v_fragmentColor;varying vec2 v_texCoord;uniform sampler2D u_texture;
void main(){ vec4 color1 = texture2D(u_texture, v_texCoord) * v_fragmentColor;float brightness = (color1.r + color1.g + color1.b) * (1. / 3.);float gray = (1.5)*brightness;color1 = vec4(gray, gray, gray, color1.a)*vec4(0.8,1.2,1.5,1); gl_FragColor =color1;}
IceShader.vsh文件内容:
attribute vec4 a_position;attribute vec2 a_texCoord;attribute vec4 a_color;
#ifdef GL_ESvarying lowp vec4 v_fragmentColor;varying mediump vec2 v_texCoord;#elsevarying vec4 v_fragmentColor;varying vec2 v_texCoord;#endif
void main(){gl_Position = CC_MVPMatrix * a_position;v_fragmentColor = a_color;v_texCoord = a_texCoord;}
程序运行结果:
来说是非者,便是是非人。