Cocos2d-js 实现弹窗背景虚化效果
来源:互联网 发布:网络连接受限制怎么办 编辑:程序博客网 时间:2024/05/21 09:52
要实现游戏中对话框的背景不是单调地叠一层半透明黑色,而是能有模糊的虚化效果。像是这个网页中第一个按钮按下去的样子。
显然,如果在要手游中实现这个效果,需要借助 OpenGL ES 2.0 Shader 来完成。
一个理想的方案是对当前场景设置一个 Shader 并在 Shader 中实现模糊效果,使得整个场景虚化。但是对话框也需要置于场景中,这会导致连对话框也虚化掉。
RenderTexture/FrameBuffer
不过好在现实也没有那么理想,在 Cocos2d 中直接对场景(CCScene)设置 Shader 是不起作用的。
一个变通的方法是将场景先绘制到缓冲区,然后再对缓冲区进行模糊。可以使用cc.director.getRunningScene().visit(); 完成这一操作:
var bgTex = cc.RenderTexture.create(cc.visibleRect.width, cc.visibleRect.height);
bgTex.begin();
cc.director.getRunningScene().visit();
bgTex.end();
此时整个场景的‘截图’保存在了 bgTex 中。接下来只要对此截图进行模糊处理即可。
Software Blur
查阅了一些资料后,找到了一些备选的软模糊算法。
- Box Blur: 简单高速的模糊方法,但效果不理想,正如它的名字,是有棱角的;
- StackBox Blur: Box Blur 的升级版,效果更好一些,而且速度是 Gaussian Blur 的 7 倍;
- Gaussian Blur: 著名的高斯模糊,效果很棒,但是算法效率比较低。
乍一看似乎 StackBox Blur 是较好的选择,但是从它源码上来看,它是最不容易实现的。所以我暂不考虑它了。我尝试了的 Box Blur 和 Gaussian Blur。
Box Blur 的效果过于生硬,而 Gaussian Blur 的效果好很多。
这里有一个简单的高斯模糊 Fragment Shader 的实现,不过只有9阶,在大半径的时候效果不够赞。所以我将其修改为15阶:
//apply blurring, using a 15-tap filter with predefined gaussian weights
sum += texture2D(CC_Texture0, vec2(tc.x - 7.0*blur*hstep, tc.y - 7.0*blur*vstep)) * 0.0044299121055113265;
sum += texture2D(CC_Texture0, vec2(tc.x - 6.0*blur*hstep, tc.y - 6.0*blur*vstep)) * 0.00895781211794;
sum += texture2D(CC_Texture0, vec2(tc.x - 5.0*blur*hstep, tc.y - 5.0*blur*vstep)) * 0.0215963866053;
sum += texture2D(CC_Texture0, vec2(tc.x - 4.0*blur*hstep, tc.y - 4.0*blur*vstep)) * 0.0443683338718;
sum += texture2D(CC_Texture0, vec2(tc.x - 3.0*blur*hstep, tc.y - 3.0*blur*vstep)) * 0.0776744219933;
sum += texture2D(CC_Texture0, vec2(tc.x - 2.0*blur*hstep, tc.y - 2.0*blur*vstep)) * 0.115876621105;
sum += texture2D(CC_Texture0, vec2(tc.x - 1.0*blur*hstep, tc.y - 1.0*blur*vstep)) * 0.147308056121;
sum += texture2D(CC_Texture0, vec2(tc.x, tc.y)) * 0.159576912161;
sum += texture2D(CC_Texture0, vec2(tc.x + 1.0*blur*hstep, tc.y + 1.0*blur*vstep)) * 0.147308056121;
sum += texture2D(CC_Texture0, vec2(tc.x + 2.0*blur*hstep, tc.y + 2.0*blur*vstep)) * 0.115876621105;
sum += texture2D(CC_Texture0, vec2(tc.x + 3.0*blur*hstep, tc.y + 3.0*blur*vstep)) * 0.0776744219933;
sum += texture2D(CC_Texture0, vec2(tc.x + 4.0*blur*hstep, tc.y + 4.0*blur*vstep)) * 0.0443683338718;
sum += texture2D(CC_Texture0, vec2(tc.x + 5.0*blur*hstep, tc.y + 5.0*blur*vstep)) * 0.0215963866053;
sum += texture2D(CC_Texture0, vec2(tc.x + 6.0*blur*hstep, tc.y + 6.0*blur*vstep)) * 0.00895781211794;
sum += texture2D(CC_Texture0, vec2(tc.x + 7.0*blur*hstep, tc.y + 7.0*blur*vstep)) * 0.0044299121055113265;
这是一组预算好的权重,节省计算量,这样就能省时省力达到满意的效果了。
需要注意的是,高斯模糊算法需要两次作用于图像。第一次对原图进行水平模糊,第二次对水平模糊后的图像进行垂直模糊。所以前面提到的缓冲区截图是非常必要的。
LayerBlur
由于绘制整个场景的过程是耗时的,且该效果只是用于对话框背景,所以缓冲区中的图像并不需要实时更新,创建后直接当作静态背景纹理使用即可。
为了便于使用,我将其封装为一个 Layer:
var modalBg = LayerBlur.create(LayerBlur.defaultBlurRadius, cc.color(0, 0, 0, 255 * 0.6));
this
.addChild(modalBg);
<img src=
"/uploads/20140617105632_18700.png"
alt=
""
style=
"cursor: pointer;"
>
本文例子在此开发环境中创建并测试通过:cocos2d-html5 3.0 alpha 2
源码已上传至 GistUPDATED 20140528: 在 iOS 模拟器中测试没有通过:
-x 中须使用独立 shader,且需要使用两次 bgTex 缓冲区;
-x 在 visit() 渲染包含 ccui 的组件时,会产生奇怪的 bug 导致场景被色块覆盖。
- Cocos2d-js 实现弹窗背景虚化效果
- cocos2d - JS 实现翻页效果
- Cocos2d-X 背景层循环运动效果的具体实现
- Cocos2d-js中实现惯性滑动效果
- Agar 流体效果的 Cocos2d-JS 实现
- Cocos2d-js中实现惯性滑动效果
- cocos2d-JS 实现 横竖屏提示效果
- JS背景分裂效果
- 半透明背景Activity实现AlertDialog弹窗效果
- android 中毛玻璃效果(背景虚化)的实现
- android 中毛玻璃效果(背景虚化)的实现
- android--毛玻璃效果(背景虚化)的实现
- android 中毛玻璃效果(背景虚化)的实现
- JS实现背景透明度可变,文字不透明的效果
- Cocos2d-JS 粒子效果
- cocos2d-JS 实现 横 竖 屏 显示提示图片效果 !!!!!
- cocos2d-x 多层背景滚动效果
- 【Cocos2d-x】新手自学(九)滚动背景..实现无限卷轴效果(2.0.1版本)
- 项目管理随想
- 关闭iptables
- 对BST的测试用例(使用junit4)
- LeetCode | Word Break II
- Shell 脚本小试牛刀(5) -- 超便捷脚本之快速ssh 登录其他主机
- Cocos2d-js 实现弹窗背景虚化效果
- 7月2日倒霉
- poj 3709: 2进制转化为3进制
- air升级程序利用7za.exe curl.exe后台升级
- Factory Method - 工厂方法模式
- ci框架---调用非php文件作视图
- rails 数据验证
- java语言-下雪花的简单小程序
- SQL语句异常导致项目报错