cocos2d-x 精灵遮罩

在网上看到一些对精灵遮罩的文章,但是都写的不够详细。以下是精灵遮罩的原理和实现。

 

首先得理解一些东西。

1.理解颜色混合。精灵有个成员函数: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为源颜色。

 

2.做精灵的遮罩效果为什么要用CCRenderTexture这个类。

你可能会觉得我们只需要先把mask(遮罩)精灵渲染上去,然后再渲染被遮罩的精灵,并且指定这两个精灵的blendFunc就行了。可是,实际上这样是行不通的!

因为被渲染上去的mask精灵下面如果还有其他的精灵。这样的话被渲染到mask精灵之上的精灵在做颜色混合的时候会出现意想不到的结果。达不到我们做遮罩的效果。

这样的话,我们需要一个比较干净的画板,这个干净的画板只有两个精灵在做颜色混合。这样的话这两个精灵在做颜色混合的时候就能达到我们想要的结果。不会受到不干净的背景造成的混合误差。这个背景就是CCRenderTexture.

 

当然如果我们的layer上只有精灵做混合的话就用不着CCRenderTexture了。但是实际项目中基本上是不能的。

 

OK。看看我们的Code.

 

[cpp]  view plain copy
  1. CCSize size = CCDirector::sharedDirector()->getWinSize();  
  2.    //创建干净的画板  
  3. CCRenderTexture *pRt = CCRenderTexture::create(size.width,size.height);  
  4.     CCAssert(pRt, "RenderTexture is invalid");  
  5.     addChild(pRt);  
  6.     pRt->setPosition(size.width/2,size.height/2);  
  7. //创建遮罩图片  
  8. CCSprite *pMask = CCSprite::create("CalendarMask.png");  
  9. CCAssert(pMask,"mask sprite is invalid");  
  10. pMask->setPosition(CCPointMake(pMask->getContentSize().width/2, pMask->getContentSize().height/2));  
  11. //创建被遮罩图片  
  12. CCSprite *pFlower = CCSprite::create("Calendar1.png");  
  13. CCAssert(pFlower, "Flower sprite is invalid");  
  14. pFlower->setPosition(CCPointMake(pFlower->getContentSize().width/2, pFlower->getContentSize().height/2));  
  15.      
  16. //先设置好 遮罩精灵 和 被遮罩精灵 在被渲染的时候采用什么样的颜色混合法则  
  17. ccBlendFunc maskBlend = {GL_ONE, GL_ZERO};  
  18. ccBlendFunc flowerBlend = {GL_DST_ALPHA, GL_ZERO};  
  19.    pMask->setBlendFunc(maskBlend);  
  20.    pFlower->setBlendFunc(flowerBlend);  
  21.   
  22. //开始把各种精灵渲染到画板上  
  23. pRt->begin();  
  24. //先渲染遮罩精灵。但是因为有个画板先被渲染。所以pMask是第二个被渲染的,即后被渲染。  
  25. //所以在这一刻pMask是源颜色。调用pMask->visit()的时候吧精灵pMask上的每个像素的RGBA分量和1.0相乘。  
  26. //所以遮罩图片被元模原样的渲染出来.  
  27. pMask->visit();  
  28. //再渲染被遮罩的精灵.在这一刻,之前先有pMask被渲染。所以pFlower后被渲染。pFlower就是源颜色。之前的pMask就是目标颜色。  
  29.  //调用pFlower->visit()的时候,精灵pFlower上的对应像素的RGBA分量和pMask上的对应像素的A分量相乘.因为前面设置了GL_DST_ALPHA。  
  30. pFlower->visit();  
  31. //停止渲染到画板  
  32. pRt->end();  


上面看注释就懂了。

 

先看遮罩图片(PNG)目标颜色

这个遮罩图片是个不规则的边缘的图片,其本事是个矩形。除了白色区域有像素外,其他区域没像素,是全透明的。以上图片中显浅蓝色的区域是我截取的时候故意这样做的 。实际上这一区域是全透明的。

 

再看被遮挡图片(源颜色)

 

采用GL_DST_ALPHA把遮挡图片对应像素的RGBA分量和 被遮挡图片的A分量相乘.这样的话,遮挡图片中透明的区域在被遮挡图片上对应的区域就全透明了。

效果如下图。

黑色的区域是layer的背景.

 

话中貌似用CCRenderTexture的方式效率很低下,但是本人也没深究过。在网上看了一篇效率高的方式来实现遮罩效果的文章。

http://blog.csdn.net/lan354898254/article/details/7887587

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值