因为项目需求,现在需要用到同一张图的不同颜色的状态。直接增加美术资源的方式不仅会占用内存,而且程序工作量也会增加。所以在网上找了一下关于如何使用shader的资料
首先,找到了官方论坛的一个帖子:在 cocos2d-x 3.x中使用shader实现精灵色相(Hue)的修改
然后打开了LZ分享的git链接:Hue rotation for sprites in cocos2d game engine
还找到一个中文版的,貌似是某位有心人仔细整理过的:Hue rotation for sprites in cocos2d-x,ported from Cocos2d-iPhone.
偷了个懒,于是看了中文版的README.md,然后用Git大神提供的SpriteWithHue写了一个测试的项目:TestColor
但是,美术说这个只是修改了图片的色相,对美术来说,并不够用。还需要能修改饱和度、亮度属性。
因为并没有理解在Cocos2dx中如何操作Shader来修改纹理,所以我又在网上找了一番。
找到了这样一篇附带代码的博客:cocos2dx 更改sprite色相 饱和度 亮度
使用第1段代码创建了一个colorHSL.fsh,放在了资源文件夹下。
新建了一个HSLSprite类,继承自Sprite,写完基础的内容后。把第2段代码添加到HSLSprite.h中。
然后看到是酱紫的,因为版本的原因(博客中使用的cocos2d-x 2.2,这里使用的cocos2d-x 3.10),很多内容不能使用。
然后逐一查看了新的替换版本,对原来的代码进行了修改。修改后是酱紫的
有一点需要注意的就是旧版本的CGLProgramWithUnifos被替换成了GLProgram
然后编译通过了,直接run一下试试,发现还是不能用。控制台报错是酱紫的
大概搜了一下这个错误,然后有个哥们解决过这个问题了:2dx-lua精灵置灰
方法就是直接注释掉uniformsampler2D CC_Texture0;这行。从报错信息中其实可以看到'CC_Texture0'不能被重复声明。
然后我在HelloWorldScene中添加了这样一段测试代码
cocos2d::Size screenSize = Director::getInstance()->getWinSize(); HSLSprite* sp = HSLSprite::create(); sp->initWithFile("alien.png"); sp->setPosition(screenSize * 0.5); sp->setHSLMode();<span style="white-space:pre"> </span> sp->setHSL(300,0); this->addChild(sp);果然,图片颜色就被修改了
原图:
然后发现一件很郁闷的事,为什么我测试代码中写的是把精灵放在屏幕中心,但是修改过色相属性的图像却偏移了位置呢。?
在查这个问题时,发现很多童鞋都有遇到。但是解决方式基本是这样的
然而查找了一下colorHSL.fsh和HSLSprite类,并没有用到CC_MVPMatrix和CC_PMatrix这两个东西(其实这个东东在引擎代码中,不过最好不要改引擎代码咯)。然后继续找
发现另外一个会影响坐标的问题:cocos2dx 3.x ccPositionTextureColor_vert与ccPositionTextureColor_noMVP_vert
也就是要把
void HSLSprite::setHSLMode()
中的pProgram->initWithByteArrays(ccPositionTextureColor_vert,fragSource);
改为pProgram->initWithByteArrays(ccPositionTextureColor_noMVP_vert,fragSource);
这样就可以了,原因在上面的博客中有讲到。
然后再运行了一次,就ok咯,效果是酱紫。
sp->setHSL(300,0,0.3);
效果如下:
简直完美~
之前在Shadertoy上写过一些小示例,结合这个在cocos2d-x中使用的例子,对shader在cocos2dx中的使用又了解了不少。后面继续去完善一下工具。