【转】http://code.lovemiao.com/?p=136#more-136

之前写过一篇《不规则形状按钮的点击判定》,利用了CCRenderTexture创建一块画布,可以在上面随意作画,这次,美术同学又本着把程序员折腾到底的态度,提出了又一奇葩需求,由于原需求设计商业机密,这里仅举个同理的例子说明。

附带福利图一张:

神马?没看够?还想看看其他人?请看耐心完全文

要做到上面的效果,glBlendFunc是个很好的选择。glBlendFunc是一个设置图像叠加方式的函数,就是把一张图绘制在画布上的时候,用指定的混色模式,使被绘制的图和原画布上的图进行混色运算,来实现各种混色效果。关于glBlendFunc的使用方法网上有很多教程,具体计算原理这里不再赘述,可参见微软的文档(官网文档排版实在蛋疼):http://msdn.microsoft.com/en-us/library/ms537046,下面介绍下上述效果的实现过程。

 

1.分层绘制

一共有三层图素,原美女图在最底层,第二层是黑色遮罩层,第三层是灯光层。

如上图,遮罩层是一张略带一点透明的黑色图素,灯光层是只用alpha值标记的黑色灯光形区域(请原谅我是用鼠标画的),要想把美女从黑色遮罩层底下露出来,就要把黑色遮罩层“抠个洞”,然后把“带洞的”遮罩层盖在原图上。

CCRenderTexture再次派上用场,当做一块临时画布,先把黑色遮罩层画在画布上,然后用灯光层进行混色运算,得到“带洞的”遮罩层。

2.选择合适的blendFunc

blendFunc是设置到灯光层上的,如果把灯光层中alpha大于0的像素称为标记像素,则期望的结果是alpha值越大的地方,混色运算后的alpha值越小,黑色遮罩层上相应的地方透明度越大,alpha值为0的像素点,不影响黑色遮罩层。

这里的黑色遮罩层(实际上已经画在renderTexture上了)就是Destination Color,灯光层就是Source Color,由于灯光层仅起到标记区域的作用,只有alpha值有效,且不应该影响最终结果的RGB值,所以srcFactor选择GL_ZERO,黑色遮罩层作为Destination Color,也是RGB图素的提供者,需要把灯光层标记的位置“抠掉”,所以dstFactor选择GL_ONE_MINUES_SRC_ALPHA。

现在就可以利用CCRenderTexture和glBlendFunc实现舞台灯光效果了。关键代码如下:

void BlendFunc::updateTexture()
{
renderTexture->beginWithClear(0, 0, 0, 0);
sprFore->visit();
sprMask->visit();
renderTexture->end();
} void BlendFunc::initSprites()
{
// 初始化所有图素
sprBg = new CCSprite();
sprBg->initWithFile("Images/back2.png");
sprFore = new CCSprite();
sprFore->initWithFile("Images/fore2.png");
sprMask = new CCSprite();
sprMask->initWithFile("Images/mask3.png"); // 初始化CCRenderTexture
const CCSize &size = sprBg->getContentSize();
renderTexture = new CCRenderTexture();
renderTexture->initWithWidthAndHeight(size.width, size.height, kCCTexture2DPixelFormat_RGBA8888);
renderTexture->setContentSize(size); // CCRenderTexture的contentSize需要手工设置,否则会影响坐标转换结果 CCPoint pos = ccp(250, 150); // 仅作为示例,这里随意设置了一个位置
renderTexture->setPosition(pos);
sprBg->setPosition(pos);
sprFore->ignoreAnchorPointForPosition(true); // CCSprite默认锚点在图素中心点,CCRenderTexture原点在坐下点,在此需要忽略锚点对CCSprite的影响 renderTexture->addChild(sprMask);
addChild(sprBg);
addChild(renderTexture); ccBlendFunc blendFunc;
blendFunc.src = GL_ZERO;
blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
sprMask->setBlendFunc(blendFunc);
updateTexture();
}

把sprBg和renderTexture加到父节点中,通过主循环递归地调用visit函数,可以直接被绘制出来,但把sprMask加到renderTexture中,并不会绘制sprMask,除非把renderTexture的autoDraw打开,不过目前最新的Cocosd-X 2.2.1版本还不建议这么做,所以需要靠updateTexture函数来修改renderTexture中的内容,不然renderTexture中始终是一块空白画布。之所以仍然要把sprMask加入到renderTexture中是因为,这样可以让sprMask的onEnter和onExit函数被调用,以保证sprMask生命周期的完整性。

现在可以通过修改sprMask的位置,照亮任意一位MM了。由于sprMask只有在修改位置的时候才需要重绘,renderTexture大部分时间都在绘制已经画好的texture,这和绘制一张普通的图片是一样的性能开销。

灯光效果介绍完了,可惜只有一盏灯,如果在updateTexture的时候,保留原画布的内容,在此基础上在不同位置上再画以此sprMask,这样在画布上就有两盏灯的效果了,以此类推,可以有多盏灯的效果。

 

void BlendFunc::updateTexture()
{
renderTexture->begin();
sprMovableMask->visit();
renderTexture->end();
} void BlendFunc::initSprites()
{
// 代码同上
...
...
... ccBlendFunc blendFunc;
blendFunc.src = GL_ZERO;
blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
sprMovableMask->setBlendFunc(blendFunc); renderTexture->beginWithClear(0, 0, 0, 0);
sprFore->visit();
renderTexture->end(); sprMovableMask->onMoving = [this]{
updateTexture();
};
}

如果把灯光遮罩换成一块橡皮遮罩呢?让橡皮遮罩可以跟随手指一起移动,一张刮刮卡诞生。

用BlendFunc实现舞台灯光和刮刮卡效果的更多相关文章

  1. qt qml 刮刮卡效果

    用canvas+mouseArea实现的刮刮卡效果. 表层是一层色彩,用手指划开,可看到下面的文字Lisence: MIT, 请保留本文档说明Author: surfsky.cnblogs.com 2 ...

  2. 网页闯关游戏(riddle webgame)--H5刮刮卡的原理和实践

    前言: 之前编写了一个网页闯关游戏(类似Riddle Game), 除了希望大家能够体验一下我的游戏外. 也愿意分享编写这个网页游戏过程中, 学到的一些知识. 对于刮刮卡, 想必大家都很熟悉, 也很喜 ...

  3. php中奖概率算法,可用于刮刮卡,大转盘等抽奖算法

    php中奖概率算法,可用于刮刮卡,大转盘等抽奖算法.用法很简单,代码里有详细注释说明,一看就懂 <?php /* * 经典的概率算法, * $proArr是一个预先设置的数组, * 假设数组为: ...

  4. Html5实现移动端、PC端 刮刮卡效果

    刚从南方回来就分了一个刮刮卡效果的页面,特么的我在烦恼怎么用H5去实现这个效果呢,好不容易写出来了,产品居然说:“既然你可以写出来这个效果那当然好了,开始我只是打算让你实现点击就出现呢!”… … 尼玛 ...

  5. 用c#开发微信 (16) 微活动 2 刮刮卡

    微信营销是一种新型的营销模式,由于微信更重视用户之间的互动,故而这种营销推广不不能盲目地套用微博营销的单纯大量广告推送方式.这种方式在微信营销中的效果非常差,会令用户反感,继而取消去企业或商家的微信公 ...

  6. Atitit .html5刮刮卡的gui实现总结

    Atitit .html5刮刮卡的gui实现总结 #----两个案例canvas或者wScratchPad-1.4.4 1 #----1.添加panel  ,这个十mask div.....posti ...

  7. paip.刮刮卡砸金蛋抽奖概率算法跟核心流程.

    paip.刮刮卡砸金蛋抽奖概率算法跟核心流程. #---抽奖算法需要满足的需求如下: 1 #---抽奖核心流程 1 #---问题???更好的算法 2 #---实际使用的扩展抽奖算法(带奖品送完判断和每 ...

  8. 使用HTML5实现刮刮卡效果

    你玩过刮刮卡么?一不小心可以中奖的那种.今天我给大家分享一个基于HTML5技术实现的刮刮卡效果,在PC上只需按住鼠标,在手机上你只需按住指头,轻轻刮去图层就可以模拟真实的刮奖效果. 我们利用HTML5 ...

  9. Android 自定义View修炼-【2014年最后的分享啦】Android实现自定义刮刮卡效果View

    一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文& ...

随机推荐

  1. Pylot压力测试(linux)

    Pylot需要python2.5以上的版本,打开以后选择对应你的系统的版本,下载好之后双击安装. centOS5.5 系统版本python版本是2.4.3,所以要下载个2.5以上的. 1.下载Pyth ...

  2. H5版俄罗斯方块(4)---火拼对战的雏形

    前言: 勿忘初心, 本系列的目标是实现一款类似QQ"火拼系列"的人机对战版俄罗斯方块. 在完成了基本游戏框架和AI的算法探索后, 让我们来尝试一下人机大战雏形编写. 本系列的文章链 ...

  3. Neo4j Cypher运行示例

    示例来源: Neo4j in Action. 0 准备数据 0.1 node (user1 { name: 'John Johnson', type: 'User', email: 'jsmith@e ...

  4. bll编译错误

    如果在项目中 ,bll有函数,却引用报错 原因很可能是因为bll在生成程序集的时候,没有生成好.其中有错误 解决办法. 1.将bll,web,dal重新生成 2.注意bll的生成,该添加的添加,该排除 ...

  5. C#可扩展编程之MEF学习

    MEF系列文章: C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import) C#可扩展编程之MEF学习 ...

  6. 设计模式-UML类图的各符号含义(转)

    UML类图的各符号含义 类图基本符号可拆分为虚线,箭头,实线,空心右三角,实心右三角,空心菱形和实心菱形.由这些基本的图形进行组合构成了类图的基本符号.这里要注意这几个符号的顺序,代表了类与类之间关系 ...

  7. SSH 创建证书认证

    *******chmod 600 195-tempuser.txt******* useradd tempusersu tempusercdmkdir .sshchmod 700 .sshcd .ss ...

  8. jquery选择器之属性选择器

    [attribute]   匹配指定属性名的所有元素 [attribute=value] 匹配给定的属性名是某个特定值的属性 [attribute!=value] 匹配给定的属性名不是某个特定值的属性 ...

  9. Excel中如何提取字符串中的数字

    取字符串中的数字,假如数据在A列,提取公式为 =LOOKUP(9^9,--MID(A1,MIN(FIND({1,2,3,4,5,6,7,8,9,0},A1&5^19)),ROW($1:$99) ...

  10. ruby 查询mysql方法

    首先对需要使用的数据库进行封装,便于使用:数据库表封装源码: mysqlapi.rb #业务涉及的数据库的配置ActiveRecord::Base$db1={:adapter => " ...