转载请标明:转载自【小枫栏目】,博文链接:http://blog.csdn.net/rexuefengye/article/details/12054393
精灵有个成员函数:setBlendFunc(),这个函数以一个ccBlendFunc类型的变量为参数。这个ccBlendFunc是个结构体。这个结构体中有两个变量:src 和 dest. 举个例子:
代码:
ccBlendFunc spriteBlend;
spriteBlend.src = GL_ONE;
spriteBlend.dst = GL_ZERO;
pSprite->setBlendFunc(spriteBlend);
假设精灵pSprite是源颜色.则setBlendFunc的作用就是把精灵pSprite的各个像素的R,G,B,A分量和源颜色因子1.0(src = GL_ONE)相乘. 如果精灵pSprite是目标颜色,则setBlendFunc的作用就是把精灵pSprite的各个像素的R,G,B,A分量和目标颜色因子(dst = GL_ZERO)相乘.
如何界定pSprite是源颜色还是目标颜色呢?
如果这个时候还存在一个精灵pSpriteOther.如果pSprite先调用visit(), 然后pSpriteOther后调用visit()(visit()的作用是递归的渲染精灵和他的孩子节点)。。。则先调用visit()的为目标颜色,后调用visit的为源颜色。即:pSprite是目标颜色 ,pSpriteOther为源颜色。
你可能会觉得我们只需要先把mask(遮罩)精灵渲染上去,然后再渲染被遮罩的精灵,并且指定这两个精灵的blendFunc就行了。可是,实际上这样是行不通的!
因为被渲染上去的mask精灵下面如果还有其他的精灵。这样的话被渲染到mask精灵之上的精灵在做颜色混合的时候会出现意想不到的结果。达不到我们做遮罩的效果。
这样的话,我们需要一个比较干净的画板,这个干净的画板只有两个精灵在做颜色混合。这样的话这两个精灵在做颜色混合的时候就能达到我们想要的结果。不会受到不干净的背景造成的混合误差。这个背景就是CCRenderTexture.
当然如果我们的layer上只有精灵做混合的话就用不着CCRenderTexture了。但是实际项目中基本上是不能的。
HelloWorldScene.cpp
bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } CCSize size = CCDirector::sharedDirector()->getWinSize(); //创建干净的画板 CCRenderTexture *pRt = CCRenderTexture::create(size.width,size.height); CCAssert(pRt, "RenderTexture is invalid"); addChild(pRt); pRt->setPosition(size.width/2,size.height/2); //创建遮罩图片 CCSprite *pMask = CCSprite::create("CalendarMask.png"); CCAssert(pMask, "mask sprite is invalid"); pMask->setPosition(CCPointMake(pMask->getContentSize().width/2, pMask->getContentSize().height/2)); //创建被遮罩图片 CCSprite *pFlower = CCSprite::create("Calendar1.png"); CCAssert(pFlower, "Flower sprite is invalid"); pFlower->setPosition(CCPointMake(pFlower->getContentSize().width/2, pFlower->getContentSize().height/2)); //先设置好 遮罩精灵 和 被遮罩精灵 在被渲染的时候采用什么样的颜色混合法则 ccBlendFunc maskBlend = {GL_ONE,GL_ZERO}; ccBlendFunc flowerBlend = {GL_DST_ALPHA, GL_ZERO}; pMask->setBlendFunc(maskBlend); pFlower->setBlendFunc(flowerBlend); //开始把各种精灵渲染到画板上 pRt->begin(); //先渲染遮罩精灵。但是因为有个画板先被渲染。所以pMask是第二个被渲染的,即后被渲染。 //所以在这一刻pMask是源颜色。调用pMask->visit()的时候吧精灵pMask上的每个像素的RGBA分量和1.0相乘。 //所以遮罩图片被元模原样的渲染出来. pMask->visit(); //再渲染被遮罩的精灵.在这一刻,之前先有pMask被渲染。所以pFlower后被渲染。pFlower就是源颜色。之前的pMask就是目标颜色。 //调用pFlower->visit()的时候,精灵pFlower上的对应像素的RGBA分量和pMask上的对应像素的A分量相乘.因为前面设置了GL_DST_ALPHA。 pFlower->visit(); //停止渲染到画板 pRt->end(); return true; }
这个遮罩图片是个不规则的边缘的图片,其本事是个矩形。除了白色区域有像素外,其他区域没像素,是全透明的。以上图片中显浅蓝色的区域是我截取的时候故意这样做的 。实际上这一区域是全透明的。
再看被遮挡图片(源颜色)
采用GL_DST_ALPHA把遮挡图片对应像素的RGBA分量和 被遮挡图片的A分量相乘.这样的话,遮挡图片中透明的区域在被遮挡图片上对应的区域就全透明了。
效果如下图:
黑色的区域是layer的背景.
话中貌似用CCRenderTexture的方式效率很低下,但是本人也没深究过。在网上看了一篇效率高的方式来实现遮罩效果的文章。