55 Commits
0.3.0 ... 0.8.0

Author SHA1 Message Date
caizhitao
c897d7f000 Merge branch 'release/0.8.0' 2020-02-07 15:18:03 +08:00
caizhitao
261f390687 update README.md and CHANGELOG.md 2020-02-07 15:17:57 +08:00
caizhitao
d967209a71 支持 Cocos Creator 2.2.2 2020-02-07 15:14:26 +08:00
caizhitao
72f9037fea 更新预览场景 2020-02-07 15:13:54 +08:00
caizhitao
7cd2edc0df Merge branch 'release/0.7.0' into dev 2020-02-07 10:12:38 +08:00
caizhitao
286fa64ba0 Merge branch 'release/0.7.0' 2020-02-07 10:12:31 +08:00
caizhitao
500d0a1614 update README.md 2020-02-07 10:12:11 +08:00
caizhitao
f2d62a70cb 更新注释 2020-02-07 09:46:33 +08:00
caizhitao
20f72cfd27 更新版本说明 2020-02-07 09:36:18 +08:00
caizhitao
cbdbc85ef3 Merge branch 'feature/gaussian_blur' into dev 2020-02-07 09:30:33 +08:00
caizhitao
b5390ea84f 整理高斯模糊代码 2020-02-07 09:30:12 +08:00
caizhitao
02d94a943d 优化权重和计算方式 2020-01-21 18:48:13 +08:00
caizhitao
f9198a3b14 完善效果 2020-01-21 16:15:35 +08:00
caizhitao
75d4d024bf 完善demo 2020-01-21 15:56:32 +08:00
caizhitao
1c5012ab65 初步实现模糊 2020-01-20 22:42:59 +08:00
caizhitao
c65106941e Merge branch 'dev' into feature/gaussian_blur 2020-01-20 22:05:50 +08:00
caizhitao
c2693616d0 update README.md 2020-01-17 09:47:05 +08:00
caizhitao
b1196e3808 Merge branch 'release/0.6.0' into dev 2020-01-17 09:38:54 +08:00
caizhitao
9865eedc34 Merge branch 'release/0.6.0' 2020-01-17 09:38:47 +08:00
caizhitao
f109455742 update README and CHANGELOG 2020-01-17 09:38:41 +08:00
caizhitao
95a7a51357 Merge branch 'feature/opt_round_corner_crop' into dev 2020-01-17 00:11:35 +08:00
caizhitao
4ed91e0a3e 更新动图 2020-01-17 00:11:21 +08:00
caizhitao
f3c0ad079a 加入抗锯齿实现 2020-01-17 00:07:35 +08:00
caizhitao
f1256c5185 bugfix 2020-01-16 23:33:46 +08:00
caizhitao
f58540ead2 完善demo 2020-01-16 23:27:14 +08:00
caizhitao
bfe61e6494 完善圆角裁剪demo 2020-01-16 23:08:59 +08:00
caizhitao
c64f1ab144 加入v2版本圆角裁剪 2020-01-16 22:59:41 +08:00
caizhitao
c047efb715 初始化高斯模糊场景相关 2020-01-16 21:41:59 +08:00
caizhitao
deebc64aa2 更新圆角Effect的注释 2020-01-14 21:53:04 +08:00
caizhitao
af8aa46786 Merge branch 'dev' 2020-01-13 23:44:24 +08:00
caizhitao
4ca3fe34b0 修改代码 2020-01-13 23:44:17 +08:00
caizhitao
eff439ef20 更新点光/扫光文章 2020-01-13 23:44:00 +08:00
caizhitao
e257d1f8b9 Merge branch 'release/0.5.0' into dev 2020-01-13 22:40:37 +08:00
caizhitao
70a3b95f10 Merge branch 'release/0.5.0' 2020-01-13 22:40:32 +08:00
caizhitao
6402c68fbc 调整点光的部分代码 2020-01-13 22:40:10 +08:00
caizhitao
dccf05cfde update README.md and CHANGELOG.md 2020-01-13 22:36:43 +08:00
caizhitao
1ff0ee3d40 Merge branch 'feature/flash_light' into dev 2020-01-13 22:15:29 +08:00
caizhitao
209e22fcca 注释调整 2020-01-13 22:14:07 +08:00
caizhitao
e7e084b958 光束宽度边界值处理 2020-01-13 22:13:55 +08:00
caizhitao
acf72e0e4f 完善闪光效果 2020-01-13 17:43:46 +08:00
caizhitao
c95329e7ab 初始化闪光场景相关 2020-01-13 15:27:46 +08:00
caizhitao
9160ad38b7 Merge branch 'release/0.4.0' into dev 2020-01-12 09:16:34 +08:00
caizhitao
f6f93bad2c Merge branch 'release/0.4.0' 2020-01-12 09:16:29 +08:00
caizhitao
45e22b866a 加入点光特效果到预览场景 2020-01-12 09:15:49 +08:00
caizhitao
9ca7bd9a02 更新圆角裁剪动图,之前的太卡了 2020-01-12 09:13:06 +08:00
caizhitao
69b863c490 update README.md and CHANGELOG.md 2020-01-12 09:10:41 +08:00
caizhitao
6286aebb8c Merge branch 'feature/point_light' into dev 2020-01-12 09:03:23 +08:00
caizhitao
ae865a7c5f 更新效果名为点光 2020-01-12 09:01:30 +08:00
caizhitao
40e905fc81 添加延时demo 2020-01-12 08:56:55 +08:00
caizhitao
9f28ef4305 加入迷雾控制 2020-01-12 08:54:08 +08:00
caizhitao
ba90b2170c 优化demo 2020-01-12 00:36:08 +08:00
caizhitao
7e197c0892 优化demo 2020-01-11 18:58:30 +08:00
caizhitao
6ac69a841a 初步支持单点扩散 2020-01-10 23:05:49 +08:00
caizhitao
f39e39e248 准备局部扩散场景相关 2020-01-10 17:44:43 +08:00
caizhitao
27e819fb2c Merge branch 'release/0.3.0' into dev 2020-01-10 16:21:18 +08:00
56 changed files with 20169 additions and 98 deletions

View File

@@ -1,5 +1,25 @@
# ChangeLog
## 0.8.0 (2020-02-07)
- 支持 Cocos Creator v2.2.2
## 0.7.0 (2020-02-07)
- 加入高斯模糊V1版本纯原理篇
## 0.6.0 (2020-01-17)
- 加入新的圆角裁剪特效 v2 ,支持任意宽高纹理圆角裁剪
## 0.5.0 (2020-01-13)
- 加入扫光特效
## 0.4.0 (2020-01-12)
- 加入点光特效
## 0.3.0 (2020-01-09)
- 加入圆角裁剪特效

View File

@@ -1,16 +1,16 @@
# Cocos Creator Shader Effect Demo
[![](https://img.shields.io/badge/Release-0.3.0-green.svg)](CHANGELOG.md)
[![](https://img.shields.io/badge/Release-0.8.0-green.svg)](CHANGELOG.md)
[![](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![](https://img.shields.io/badge/Support-Cocos%20Creator%20v2.2.1-orange.svg)](http://www.cocos.com/creator)
## 项目说明
## 一、项目说明
1. 此项目为我在学习过程中的一些分享和实现,因此项目名字以 **`Demo`** 为后缀。
2. 项目重点在于 **「渔」**,不在于 **「鱼」** 。
3. 如果你有意将此Demo中的效果加入到你的项目中**请认真评估是否适合你的项目使用!**
## 系列文章
## 二、系列文章
* [Cocos Creator Shader Effect 系列 - 0 - 前言](https://www.jianshu.com/p/20b906d7269c)
* [Cocos Creator Shader Effect 系列 - 1 - 材质EffectInspector纹理之间的关系](https://www.jianshu.com/p/ca28666d25d2)
@@ -19,14 +19,18 @@
* [Cocos Creator Shader Effect 系列 - 4 - 老照片特效](https://www.jianshu.com/p/711a54ff2fa0)
* [Cocos Creator Shader Effect 系列 - 5 - 马赛克/像素化特效](https://www.jianshu.com/p/40e72ab76afd)
* [Cocos Creator Shader Effect 系列 - 6 - 内发光特效](https://www.jianshu.com/p/326b73f86ecc)
* [Cocos Creator Shader Effect 系列 - 7 - 点光/扫光特效](https://www.jianshu.com/p/8ff03b34b0bd)
* [Cocos Creator Shader Effect 系列 - 8 - 高斯模糊](https://www.jianshu.com/p/9e42cbb1d4a8)
* 编写中...
## 特效预览
那么现在,我们先来轻松地看下有哪些特效效果吧~
## 三、特效预览
### 内发光([实现原理](https://www.jianshu.com/p/326b73f86ecc)
![](static/effects/2d-sprite-glow-inner.gif)
@@ -43,29 +47,51 @@
![](static/effects/2d-sprite-gray.gif)
### 圆角裁剪
### 点光([实现原理](https://www.jianshu.com/p/8ff03b34b0bd)(2020.01.12更新)
![](static/effects/2d-sprite-point-light.gif)
### 扫光(实现原理同点光一样,可参考[点光实现原理文章](https://www.jianshu.com/p/711a54ff2fa0)(2020.01.13更新)
![](static/effects/2d-sprite-flash-light.gif)
### 圆角裁剪-v12020.01.17更新)
> * 声明:此特效为搬运过来的特效,非原创。
> * 修改的地方:搬运后,在原来的主要代码上加入了自己的理解注释
> * 实现原理:参考文章 [《圆角计算 Shader》](https://www.cnblogs.com/jqm304775992/p/4987793.html)
> * 参考代码Cocos 论坛帖子[《分享更高效的 creator 裁圆角头像 shader》](https://forum.cocos.org/t/creator-shader-2019-10-22-2-2-0/82548) 和对应的 [实现代码](https://github.com/yanjifa/shaderDemo/blob/master/assets/Effect/CircleAvatar.effect)
![](static/effects/2d-sprite-round-corner-crop.gif)
**此版本存在局限性:只有在正方形纹理上,才能裁剪出圆角,在非正方形上,无法裁剪出圆角,具体变现为有拉伸效果**
下面GIF中第3到5秒演示所示黄色和红色的非正方形纹理的圆角明显被拉伸
![](static/effects/2d-sprite-round-corner-crop-v1.gif)
### 圆角裁剪-v22020.01.17更新)
**圆角裁剪-v1** 的原理基础上,新增支持任意宽高纹理的圆角裁剪
下面Gif中第3到5秒演示所示黄色和红色的非正方形纹理也能裁剪出圆角效果
![](static/effects/2d-sprite-round-corner-crop-v2.gif)
### 高斯模糊-V1[实现原理](https://www.jianshu.com/p/9e42cbb1d4a8)2020.02.07更新)
![](static/effects/2d-sprite-gaussian-blur-v1.png)
### 外发光(完善中...
### 外描边(完善中...
## TODO
## 四、TODO
* [ ] 图像裁剪
* [ ] 图像模糊
* [ ] 闪光
* [ ] 波浪
* [ ] 雨滴
* [ ] ...
## 支持一下作者吧
## 五、支持一下作者吧
如果此项目对你学习和理解Shader有帮助不妨支持一下我吧~

View File

@@ -0,0 +1,235 @@
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
// 闪光(光速扫过)
// 原理(和点光的很类似):
// 1. 画光束
// 2. 圆心中间高亮(透明度=1.0),边缘不亮(透明度=0.0
// 3. 在原图像上方叠加光束
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
alphaThreshold: { value: 0.5 }
# 光束颜色
lightColor: {
value: [1.0, 1.0, 0.0, 1.0],
inspector: {
type: color,
tooltip: "光束颜色"
}
}
# 光束中心点坐标
lightCenterPoint: {
value: [0.2, 0.2],
inspector: {
tooltip: "光束中心点坐标"
}
}
# 光束倾斜角度
lightAngle: {
value: 36.0,
inspctor: {
tooltip: "光束倾斜角度",
range: [0.0, 1.0],
}
}
# 光束宽度
lightWidth: {
value: 0.2,
inspector: {
tooltip: "光束宽度"
}
}
# 启用光束渐变
enableGradient: {
value: 1.0,
inspecator: {
tooltip: "是否启用光束渐变。0不启用非0启用"
}
}
# 裁剪掉透明区域上的光
cropAlpha: {
value: 1.0,
inspecator: {
tooltip: "是否裁剪透明区域上的光。0不启用非0启用"
}
}
# 是否启用迷雾效果
enableFog: {
value: 0.0,
inspecator: {
tooltip: "是否启用迷雾效果。0不启用非0启用"
}
}
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
#include <cc-local>
in vec3 a_position;
in vec4 a_color;
out vec4 v_color;
#if USE_TEXTURE
in vec2 a_uv0;
out vec2 v_uv0;
#endif
void main () {
vec4 pos = vec4(a_position, 1);
#if CC_USE_MODEL
pos = cc_matViewProj * cc_matWorld * pos;
#else
pos = cc_matViewProj * pos;
#endif
#if USE_TEXTURE
v_uv0 = a_uv0;
#endif
v_color = a_color;
gl_Position = pos;
}
}%
CCProgram fs %{
precision highp float;
#include <alpha-test>
in vec4 v_color;
#if USE_TEXTURE
in vec2 v_uv0;
uniform sampler2D texture;
#endif
#if ENABLE_LIGHT
uniform Light {
// 光束颜色
vec4 lightColor;
// 光束中心点坐标
vec2 lightCenterPoint;
// 光束倾斜角度
float lightAngle;
// 光束宽度
float lightWidth;
// 启用光束渐变
// ps编辑器还不支持 bool 类型的样子因此用float来定义
float enableGradient;
// 裁剪掉透明区域上的光
// ps编辑器还不支持 bool 类型的样子因此用float来定义
float cropAlpha;
// 是否启用迷雾效果
// ps编辑器还不支持 bool 类型的样子因此用float来定义
float enableFog;
}
/**
* 添加光束颜色
*/
vec4 addLightColor(vec4 textureColor, vec4 lightColor, vec2 lightCenterPoint, float lightAngle, float lightWidth) {
// 边界值处理,没有宽度就返回原始颜色
if (lightWidth <= 0.0) {
return textureColor;
}
// 计算当前 uv 到 光束 的距离
float angleInRadians = radians(lightAngle);
// 角度0与非0不同处理
float dis = 0.0;
if (mod(lightAngle, 180.0) != 0.0) {
// 计算光束中心线下方与X轴交点的X坐标
// 1.0 - lightCenterPoint.y 是将转换为OpenGL坐标系下文的 1.0 - y 类似
float lightOffsetX = lightCenterPoint.x - ((1.0 - lightCenterPoint.y) / tan(angleInRadians));
// 以当前点画一条平行于X轴的线假设此线和光束中心线相交的点为D点
// 那么
// D.y = uv0.y
// D.x = lightOffsetX + D.y / tan(angle)
float dx = lightOffsetX + (1.0 - v_uv0.y) / tan(angleInRadians);
// D 到当前 uv0 的距离就是
// dis = |uv0.x - D.x|
float offsetDis = abs(v_uv0.x - dx);
// 当前点到光束中心线的的垂直距离就好算了
dis = sin(angleInRadians) * offsetDis;
} else {
dis = abs(v_uv0.y - lightCenterPoint.y);
}
float a = 1.0 ;
// 裁剪掉透明区域上的点光
if (bool(cropAlpha)) {
a *= step(0.01, textureColor.a);
}
// 裁剪掉光束范围外的uv迷雾效果
if (!bool(enableFog)) {
a *= step(dis, lightWidth * 0.5);
}
// 加入从中心往外渐变的效果
if (bool(enableGradient)) {
a *= 1.0 - dis / (lightWidth * 0.5);
}
// 计算出扩散范围内,不同 uv 对应的实际扩散颜色值
vec4 finalLightColor = lightColor * a;
// 混合颜色:在原始图像颜色上叠加扩散颜色
return textureColor * textureColor.a + finalLightColor;
}
#endif
void main () {
vec4 o = vec4(1, 1, 1, 1);
#if USE_TEXTURE
o *= texture(texture, v_uv0);
#if CC_USE_ALPHA_ATLAS_TEXTURE
o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;
#endif
#endif
o *= v_color;
ALPHA_TEST(o);
gl_FragColor = o;
#if ENABLE_LIGHT
gl_FragColor = addLightColor(gl_FragColor, lightColor, lightCenterPoint, lightAngle, lightWidth);
#endif
}
}%

View File

@@ -0,0 +1,17 @@
{
"ver": "1.0.23",
"uuid": "e9682cd1-a19c-4fcb-ad8c-cf1783b805e6",
"compiledShaders": [
{
"glsl1": {
"vert": "\nprecision highp float;\nuniform mat4 cc_matViewProj;\nuniform mat4 cc_matWorld;\n\nattribute vec3 a_position;\nattribute vec4 a_color;\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nattribute vec2 a_uv0;\nvarying vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform float alphaThreshold;\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nvarying vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_LIGHT\nuniform vec4 lightColor;\nuniform vec2 lightCenterPoint;\nuniform float lightAngle;\nuniform float lightWidth;\nuniform float enableGradient;\nuniform float cropAlpha;\nuniform float enableFog;\n/**\n * 添加光束颜色\n */\nvec4 addLightColor(vec4 textureColor, vec4 lightColor, vec2 lightCenterPoint, float lightAngle, float lightWidth) {\n\n if (lightWidth <= 0.0) {\n return textureColor;\n }\n\n float angleInRadians = radians(lightAngle);\n\n float dis = 0.0;\n if (mod(lightAngle, 180.0) != 0.0) {\n\n float lightOffsetX = lightCenterPoint.x - ((1.0 - lightCenterPoint.y) / tan(angleInRadians));\n\n float dx = lightOffsetX + (1.0 - v_uv0.y) / tan(angleInRadians);\n\n float offsetDis = abs(v_uv0.x - dx);\n\n dis = sin(angleInRadians) * offsetDis;\n } else {\n dis = abs(v_uv0.y - lightCenterPoint.y);\n }\n \n float a = 1.0 ;\n\n if (bool(cropAlpha)) {\n a *= step(0.01, textureColor.a);\n }\n\n if (!bool(enableFog)) {\n a *= step(dis, lightWidth * 0.5);\n }\n\n if (bool(enableGradient)) {\n a *= 1.0 - dis / (lightWidth * 0.5);\n }\n\n vec4 finalLightColor = lightColor * a;\n\n return textureColor * textureColor.a + finalLightColor;\n}\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n gl_FragColor = o;\n \n #if ENABLE_LIGHT\n gl_FragColor = addLightColor(gl_FragColor, lightColor, lightCenterPoint, lightAngle, lightWidth);\n #endif\n}\n"
},
"glsl3": {
"vert": "\nprecision highp float;\nuniform CCGlobal {\n vec4 cc_time;\n\n vec4 cc_screenSize;\n\n vec4 cc_screenScale;\n\n vec4 cc_nativeSize;\n\n mat4 cc_matView;\n mat4 cc_matViewInv;\n mat4 cc_matProj;\n mat4 cc_matProjInv;\n mat4 cc_matViewProj;\n mat4 cc_matViewProjInv;\n vec4 cc_cameraPos;\n\n vec4 cc_exposure;\n\n vec4 cc_mainLitDir;\n\n vec4 cc_mainLitColor;\n\n vec4 cc_ambientSky;\n vec4 cc_ambientGround;\n};\nuniform CCLocal {\n mat4 cc_matWorld;\n mat4 cc_matWorldIT;\n};\n\nin vec3 a_position;\nin vec4 a_color;\nout vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 a_uv0;\nout vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform ALPHA_TEST {\n float alphaThreshold;\n }\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nin vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_LIGHT\nuniform Light {\n\n vec4 lightColor;\n\n vec2 lightCenterPoint;\n\n float lightAngle;\n\n float lightWidth;\n\n float enableGradient;\n\n float cropAlpha;\n\n float enableFog;\n}\n\n/**\n * 添加光束颜色\n */\nvec4 addLightColor(vec4 textureColor, vec4 lightColor, vec2 lightCenterPoint, float lightAngle, float lightWidth) {\n\n if (lightWidth <= 0.0) {\n return textureColor;\n }\n\n float angleInRadians = radians(lightAngle);\n\n float dis = 0.0;\n if (mod(lightAngle, 180.0) != 0.0) {\n\n float lightOffsetX = lightCenterPoint.x - ((1.0 - lightCenterPoint.y) / tan(angleInRadians));\n\n float dx = lightOffsetX + (1.0 - v_uv0.y) / tan(angleInRadians);\n\n float offsetDis = abs(v_uv0.x - dx);\n\n dis = sin(angleInRadians) * offsetDis;\n } else {\n dis = abs(v_uv0.y - lightCenterPoint.y);\n }\n \n float a = 1.0 ;\n\n if (bool(cropAlpha)) {\n a *= step(0.01, textureColor.a);\n }\n\n if (!bool(enableFog)) {\n a *= step(dis, lightWidth * 0.5);\n }\n\n if (bool(enableGradient)) {\n a *= 1.0 - dis / (lightWidth * 0.5);\n }\n\n vec4 finalLightColor = lightColor * a;\n\n return textureColor * textureColor.a + finalLightColor;\n}\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n gl_FragColor = o;\n \n #if ENABLE_LIGHT\n gl_FragColor = addLightColor(gl_FragColor, lightColor, lightCenterPoint, lightAngle, lightWidth);\n #endif\n}\n"
}
}
],
"subMetas": {}
}

View File

@@ -0,0 +1,196 @@
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
// 高斯模糊
//
// 参考资料(必读)
// * http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html
// * https://zh.wikipedia.org/wiki/%E9%AB%98%E6%96%AF%E6%A8%A1%E7%B3%8A
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
alphaThreshold: { value: 0.5 }
# # 标准方差值
# stDev: {
# value: 0.84089642,
# inspector: {
# tooltip: "标准方差值"
# }
# }
# 纹理尺寸
textureSize: {
value: [100.0, 100.0],
inspector: {
tooltip: "纹理尺寸px宽 x 高)"
}
}
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
#include <cc-local>
in vec3 a_position;
in vec4 a_color;
out vec4 v_color;
#if USE_TEXTURE
in vec2 a_uv0;
out vec2 v_uv0;
#endif
void main () {
vec4 pos = vec4(a_position, 1);
#if CC_USE_MODEL
pos = cc_matViewProj * cc_matWorld * pos;
#else
pos = cc_matViewProj * pos;
#endif
#if USE_TEXTURE
v_uv0 = a_uv0;
#endif
v_color = a_color;
gl_Position = pos;
}
}%
CCProgram fs %{
precision highp float;
#include <alpha-test>
in vec4 v_color;
#if USE_TEXTURE
in vec2 v_uv0;
uniform sampler2D texture;
#endif
#if ENABLE_GAUSSIAN_BLUR
// 定义无理数
#define e 2.718281828459045
// 定义标准方差值(方差值越大,越模糊,但是需要计算的高斯矩阵范围会变大,从而带来巨大的计算量)
// #define stDev 0.84089642
#define stDev 1.5
// #define stDev 5.0
// #define stDev 10.0
// 定义π
#define pi 3.141592653589793
// 接收外部变量
uniform GaussianBlur {
// 纹理尺寸(宽 x 高px
vec2 textureSize;
// // 标准方差值
// float stDev;
}
/**
* 获取权重(对应二维高斯函数公式,见 https://zh.wikipedia.org/wiki/%E9%AB%98%E6%96%AF%E6%A8%A1%E7%B3%8A )
*/
float getWeight(float x, float y) {
return (1.0 / (2.0 * pi * pow(stDev, 2.0))) * pow(1.0 / e, (pow(x, 2.0) + pow(y, 2.0)) / (2.0 * pow(stDev, 2.0)));
}
#endif
void main () {
vec4 o = vec4(1, 1, 1, 1);
#if USE_TEXTURE
o *= texture(texture, v_uv0);
#if CC_USE_ALPHA_ATLAS_TEXTURE
o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;
#endif
#endif
o *= v_color;
ALPHA_TEST(o);
gl_FragColor = o;
#if ENABLE_GAUSSIAN_BLUR
// 根据高斯分布也叫正态分布在3个标准差范围内的分布比例占到99%的权重,因此我们只需要计算矩阵范围 [6 * stDev + 1, 6 * stDev +1] 上的权重
const float size = floor(stDev * 6.0 + 1.0);
const float halfSize = floor(size / 2.0);
// 步骤一:计算高斯矩阵上所有权重的和
// // v1遍历所有点每个点都计算权重
// float totalWeight = 0.0;
// for(float x = -halfSize; x<= halfSize; x++) {
// for (float y = -halfSize; y<= halfSize; y++) {
// totalWeight += getWeight(x, y);
// }
// }
// v2因为高斯分布是对称的所以只计算原点、X轴正方向 * 2 、Y轴正方向 * 2 、第一象限的权重 * 4即可求出所有权重之和相比起v1版本减少很多循环计算
// 原点
float totalWeight = getWeight(0.0, 0.0);
// X轴正方向上的权重 * 2.0 就是整个X轴上的权重
for(float x = 1.0; x <= halfSize; x++) {
totalWeight += getWeight(x, 0.0) * 2.0;
}
// Y轴正方向上的权重 * 2.0 就是整个Y轴上的权重
for(float y = 1.0; y <= halfSize; y++) {
totalWeight += getWeight(0.0, y) * 2.0;
}
// 第一象限的权重 * 4.0 就是4个象限的权重
for(float x = 1.0; x <= halfSize; x++) {
for (float y = 1.0; y<= halfSize; y++) {
totalWeight += getWeight(x, y) * 4.0;
}
}
// TODO:
//
// 因为权重矩阵是一次性计算即可不断应用因此可以将权重矩阵的计算放到CPU计算并传入到Shader直接渲染因此有以下优化方案
//
// v3原始权重矩阵在CPU计算并传入到Shader
// v4加权平均后的权重矩阵在CPU计算并传入Shader
// 步骤二:采样周边像素并应用加权平均值,得出最终像素值
vec4 finalColor = vec4(0.0, 0.0, 0.0, 0.0);
// float divider = 0.01;
float onePxWidth = 1.0 / textureSize.x;
float onePxHeight = 1.0 / textureSize.y;
for(float x = -halfSize; x<= halfSize; x++) {
for (float y = -halfSize; y<= halfSize; y++) {
// 求出对应坐标的真正权重(对应权重矩阵)
float weight = getWeight(x, y) / totalWeight;
// 求出对应坐标像素颜色值的加权值
// finalColor += texture(texture, v_uv0 + vec2(divider * x, divider * y)) * weight;
finalColor += texture(texture, v_uv0 + vec2(onePxWidth * x, onePxHeight * y)) * weight;
}
}
gl_FragColor = finalColor;
#endif
}
}%

View File

@@ -0,0 +1,17 @@
{
"ver": "1.0.23",
"uuid": "41f4d474-d707-45bb-af93-637573f92d54",
"compiledShaders": [
{
"glsl1": {
"vert": "\nprecision highp float;\nuniform mat4 cc_matViewProj;\nuniform mat4 cc_matWorld;\n\nattribute vec3 a_position;\nattribute vec4 a_color;\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nattribute vec2 a_uv0;\nvarying vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform float alphaThreshold;\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nvarying vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_GAUSSIAN_BLUR\n\nuniform vec2 textureSize;\n/**\n * 获取权重(对应二维高斯函数公式,见 https:\n\n */\nfloat getWeight(float x, float y) {\n return (1.0 / (2.0 * 3.141592653589793 * pow(1.5, 2.0))) * pow(1.0 / 2.718281828459045, (pow(x, 2.0) + pow(y, 2.0)) / (2.0 * pow(1.5, 2.0)));\n}\n\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n gl_FragColor = o;\n #if ENABLE_GAUSSIAN_BLUR\n\n const float size = floor(1.5 * 6.0 + 1.0);\n const float halfSize = floor(size / 2.0);\n\n float totalWeight = getWeight(0.0, 0.0);\n\n for(float x = 1.0; x <= halfSize; x++) {\n totalWeight += getWeight(x, 0.0) * 2.0;\n }\n\n for(float y = 1.0; y <= halfSize; y++) {\n totalWeight += getWeight(0.0, y) * 2.0;\n }\n\n for(float x = 1.0; x <= halfSize; x++) {\n for (float y = 1.0; y<= halfSize; y++) {\n totalWeight += getWeight(x, y) * 4.0;\n }\n }\n\n vec4 finalColor = vec4(0.0, 0.0, 0.0, 0.0);\n\n float onePxWidth = 1.0 / textureSize.x;\n float onePxHeight = 1.0 / textureSize.y;\n for(float x = -halfSize; x<= halfSize; x++) {\n for (float y = -halfSize; y<= halfSize; y++) {\n\n float weight = getWeight(x, y) / totalWeight;\n\n finalColor += texture2D(texture, v_uv0 + vec2(onePxWidth * x, onePxHeight * y)) * weight;\n }\n }\n gl_FragColor = finalColor;\n #endif\n}\n"
},
"glsl3": {
"vert": "\nprecision highp float;\nuniform CCGlobal {\n vec4 cc_time;\n\n vec4 cc_screenSize;\n\n vec4 cc_screenScale;\n\n vec4 cc_nativeSize;\n\n mat4 cc_matView;\n mat4 cc_matViewInv;\n mat4 cc_matProj;\n mat4 cc_matProjInv;\n mat4 cc_matViewProj;\n mat4 cc_matViewProjInv;\n vec4 cc_cameraPos;\n\n vec4 cc_exposure;\n\n vec4 cc_mainLitDir;\n\n vec4 cc_mainLitColor;\n\n vec4 cc_ambientSky;\n vec4 cc_ambientGround;\n};\nuniform CCLocal {\n mat4 cc_matWorld;\n mat4 cc_matWorldIT;\n};\n\nin vec3 a_position;\nin vec4 a_color;\nout vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 a_uv0;\nout vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform ALPHA_TEST {\n float alphaThreshold;\n }\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nin vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_GAUSSIAN_BLUR\n\nuniform GaussianBlur {\n\n vec2 textureSize;\n\n}\n\n/**\n * 获取权重(对应二维高斯函数公式,见 https:\n\n */\nfloat getWeight(float x, float y) {\n return (1.0 / (2.0 * 3.141592653589793 * pow(1.5, 2.0))) * pow(1.0 / 2.718281828459045, (pow(x, 2.0) + pow(y, 2.0)) / (2.0 * pow(1.5, 2.0)));\n}\n\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n gl_FragColor = o;\n #if ENABLE_GAUSSIAN_BLUR\n\n const float size = floor(1.5 * 6.0 + 1.0);\n const float halfSize = floor(size / 2.0);\n\n float totalWeight = getWeight(0.0, 0.0);\n\n for(float x = 1.0; x <= halfSize; x++) {\n totalWeight += getWeight(x, 0.0) * 2.0;\n }\n\n for(float y = 1.0; y <= halfSize; y++) {\n totalWeight += getWeight(0.0, y) * 2.0;\n }\n\n for(float x = 1.0; x <= halfSize; x++) {\n for (float y = 1.0; y<= halfSize; y++) {\n totalWeight += getWeight(x, y) * 4.0;\n }\n }\n\n vec4 finalColor = vec4(0.0, 0.0, 0.0, 0.0);\n\n float onePxWidth = 1.0 / textureSize.x;\n float onePxHeight = 1.0 / textureSize.y;\n for(float x = -halfSize; x<= halfSize; x++) {\n for (float y = -halfSize; y<= halfSize; y++) {\n\n float weight = getWeight(x, y) / totalWeight;\n\n finalColor += texture(texture, v_uv0 + vec2(onePxWidth * x, onePxHeight * y)) * weight;\n }\n }\n gl_FragColor = finalColor;\n #endif\n}\n"
}
}
],
"subMetas": {}
}

View File

@@ -0,0 +1,166 @@
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
// 点光/点扩散
// 原理:
// 1. 画圆
// 2. 圆心高亮(透明度=1.0),圆边缘不亮(透明度=0.0
// 3. 在原图像上方叠加圆
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
alphaThreshold: { value: 0.5 }
# 扩散颜色
centerColor: {
value: [1.0, 1.0, 0.0, 1.0],
inspector: {
type: color,
tooltip: "发光颜色"
}
}
# 扩散起点坐标
centerPoint: {
value: [0.2, 0.2],
inspector: {
tooltip: "扩散起点坐标"
}
}
# 扩散半径
radius: {
value: 0.4,
inspector: {
tooltip: "扩散半径"
}
}
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
#include <cc-local>
in vec3 a_position;
in vec4 a_color;
out vec4 v_color;
#if USE_TEXTURE
in vec2 a_uv0;
out vec2 v_uv0;
#endif
void main () {
vec4 pos = vec4(a_position, 1);
#if CC_USE_MODEL
pos = cc_matViewProj * cc_matWorld * pos;
#else
pos = cc_matViewProj * pos;
#endif
#if USE_TEXTURE
v_uv0 = a_uv0;
#endif
v_color = a_color;
gl_Position = pos;
}
}%
CCProgram fs %{
precision highp float;
#include <alpha-test>
in vec4 v_color;
#if USE_TEXTURE
in vec2 v_uv0;
uniform sampler2D texture;
#endif
#if ENABLE_DIFFUSION
uniform Diffusion {
// 扩散颜色
vec4 centerColor;
// 扩散起点坐标
vec2 centerPoint;
// 扩展半径
float radius;
// 裁剪掉透明区域上的点光
// ps编辑器还不支持 bool 类型的样子,因此没在 CCEffect 中定义
bool cropAlpha;
// 是否启用迷雾效果
// ps编辑器还不支持 bool 类型的样子,因此没在 CCEffect 中定义
bool enableFog;
}
/**
* 添加某个扩散点后混合后的纹理颜色
*/
vec4 addLightColor(vec4 textureColor, vec2 centerPoint, float radius, vec4 centerColor) {
// 计算当前 uv 到圆心起点的距离
float dis = distance(v_uv0, centerPoint);
float a = 1.0 ;
// 裁剪掉透明区域上的点光
if (cropAlpha) {
a *= step(0.01, textureColor.a);
}
// 裁剪掉圆范围外的uv迷雾效果
if (!enableFog) {
a *= step(dis, radius);
}
// 加入从中心往外渐变的效果
a *= 1.0 - (dis / radius);
// 计算出圆范围内,不同 uv 对应的实际颜色值
vec4 lightColor = centerColor * a;
// 混合颜色:在原始图像颜色上叠加圆颜色
return textureColor * textureColor.a + lightColor;
}
#endif
void main () {
vec4 o = vec4(1, 1, 1, 1);
#if USE_TEXTURE
o *= texture(texture, v_uv0);
#if CC_USE_ALPHA_ATLAS_TEXTURE
o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;
#endif
#endif
o *= v_color;
ALPHA_TEST(o);
gl_FragColor = o;
#if ENABLE_DIFFUSION
gl_FragColor = addLightColor(gl_FragColor, centerPoint, radius, centerColor);
#endif
}
}%

View File

@@ -0,0 +1,17 @@
{
"ver": "1.0.23",
"uuid": "72a182fc-08a6-4faa-8e36-8bd84b4a0b53",
"compiledShaders": [
{
"glsl1": {
"vert": "\nprecision highp float;\nuniform mat4 cc_matViewProj;\nuniform mat4 cc_matWorld;\n\nattribute vec3 a_position;\nattribute vec4 a_color;\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nattribute vec2 a_uv0;\nvarying vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform float alphaThreshold;\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nvarying vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_DIFFUSION\nuniform vec4 centerColor;\nuniform vec2 centerPoint;\nuniform float radius;\nuniform bool cropAlpha;\nuniform bool enableFog;\n/**\n * 添加某个扩散点后混合后的纹理颜色\n */\nvec4 addLightColor(vec4 textureColor, vec2 centerPoint, float radius, vec4 centerColor) {\n\n float dis = distance(v_uv0, centerPoint);\n\n float a = 1.0 ;\n\n if (cropAlpha) {\n a *= step(0.01, textureColor.a);\n }\n\n if (!enableFog) {\n a *= step(dis, radius);\n }\n\n a *= 1.0 - (dis / radius);\n\n vec4 lightColor = centerColor * a;\n\n return textureColor * textureColor.a + lightColor;\n}\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n gl_FragColor = o;\n \n #if ENABLE_DIFFUSION\n gl_FragColor = addLightColor(gl_FragColor, centerPoint, radius, centerColor);\n #endif\n}\n"
},
"glsl3": {
"vert": "\nprecision highp float;\nuniform CCGlobal {\n vec4 cc_time;\n\n vec4 cc_screenSize;\n\n vec4 cc_screenScale;\n\n vec4 cc_nativeSize;\n\n mat4 cc_matView;\n mat4 cc_matViewInv;\n mat4 cc_matProj;\n mat4 cc_matProjInv;\n mat4 cc_matViewProj;\n mat4 cc_matViewProjInv;\n vec4 cc_cameraPos;\n\n vec4 cc_exposure;\n\n vec4 cc_mainLitDir;\n\n vec4 cc_mainLitColor;\n\n vec4 cc_ambientSky;\n vec4 cc_ambientGround;\n};\nuniform CCLocal {\n mat4 cc_matWorld;\n mat4 cc_matWorldIT;\n};\n\nin vec3 a_position;\nin vec4 a_color;\nout vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 a_uv0;\nout vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform ALPHA_TEST {\n float alphaThreshold;\n }\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nin vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_DIFFUSION\nuniform Diffusion {\n\n vec4 centerColor;\n\n vec2 centerPoint;\n\n float radius;\n\n bool cropAlpha;\n\n bool enableFog;\n}\n\n/**\n * 添加某个扩散点后混合后的纹理颜色\n */\nvec4 addLightColor(vec4 textureColor, vec2 centerPoint, float radius, vec4 centerColor) {\n\n float dis = distance(v_uv0, centerPoint);\n\n float a = 1.0 ;\n\n if (cropAlpha) {\n a *= step(0.01, textureColor.a);\n }\n\n if (!enableFog) {\n a *= step(dis, radius);\n }\n\n a *= 1.0 - (dis / radius);\n\n vec4 lightColor = centerColor * a;\n\n return textureColor * textureColor.a + lightColor;\n}\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n gl_FragColor = o;\n \n #if ENABLE_DIFFUSION\n gl_FragColor = addLightColor(gl_FragColor, centerPoint, radius, centerColor);\n #endif\n}\n"
}
}
],
"subMetas": {}
}

View File

@@ -1,5 +1,7 @@
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
// 圆角裁剪
//
// 圆角裁剪(仅支持正方形纹理)
//
// 原理https://www.cnblogs.com/jqm304775992/p/4987793.html
// 代码:复制 yanjifa/shaderDemor 的 https://github.com/yanjifa/shaderDemo/blob/master/assets/Effect/CircleAvatar.effect
@@ -17,8 +19,8 @@ CCEffect %{
texture: { value: white }
alphaThreshold: { value: 0.5 }
# 圆角半径
roundCornerRadius: {
value: 0.1,
radius: {
value: 0.4,
inspector: {
tooltip: "圆角半径",
range: [0.0, 0.5]
@@ -77,7 +79,7 @@ CCProgram fs %{
#if ENABLE_ROUNDCORNER
uniform RoundCorner {
// 圆角半径
float roundCornerRadius;
float radius;
}
#endif
@@ -97,17 +99,17 @@ CCProgram fs %{
#if ENABLE_ROUNDCORNER
// 约束圆角半径范围在 [0.0, 0.5]
float radius = clamp(0.0, 0.5, roundCornerRadius);
float circleRadius = clamp(0.0, 0.5, radius);
// 将纹理uv往左偏移,实现偏移后的纹理中心点在 OpenGL 坐标系原点
// 将纹理uv往左偏移,实现偏移后的坐标系原点在纹理中心
vec2 uv = v_uv0.xy - vec2(0.5, 0.5);
// uv.x , uv.y : 为偏移后的的uv
// abs(uv.x) , abs(uv.y) : 将第二、三、四象限的点都投影到第一象限上,这样子只需要处理第一象限的情况就可以,简化判断
// 0.5 - radius : 计算出第一象限的圆角所在圆的圆心坐标
// (rx, ry) : 偏移映射后的 新的uv 坐标,相对于 第一象限圆角坐在圆心坐标 的相对坐标
float rx = abs(uv.x) - (0.5 - radius);
float ry = abs(uv.y) - (0.5 - radius);
float rx = abs(uv.x) - (0.5 - circleRadius);
float ry = abs(uv.y) - (0.5 - circleRadius);
// 区分 以第一象限圆角所在圆心坐标为原点的坐标的四个象限
//
@@ -117,26 +119,26 @@ CCProgram fs %{
// 第四象限 mx = 1, my = 0
//
// 当 mx * my 时只要等于1那就是标识第一象限实际对应圆角区域所在矩形否则就是第二、三、四象限
float mx = step(0.5 - radius, abs(uv.x));
float my = step(0.5 - radius, abs(uv.y));
float mx = step(0.5 - circleRadius, abs(uv.x));
float my = step(0.5 - circleRadius, abs(uv.y));
// 计算相对uv坐标到圆心的距离
float len = length(vec2(rx, ry));
// mx * my = 0 时代表非圆角区域a 值为1代表完全采用原始纹理的透明度
// mx * my = 1 时,代表园所所在矩形区域
// step(radius, len) 可以区分出圆角所在矩形区域的 圆角区域 和 非圆角区域
// step(circleRadius, len) 可以区分出圆角所在矩形区域的 圆角区域 和 非圆角区域
// 其中圆角区域值为0非圆角区域值为1
// 当为圆角区域时a 值为1代表完全采用原始纹理透明度
// 当为非圆角区域时a 值为0代表完全透明
// 至此已经实现圆角裁剪
//
// smoothstep(0., radius * 0.01, len - radius) 是用于抗锯齿优化
// smoothstep(0., circleRadius * 0.01, len - circleRadius) 是用于抗锯齿优化
// 原理:针对点在非圆角区域的情况,针对点在大于「圆半径一点点」地方的区域,进行平滑过渡,以实现抗锯齿
// 其中,
// 「圆半径一点点」用 radius * 0.01 表示0.01 可自行改变)
// 点在大于圆半径的区域用 len - radius ,此值会在 [0.0, radius * 0.01] 之间时会平滑过渡
float a = 1.0 - mx * my * step(radius, len) * smoothstep(0., radius * 0.01, len - radius);
// 「圆半径一点点」用 circleRadius * 0.01 表示0.01 可自行改变)
// 点在大于圆半径的区域用 len - circleRadius ,此值会在 [0.0, circleRadius * 0.01] 之间时会平滑过渡
float a = 1.0 - mx * my * step(circleRadius, len) * smoothstep(0., circleRadius * 0.01, len - circleRadius);
o = vec4(o.rgb, o.a * a);
#endif
gl_FragColor = o;

View File

@@ -5,11 +5,11 @@
{
"glsl1": {
"vert": "\nprecision highp float;\nuniform mat4 cc_matViewProj;\nuniform mat4 cc_matWorld;\n\nattribute vec3 a_position;\nattribute vec4 a_color;\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nattribute vec2 a_uv0;\nvarying vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform float alphaThreshold;\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nvarying vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_ROUNDCORNER\nuniform float roundCornerRadius;\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n #if ENABLE_ROUNDCORNER\n\n float radius = clamp(0.0, 0.5, roundCornerRadius);\n\n vec2 uv = v_uv0.xy - vec2(0.5, 0.5);\n\n float rx = abs(uv.x) - (0.5 - radius);\n float ry = abs(uv.y) - (0.5 - radius);\n\n float mx = step(0.5 - radius, abs(uv.x));\n float my = step(0.5 - radius, abs(uv.y));\n\n float len = length(vec2(rx, ry));\n\n float a = 1.0 - mx * my * step(radius, len) * smoothstep(0., radius * 0.01, len - radius);\n o = vec4(o.rgb, o.a * a);\n #endif\n gl_FragColor = o;\n}\n"
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform float alphaThreshold;\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nvarying vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_ROUNDCORNER\nuniform float radius;\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n #if ENABLE_ROUNDCORNER\n\n float circleRadius = clamp(0.0, 0.5, radius);\n\n vec2 uv = v_uv0.xy - vec2(0.5, 0.5);\n\n float rx = abs(uv.x) - (0.5 - circleRadius);\n float ry = abs(uv.y) - (0.5 - circleRadius);\n\n float mx = step(0.5 - circleRadius, abs(uv.x));\n float my = step(0.5 - circleRadius, abs(uv.y));\n\n float len = length(vec2(rx, ry));\n\n float a = 1.0 - mx * my * step(circleRadius, len) * smoothstep(0., circleRadius * 0.01, len - circleRadius);\n o = vec4(o.rgb, o.a * a);\n #endif\n gl_FragColor = o;\n}\n"
},
"glsl3": {
"vert": "\nprecision highp float;\nuniform CCGlobal {\n vec4 cc_time;\n\n vec4 cc_screenSize;\n\n vec4 cc_screenScale;\n\n vec4 cc_nativeSize;\n\n mat4 cc_matView;\n mat4 cc_matViewInv;\n mat4 cc_matProj;\n mat4 cc_matProjInv;\n mat4 cc_matViewProj;\n mat4 cc_matViewProjInv;\n vec4 cc_cameraPos;\n\n vec4 cc_exposure;\n\n vec4 cc_mainLitDir;\n\n vec4 cc_mainLitColor;\n\n vec4 cc_ambientSky;\n vec4 cc_ambientGround;\n};\nuniform CCLocal {\n mat4 cc_matWorld;\n mat4 cc_matWorldIT;\n};\n\nin vec3 a_position;\nin vec4 a_color;\nout vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 a_uv0;\nout vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform ALPHA_TEST {\n float alphaThreshold;\n }\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nin vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_ROUNDCORNER\nuniform RoundCorner {\n\n float roundCornerRadius;\n}\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n #if ENABLE_ROUNDCORNER\n\n float radius = clamp(0.0, 0.5, roundCornerRadius);\n\n vec2 uv = v_uv0.xy - vec2(0.5, 0.5);\n\n float rx = abs(uv.x) - (0.5 - radius);\n float ry = abs(uv.y) - (0.5 - radius);\n\n float mx = step(0.5 - radius, abs(uv.x));\n float my = step(0.5 - radius, abs(uv.y));\n\n float len = length(vec2(rx, ry));\n\n float a = 1.0 - mx * my * step(radius, len) * smoothstep(0., radius * 0.01, len - radius);\n o = vec4(o.rgb, o.a * a);\n #endif\n gl_FragColor = o;\n}\n"
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform ALPHA_TEST {\n float alphaThreshold;\n }\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nin vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_ROUNDCORNER\nuniform RoundCorner {\n\n float radius;\n}\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n #if ENABLE_ROUNDCORNER\n\n float circleRadius = clamp(0.0, 0.5, radius);\n\n vec2 uv = v_uv0.xy - vec2(0.5, 0.5);\n\n float rx = abs(uv.x) - (0.5 - circleRadius);\n float ry = abs(uv.y) - (0.5 - circleRadius);\n\n float mx = step(0.5 - circleRadius, abs(uv.x));\n float my = step(0.5 - circleRadius, abs(uv.y));\n\n float len = length(vec2(rx, ry));\n\n float a = 1.0 - mx * my * step(circleRadius, len) * smoothstep(0., circleRadius * 0.01, len - circleRadius);\n o = vec4(o.rgb, o.a * a);\n #endif\n gl_FragColor = o;\n}\n"
}
}
],

View File

@@ -0,0 +1,194 @@
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
//
// 圆角裁剪(支持任意宽高纹理)
//
// 原理:
// 1. 正方形纹理的圆角原理参考 https://www.cnblogs.com/jqm304775992/p/4987793.html
// 2. 正方形纹理的圆角代码参考 yanjifa/shaderDemor 的 https://github.com/yanjifa/shaderDemo/blob/master/assets/Effect/CircleAvatar.effect
// 3. 上述皆为只针对正方形纹理做的操作,如果是长方形的纹理,那么圆角就会有拉伸后的效果,最后变成看起来就不是圆角了,本特效支持任意长方形做圆角
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
alphaThreshold: { value: 0.5 }
# 圆角x轴半径长度相对于纹理宽度
xRadius: {
value: 0.4,
inspector: {
tooltip: "圆角x轴半径长度相对于纹理宽度",
range: [0.0, 0.5]
}
}
# 圆角y轴半径长度相对于纹理高度
yRadius: {
value: 0.4,
inspector: {
tooltip: "圆角y轴半径长度相对于纹理高度",
range: [0.0, 0.5]
}
}
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
#include <cc-local>
in vec3 a_position;
in vec4 a_color;
out vec4 v_color;
#if USE_TEXTURE
in vec2 a_uv0;
out vec2 v_uv0;
#endif
void main () {
vec4 pos = vec4(a_position, 1);
#if CC_USE_MODEL
pos = cc_matViewProj * cc_matWorld * pos;
#else
pos = cc_matViewProj * pos;
#endif
#if USE_TEXTURE
v_uv0 = a_uv0;
#endif
v_color = a_color;
gl_Position = pos;
}
}%
CCProgram fs %{
precision highp float;
#include <alpha-test>
in vec4 v_color;
#if USE_TEXTURE
in vec2 v_uv0;
uniform sampler2D texture;
#endif
#if ENABLE_ROUNDCORNER
uniform RoundCorner {
// 圆角x轴半径长度相对于纹理宽度
float xRadius;
// 圆角y轴半径长度相对于纹理高度
float yRadius;
}
#endif
void main () {
vec4 o = vec4(1, 1, 1, 1);
#if USE_TEXTURE
o *= texture(texture, v_uv0);
#if CC_USE_ALPHA_ATLAS_TEXTURE
o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;
#endif
#endif
o *= v_color;
ALPHA_TEST(o);
#if ENABLE_ROUNDCORNER
// 约束圆角半径范围在 [0.0, 0.5]
//
// 请注意这里我是用椭圆前缀去命名的半径
//
// 为什么是椭圆?
//
// 因为圆角,相对于长方形的纹理的宽高来说,归一化后值并不一样,不是圆,而是一个椭圆
//
// 比如:
//
// 纹理是 200 x 100 的像素圆角半径是20像素那么归一化后
// X轴上的半径就是 20 / 200 = 0.1
// Y轴上的半径就是 20 / 100 = 0.2
//
// 这就会变成是椭圆,而不是圆
float ellipseXRadius = clamp(0.0, 0.5, xRadius);
float ellipseYRadius = clamp(0.0, 0.5, yRadius);
// 将纹理uv往左上偏移实现偏移后的坐标系原点在纹理中心
vec2 uv = v_uv0.xy - vec2(0.5, 0.5);
// uv.x , uv.y : 为偏移后的的uv
// abs(uv.x) , abs(uv.y) : 将第二、三、四象限的点都投影到第一象限上,这样子只需要处理第一象限的情况就可以,简化判断
// 0.5 - radius : 计算出第一象限的圆角所在圆的圆心坐标
// (rx, ry) : 偏移映射后的 新的uv 坐标,相对于 第一象限圆角坐在圆心坐标 的相对坐标
float rx = abs(uv.x) - (0.5 - ellipseXRadius);
float ry = abs(uv.y) - (0.5 - ellipseYRadius);
// 区分 以第一象限圆角所在圆心坐标为原点的坐标的四个象限
//
// 第一象限 mx = 1, my = 1
// 第二象限 mx = 0, my = 1
// 第三象限 mx = 0, my = 0
// 第四象限 mx = 1, my = 0
//
// 当 mx * my 时只要等于1那就是标识第一象限实际对应圆角区域所在矩形否则就是第二、三、四象限
float mx = step(0.5 - ellipseXRadius, abs(uv.x));
float my = step(0.5 - ellipseYRadius, abs(uv.y));
// 判断点(rx, ry)是否在椭圆外部(应用椭圆公式)
float isOutOfEllipse = step(1.0, pow(rx, 2.0) / pow(xRadius, 2.0) + pow(ry, 2.0) / pow(yRadius, 2.0));
///////////////////////////////////////////////////////////////////////////////////////////
// 抗锯齿
// 1. 先计算当前点到椭圆中心的角度
float angleInRadian = atan(ry / rx);
// 2. 计算这个角度下,对于对应圆角(椭圆)上的点
vec2 pointInEllipse = vec2(xRadius * cos(angleInRadian), yRadius * sin(angleInRadian));
// 3. 计算这个角度下,比当前圆角大一点椭圆上的点
vec2 pointInBigEllipse = vec2((xRadius * 1.01) * cos(angleInRadian), (yRadius * 1.01)* sin(angleInRadian));
// 4. 计算最远点到当前椭圆的距离
float maxDis = distance(pointInBigEllipse, pointInEllipse);
// 5. 计算当前点到当前椭圆的距离
float curDis = distance(vec2(rx, ry), pointInEllipse);
// 6. 生成插值
float smo = smoothstep(0.0, maxDis, curDis);
///////////////////////////////////////////////////////////////////////////////////////////
// mx * my = 0 时代表非椭圆角区域alpha 值为1代表完全采用原始纹理的透明度
// mx * my = 1 时,代表椭圆角所在矩形区域
// isOutOfEllipse:
// 当点在椭圆外部时此值为1导致 alpha 最终值为0.0,即表示不显示椭圆外部的像素
// 当点在椭圆内部时此值为0导致 alpha 最终值为1.0,即表示显示椭圆内部的像素
// smo : 抗锯齿实现
// float alpha = 1.0 - mx * my * isOutOfEllipse;
float alpha = 1.0 - mx * my * isOutOfEllipse * smo;
o = vec4(o.rgb, o.a * alpha);
#endif
gl_FragColor = o;
}
}%

View File

@@ -0,0 +1,17 @@
{
"ver": "1.0.23",
"uuid": "7c24b57e-e819-4fc9-a8d2-b06cf61b782d",
"compiledShaders": [
{
"glsl1": {
"vert": "\nprecision highp float;\nuniform mat4 cc_matViewProj;\nuniform mat4 cc_matWorld;\n\nattribute vec3 a_position;\nattribute vec4 a_color;\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nattribute vec2 a_uv0;\nvarying vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform float alphaThreshold;\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nvarying vec4 v_color;\n\n#if USE_TEXTURE\nvarying vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_ROUNDCORNER\nuniform float xRadius;\nuniform float yRadius;\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n #if ENABLE_ROUNDCORNER\n\n float ellipseXRadius = clamp(0.0, 0.5, xRadius);\n float ellipseYRadius = clamp(0.0, 0.5, yRadius);\n\n vec2 uv = v_uv0.xy - vec2(0.5, 0.5);\n\n float rx = abs(uv.x) - (0.5 - ellipseXRadius);\n float ry = abs(uv.y) - (0.5 - ellipseYRadius);\n\n float mx = step(0.5 - ellipseXRadius, abs(uv.x));\n float my = step(0.5 - ellipseYRadius, abs(uv.y));\n\n float isOutOfEllipse = step(1.0, pow(rx, 2.0) / pow(xRadius, 2.0) + pow(ry, 2.0) / pow(yRadius, 2.0));\n\n float angleInRadian = atan(ry / rx);\n\n vec2 pointInEllipse = vec2(xRadius * cos(angleInRadian), yRadius * sin(angleInRadian));\n\n vec2 pointInBigEllipse = vec2((xRadius * 1.01) * cos(angleInRadian), (yRadius * 1.01)* sin(angleInRadian));\n\n float maxDis = distance(pointInBigEllipse, pointInEllipse);\n\n float curDis = distance(vec2(rx, ry), pointInEllipse);\n\n float smo = smoothstep(0.0, maxDis, curDis);\n\n float alpha = 1.0 - mx * my * isOutOfEllipse * smo;\n\n o = vec4(o.rgb, o.a * alpha);\n\n #endif\n gl_FragColor = o;\n}\n"
},
"glsl3": {
"vert": "\nprecision highp float;\nuniform CCGlobal {\n vec4 cc_time;\n\n vec4 cc_screenSize;\n\n vec4 cc_screenScale;\n\n vec4 cc_nativeSize;\n\n mat4 cc_matView;\n mat4 cc_matViewInv;\n mat4 cc_matProj;\n mat4 cc_matProjInv;\n mat4 cc_matViewProj;\n mat4 cc_matViewProjInv;\n vec4 cc_cameraPos;\n\n vec4 cc_exposure;\n\n vec4 cc_mainLitDir;\n\n vec4 cc_mainLitColor;\n\n vec4 cc_ambientSky;\n vec4 cc_ambientGround;\n};\nuniform CCLocal {\n mat4 cc_matWorld;\n mat4 cc_matWorldIT;\n};\n\nin vec3 a_position;\nin vec4 a_color;\nout vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 a_uv0;\nout vec2 v_uv0;\n#endif\n\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n\n v_color = a_color;\n\n gl_Position = pos;\n}\n",
"frag": "\nprecision highp float;\n\n#if USE_ALPHA_TEST\n \n uniform ALPHA_TEST {\n float alphaThreshold;\n }\n#endif\n\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\n\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\n\nin vec4 v_color;\n\n#if USE_TEXTURE\nin vec2 v_uv0;\nuniform sampler2D texture;\n#endif\n\n#if ENABLE_ROUNDCORNER\nuniform RoundCorner {\n\n float xRadius;\n\n float yRadius;\n}\n#endif\n\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n\n #if USE_TEXTURE\n o *= texture(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n\n o *= v_color;\n\n ALPHA_TEST(o);\n\n #if ENABLE_ROUNDCORNER\n\n float ellipseXRadius = clamp(0.0, 0.5, xRadius);\n float ellipseYRadius = clamp(0.0, 0.5, yRadius);\n\n vec2 uv = v_uv0.xy - vec2(0.5, 0.5);\n\n float rx = abs(uv.x) - (0.5 - ellipseXRadius);\n float ry = abs(uv.y) - (0.5 - ellipseYRadius);\n\n float mx = step(0.5 - ellipseXRadius, abs(uv.x));\n float my = step(0.5 - ellipseYRadius, abs(uv.y));\n\n float isOutOfEllipse = step(1.0, pow(rx, 2.0) / pow(xRadius, 2.0) + pow(ry, 2.0) / pow(yRadius, 2.0));\n\n float angleInRadian = atan(ry / rx);\n\n vec2 pointInEllipse = vec2(xRadius * cos(angleInRadian), yRadius * sin(angleInRadian));\n\n vec2 pointInBigEllipse = vec2((xRadius * 1.01) * cos(angleInRadian), (yRadius * 1.01)* sin(angleInRadian));\n\n float maxDis = distance(pointInBigEllipse, pointInEllipse);\n\n float curDis = distance(vec2(rx, ry), pointInEllipse);\n\n float smo = smoothstep(0.0, maxDis, curDis);\n\n float alpha = 1.0 - mx * my * isOutOfEllipse * smo;\n\n o = vec4(o.rgb, o.a * alpha);\n\n #endif\n gl_FragColor = o;\n}\n"
}
}
],
"subMetas": {}
}

View File

@@ -0,0 +1,24 @@
{
"__type__": "cc.Material",
"_name": "",
"_objFlags": 0,
"_native": "",
"_effectAsset": {
"__uuid__": "e9682cd1-a19c-4fcb-ad8c-cf1783b805e6"
},
"_defines": {
"USE_TEXTURE": true,
"ENABLE_LIGHT": true
},
"_props": {
"lightColor": {
"__type__": "cc.Color",
"r": 255,
"g": 245,
"b": 0,
"a": 255
},
"lightAngle": 36,
"lightWidth": 0.2
}
}

View File

@@ -0,0 +1,6 @@
{
"ver": "1.0.2",
"uuid": "43a22f18-72fc-4399-b5ae-8305705861f4",
"dataAsSubAsset": null,
"subMetas": {}
}

View File

@@ -0,0 +1,14 @@
{
"__type__": "cc.Material",
"_name": "",
"_objFlags": 0,
"_native": "",
"_effectAsset": {
"__uuid__": "41f4d474-d707-45bb-af93-637573f92d54"
},
"_defines": {
"USE_TEXTURE": true,
"ENABLE_GAUSSIAN_BLUR": true
},
"_props": {}
}

View File

@@ -0,0 +1,6 @@
{
"ver": "1.0.2",
"uuid": "dd3d8f78-9b79-4ca7-9bf7-7a09f7b34108",
"dataAsSubAsset": null,
"subMetas": {}
}

View File

@@ -0,0 +1,16 @@
{
"__type__": "cc.Material",
"_name": "",
"_objFlags": 0,
"_native": "",
"_effectAsset": {
"__uuid__": "72a182fc-08a6-4faa-8e36-8bd84b4a0b53"
},
"_defines": {
"USE_TEXTURE": true,
"ENABLE_DIFFUSION": true
},
"_props": {
"radius": 0.4
}
}

View File

@@ -0,0 +1,6 @@
{
"ver": "1.0.2",
"uuid": "d88d982e-4ed7-4f90-9566-2ac2fef4bcb3",
"dataAsSubAsset": null,
"subMetas": {}
}

View File

@@ -10,7 +10,5 @@
"USE_TEXTURE": true,
"ENABLE_ROUNDCORNER": true
},
"_props": {
"roundCornerRadius": 0.1
}
"_props": {}
}

View File

@@ -0,0 +1,14 @@
{
"__type__": "cc.Material",
"_name": "",
"_objFlags": 0,
"_native": "",
"_effectAsset": {
"__uuid__": "7c24b57e-e819-4fc9-a8d2-b06cf61b782d"
},
"_defines": {
"USE_TEXTURE": true,
"ENABLE_ROUNDCORNER": true
},
"_props": {}
}

View File

@@ -0,0 +1,6 @@
{
"ver": "1.0.2",
"uuid": "a86e8864-5390-443f-b41b-b38e9d584c43",
"dataAsSubAsset": null,
"subMetas": {}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
{
"ver": "1.2.5",
"uuid": "54bdad42-93aa-4869-a465-c0eac37bf0d2",
"asyncLoadAssets": false,
"autoReleaseAssets": false,
"subMetas": {}
}

View File

@@ -58,7 +58,7 @@
"_groupIndex": 0,
"groupIndex": 0,
"autoReleaseAssets": false,
"_id": "6c351889-b6c8-409f-b36c-4263b06d0b23"
"_id": "147d5b9f-b769-4112-9daf-2e28236161fa"
},
{
"__type__": "cc.Node",
@@ -171,7 +171,7 @@
"array": [
0,
0,
418.2902700278839,
491.9024293495612,
0,
0,
0,
@@ -428,7 +428,7 @@
},
{
"__type__": "cc.Node",
"_name": "Sliders",
"_name": "Controller",
"_objFlags": 0,
"_parent": {
"__id__": 5
@@ -459,7 +459,7 @@
"_contentSize": {
"__type__": "cc.Size",
"width": 576,
"height": 60
"height": -36
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -497,7 +497,7 @@
},
{
"__type__": "cc.Node",
"_name": "RoundCornerRadiusSlider",
"_name": "BlurSlider",
"_objFlags": 0,
"_parent": {
"__id__": 9
@@ -513,7 +513,7 @@
"__id__": 23
}
],
"_active": true,
"_active": false,
"_components": [
{
"__id__": 26
@@ -646,8 +646,8 @@
}
],
"_useOriginalSize": false,
"_string": "圆角半径",
"_N$string": "圆角半径",
"_string": "模糊程度",
"_N$string": "模糊程度",
"_fontSize": 40,
"_lineHeight": 40,
"_enableWrapText": true,
@@ -1294,7 +1294,7 @@
"_layoutSize": {
"__type__": "cc.Size",
"width": 576,
"height": 60
"height": -36
},
"_resize": 1,
"_N$layoutType": 2,
@@ -1367,7 +1367,7 @@
"_contentSize": {
"__type__": "cc.Size",
"width": 384,
"height": 629.73
"height": 805.73
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -1411,7 +1411,7 @@
"__id__": 29
},
"_children": [],
"_active": false,
"_active": true,
"_components": [
{
"__id__": 31
@@ -1475,7 +1475,7 @@
"_enabled": true,
"_materials": [
{
"__uuid__": "642c2d0e-7eb6-4d65-96f2-d6e0d0305310"
"__uuid__": "dd3d8f78-9b79-4ca7-9bf7-7a09f7b34108"
}
],
"_srcBlendFactor": 770,
@@ -1499,7 +1499,7 @@
},
{
"__type__": "cc.Node",
"_name": "freedom",
"_name": "gaussian_blur",
"_objFlags": 0,
"_parent": {
"__id__": 29
@@ -1522,8 +1522,8 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 240,
"height": 240
"width": 316,
"height": 210
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -1535,7 +1535,7 @@
"ctor": "Float64Array",
"array": [
0,
-120,
-177,
0,
0,
0,
@@ -1557,7 +1557,7 @@
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "47hFX2oHFLvrpZ4r0ouXPs"
"_id": "0c1gWopWlLwLl+GiSUizBJ"
},
{
"__type__": "cc.Sprite",
@@ -1569,16 +1569,16 @@
"_enabled": true,
"_materials": [
{
"__uuid__": "642c2d0e-7eb6-4d65-96f2-d6e0d0305310"
"__uuid__": "dd3d8f78-9b79-4ca7-9bf7-7a09f7b34108"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "dbc8f785-d78b-4179-bfce-ffbf69396712"
"__uuid__": "91f28953-0d5f-4379-9ae6-f3f6afb3241c"
},
"_type": 0,
"_sizeMode": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
@@ -1589,7 +1589,7 @@
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": null,
"_id": "f61+UyKJdOyIJQABsng1SX"
"_id": "eckV5v4lpDULdq2uKByFTd"
},
{
"__type__": "cc.Node",
@@ -1629,7 +1629,7 @@
"ctor": "Float64Array",
"array": [
0,
-387,
-429,
0,
0,
0,
@@ -1663,7 +1663,7 @@
"_enabled": true,
"_materials": [
{
"__uuid__": "642c2d0e-7eb6-4d65-96f2-d6e0d0305310"
"__uuid__": "dd3d8f78-9b79-4ca7-9bf7-7a09f7b34108"
}
],
"_srcBlendFactor": 770,
@@ -1693,7 +1693,7 @@
"__id__": 29
},
"_children": [],
"_active": false,
"_active": true,
"_components": [
{
"__id__": 37
@@ -1723,7 +1723,7 @@
"ctor": "Float64Array",
"array": [
0,
-564,
-606,
0,
0,
0,
@@ -1757,7 +1757,7 @@
"_enabled": true,
"_materials": [
{
"__uuid__": "642c2d0e-7eb6-4d65-96f2-d6e0d0305310"
"__uuid__": "dd3d8f78-9b79-4ca7-9bf7-7a09f7b34108"
}
],
"_srcBlendFactor": 770,
@@ -1787,7 +1787,7 @@
"__id__": 29
},
"_children": [],
"_active": false,
"_active": true,
"_components": [
{
"__id__": 39
@@ -1817,7 +1817,7 @@
"ctor": "Float64Array",
"array": [
0,
-631,
-673,
0,
0,
0,
@@ -1851,7 +1851,7 @@
"_enabled": true,
"_materials": [
{
"__uuid__": "642c2d0e-7eb6-4d65-96f2-d6e0d0305310"
"__uuid__": "dd3d8f78-9b79-4ca7-9bf7-7a09f7b34108"
}
],
"_srcBlendFactor": 770,
@@ -1911,7 +1911,7 @@
"ctor": "Float64Array",
"array": [
0,
-559.2,
-735.2,
0,
0,
0,
@@ -1945,7 +1945,7 @@
"_enabled": true,
"_materials": [
{
"__uuid__": "642c2d0e-7eb6-4d65-96f2-d6e0d0305310"
"__uuid__": "dd3d8f78-9b79-4ca7-9bf7-7a09f7b34108"
}
],
"_useOriginalSize": false,
@@ -2003,7 +2003,7 @@
"ctor": "Float64Array",
"array": [
0,
-613.065,
-789.065,
0,
0,
0,
@@ -2037,7 +2037,7 @@
"_enabled": true,
"_materials": [
{
"__uuid__": "642c2d0e-7eb6-4d65-96f2-d6e0d0305310"
"__uuid__": "dd3d8f78-9b79-4ca7-9bf7-7a09f7b34108"
}
],
"_useOriginalSize": false,
@@ -2097,7 +2097,7 @@
"_layoutSize": {
"__type__": "cc.Size",
"width": 384,
"height": 629.73
"height": 805.73
},
"_resize": 1,
"_N$layoutType": 2,
@@ -2147,13 +2147,13 @@
"_id": "4bz2+ak99DBYVlSVIMFGN0"
},
{
"__type__": "d3d2b7nIXNDbKEclKMbIFTC",
"__type__": "f460djPUfdEdrpZFw3saPVi",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 2
},
"_enabled": true,
"_id": "9ayfD37bZP1IEjPxGKO6+/"
"_id": "77Tlx8YKFO6aLFI6G67OJ+"
}
]

View File

@@ -0,0 +1,7 @@
{
"ver": "1.2.5",
"uuid": "147d5b9f-b769-4112-9daf-2e28236161fa",
"asyncLoadAssets": false,
"autoReleaseAssets": false,
"subMetas": {}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
{
"ver": "1.2.5",
"uuid": "7d64bd80-8e2c-4c7c-8d65-ea69b0c4b3d3",
"asyncLoadAssets": false,
"autoReleaseAssets": false,
"subMetas": {}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
{
"ver": "1.2.5",
"uuid": "c2dec4ed-8129-40a2-9a1e-2440da772015",
"asyncLoadAssets": false,
"autoReleaseAssets": false,
"subMetas": {}
}

View File

@@ -0,0 +1,97 @@
const { ccclass, property } = cc._decorator;
@ccclass
export default class FlashLightCtrlComponent extends cc.Component {
private _flashLightUBO: FlashLightUBO = new FlashLightUBO();
onEnable() {
this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
this.node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this);
this.node.on("on_property_change", this._onPropertyChange, this);
}
onDisable() {
this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
this.node.off(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this);
this.node.off("on_property_change", this._onPropertyChange, this);
}
private _onTouchStart(event: cc.Event.EventTouch) {
this._onTouchMove(event);
}
private _onTouchMove(event: cc.Event.EventTouch) {
let touchPointInWorldSpace = event.getLocation();
let touchPointInNodeSpace = this.node.convertToNodeSpaceAR(touchPointInWorldSpace);
// 将触摸点转换为OPENGL坐标系并归一化
// OpenGl 坐标系原点在左上角
this._flashLightUBO.lightCenterPoint = cc.v2(
this.node.anchorX + touchPointInNodeSpace.x / this.node.width,
1 - (this.node.anchorY + touchPointInNodeSpace.y / this.node.height)
);
this._updateMaterial();
}
private _onPropertyChange(localDiffusionUniform: FlashLightUBO) {
this._flashLightUBO.lightColor = localDiffusionUniform.lightColor;
this._flashLightUBO.lightAngle = localDiffusionUniform.lightAngle;
this._flashLightUBO.lightWidth = localDiffusionUniform.lightWidth;
this._flashLightUBO.enableGradient = localDiffusionUniform.enableGradient;
this._flashLightUBO.cropAlpha = localDiffusionUniform.cropAlpha;
this._flashLightUBO.enableFog = localDiffusionUniform.enableFog;
this._updateMaterial();
}
private _updateMaterial() {
this.getComponents(cc.RenderComponent).forEach(renderComponent => {
let material: cc.Material = renderComponent.getMaterial(0);
material.setProperty("lightColor", this._flashLightUBO.lightColor);
material.setProperty("lightCenterPoint", this._flashLightUBO.lightCenterPoint);
material.setProperty("lightAngle", this._flashLightUBO.lightAngle);
material.setProperty("lightWidth", this._flashLightUBO.lightWidth);
material.setProperty("enableGradient", this._flashLightUBO.enableGradient);
material.setProperty("cropAlpha", this._flashLightUBO.cropAlpha);
material.setProperty("enableFog", this._flashLightUBO.enableFog);
renderComponent.setMaterial(0, material);
});
}
}
export class FlashLightUBO {
/**
* 中心点颜色
*/
lightColor: cc.Color = cc.Color.YELLOW;
/**
* 中心点坐标 ([0.0, 1.0], [0.0, 1.0])
*/
lightCenterPoint: cc.Vec2 = cc.v2(0.5, 0.5);
/**
* 光束角度 [0.0, 180.0]
*/
lightAngle: number = 45;
/**
* 光束宽度 [0.0, +∞]
*/
lightWidth: number = 0.5;
/**
* 是否启用光束渐变
*/
enableGradient: boolean = true;
/**
* 是否裁剪掉透明区域上的点光
*/
cropAlpha: boolean = true;
/**
* 是否开启战争迷雾效果
*/
enableFog: boolean = false;
}

View File

@@ -1,6 +1,6 @@
{
"ver": "1.0.5",
"uuid": "d3d2bee7-2173-436c-a11c-94a31b2054c2",
"uuid": "3edca38f-0f12-489f-847a-0d89d9e55c6c",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,

View File

@@ -0,0 +1,111 @@
import FlashLightCtrlComponent, { FlashLightUBO } from "./FlashLightCtrlComponent";
const { ccclass, property } = cc._decorator;
@ccclass
export default class FlashLightEffectScene extends cc.Component {
private _redSlider: cc.Slider = null;
private _redSliderLabel: cc.Label = null;
private _greenSlider: cc.Slider = null;
private _greenSliderLabel: cc.Label = null;
private _blueSlider: cc.Slider = null;
private _blueSliderLabel: cc.Label = null;
private _alphaSlider: cc.Slider = null;
private _alphaSliderLabel: cc.Label = null;
private _lightWidthSlider: cc.Slider = null;
private _lightWidthSliderLabel: cc.Label = null;
private _lightAngleSlider: cc.Slider = null;
private _lightAngleSliderLabel: cc.Label = null;
private _enableGradientToggle: cc.Toggle = null;
private _cropAlphaToggle: cc.Toggle = null;
private _enableFogToggle: cc.Toggle = null;
private _examplesParentNode: cc.Node = null;
onLoad() {
cc.dynamicAtlasManager.enabled = false;
this._redSlider = cc.find("Canvas/Content/Controller/ColorRedSlider/Slider").getComponent(cc.Slider);
this._redSliderLabel = cc.find("Canvas/Content/Controller/ColorRedSlider/ValueLabel").getComponent(cc.Label);
this._greenSlider = cc.find("Canvas/Content/Controller/ColorGreenSlider/Slider").getComponent(cc.Slider);
this._greenSliderLabel = cc.find("Canvas/Content/Controller/ColorGreenSlider/ValueLabel").getComponent(cc.Label);
this._blueSlider = cc.find("Canvas/Content/Controller/ColorBlueSlider/Slider").getComponent(cc.Slider);
this._blueSliderLabel = cc.find("Canvas/Content/Controller/ColorBlueSlider/ValueLabel").getComponent(cc.Label);
this._alphaSlider = cc.find("Canvas/Content/Controller/ColorAlphaSlider/Slider").getComponent(cc.Slider);
this._alphaSliderLabel = cc.find("Canvas/Content/Controller/ColorAlphaSlider/ValueLabel").getComponent(cc.Label);
this._lightWidthSlider = cc.find("Canvas/Content/Controller/LightWidthSlider/Slider").getComponent(cc.Slider);
this._lightWidthSliderLabel = cc.find("Canvas/Content/Controller/LightWidthSlider/ValueLabel").getComponent(cc.Label);
this._lightAngleSlider = cc.find("Canvas/Content/Controller/LightAngleSlider/Slider").getComponent(cc.Slider);
this._lightAngleSliderLabel = cc.find("Canvas/Content/Controller/LightAngleSlider/ValueLabel").getComponent(cc.Label);
this._enableGradientToggle = cc.find("Canvas/Content/Controller/EnableGradientToggle/Toggle").getComponent(cc.Toggle);
this._cropAlphaToggle = cc.find("Canvas/Content/Controller/CropAlphaToggle/Toggle").getComponent(cc.Toggle);
this._enableFogToggle = cc.find("Canvas/Content/Controller/EnableFogToggle/Toggle").getComponent(cc.Toggle);
// 代码添加控制脚本
this._examplesParentNode = cc.find("Canvas/Content/Examples");
this._examplesParentNode.children.forEach(childNode => {
childNode.addComponent(FlashLightCtrlComponent);
});
}
onEnable() {
this._redSlider.node.on("slide", this._onPropertyChanged, this);
this._greenSlider.node.on("slide", this._onPropertyChanged, this);
this._blueSlider.node.on("slide", this._onPropertyChanged, this);
this._alphaSlider.node.on("slide", this._onPropertyChanged, this);
this._lightWidthSlider.node.on("slide", this._onPropertyChanged, this);
this._lightAngleSlider.node.on("slide", this._onPropertyChanged, this);
this._enableGradientToggle.node.on("toggle", this._onPropertyChanged, this);
this._cropAlphaToggle.node.on("toggle", this._onPropertyChanged, this);
this._enableFogToggle.node.on("toggle", this._onPropertyChanged, this);
}
onDisable() {
this._redSlider.node.off("slide", this._onPropertyChanged, this);
this._greenSlider.node.off("slide", this._onPropertyChanged, this);
this._blueSlider.node.off("slide", this._onPropertyChanged, this);
this._alphaSlider.node.off("slide", this._onPropertyChanged, this);
this._lightWidthSlider.node.off("slide", this._onPropertyChanged, this);
this._lightAngleSlider.node.off("slide", this._onPropertyChanged, this);
this._enableGradientToggle.node.off("toggle", this._onPropertyChanged, this);
this._cropAlphaToggle.node.off("toggle", this._onPropertyChanged, this);
this._enableFogToggle.node.off("toggle", this._onPropertyChanged, this);
}
start() {
this._onPropertyChanged();
}
private _onPropertyChanged() {
// 更新进度条值 Label 文本
this._redSliderLabel.string = `${this._redSlider.progress.toFixed(2)} | ${Math.round(255 * this._redSlider.progress)}`;
this._greenSliderLabel.string = `${this._greenSlider.progress.toFixed(2)} | ${Math.round(255 * this._greenSlider.progress)}`;
this._blueSliderLabel.string = `${this._blueSlider.progress.toFixed(2)} | ${Math.round(255 * this._blueSlider.progress)}`;
this._alphaSliderLabel.string = `${this._alphaSlider.progress.toFixed(2)} | ${Math.round(255 * this._alphaSlider.progress)}`;
this._lightWidthSliderLabel.string = `${this._lightWidthSlider.progress.toFixed(2)}`;
let angle = 180 * this._lightAngleSlider.progress;
this._lightAngleSliderLabel.string = `${this._lightAngleSlider.progress.toFixed(2)} | ${angle.toFixed(2)}`;
// 通知子节点更新材质
this._examplesParentNode.children.forEach(childNode => {
childNode.emit("on_property_change", <FlashLightUBO>{
lightColor: cc.color(
Math.round(255 * this._redSlider.progress),
Math.round(255 * this._greenSlider.progress),
Math.round(255 * this._blueSlider.progress),
Math.round(255 * this._alphaSlider.progress)
),
lightAngle: angle,
lightWidth: this._lightWidthSlider.progress,
enableGradient: this._enableGradientToggle.isChecked,
cropAlpha: this._cropAlphaToggle.isChecked,
enableFog: this._enableFogToggle.isChecked
});
});
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "6d3aff77-2683-4417-8960-2a5fd5d0757c",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,54 @@
const { ccclass, property } = cc._decorator;
@ccclass
export default class GaussianBlurV1EffectScene extends cc.Component {
private _blurSlider: cc.Slider = null;
private _blurSliderLabel: cc.Label = null;
private _examplesParentNode: cc.Node = null;
onLoad() {
cc.dynamicAtlasManager.enabled = false;
this._blurSlider = cc.find("Canvas/Content/Controller/BlurSlider/Slider").getComponent(cc.Slider);
this._blurSliderLabel = cc.find("Canvas/Content/Controller/BlurSlider/ValueLabel").getComponent(cc.Label);
this._examplesParentNode = cc.find("Canvas/Content/Examples");
}
onEnable() {
this._blurSlider.node.on("slide", this._onSliderChanged, this);
}
onDisable() {
this._blurSlider.node.off("slide", this._onSliderChanged, this);
}
start() {
this._onSliderChanged();
}
private _onSliderChanged() {
this._blurSliderLabel.string = `${this._blurSlider.progress.toFixed(2)}`;
// 更新材质
this._updateRenderComponentMaterial({});
}
/**
* 更新渲染组件的材质
*
* 1. 获取材质
* 2. 给材质的 unitform 变量赋值
* 3. 重新将材质赋值回去
*/
private _updateRenderComponentMaterial(param: {}) {
this._examplesParentNode.children.forEach(childNode => {
childNode.getComponents(cc.RenderComponent).forEach(renderComponent => {
let material: cc.Material = renderComponent.getMaterial(0);
material.setProperty("textureSize", cc.v2(childNode.width, childNode.height));
renderComponent.setMaterial(0, material);
});
});
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "f460d8cf-51f7-4476-ba59-170dec68f562",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,83 @@
const { ccclass, property } = cc._decorator;
@ccclass
export default class PointLightCtrlComponent extends cc.Component {
private _pointLightUBO: PointLightUBO = new PointLightUBO();
onEnable() {
this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
this.node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this);
this.node.on("on_property_change", this._onPropertyChange, this);
}
onDisable() {
this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
this.node.off(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this);
this.node.off("on_property_change", this._onPropertyChange, this);
}
private _onTouchStart(event: cc.Event.EventTouch) {
this._onTouchMove(event);
}
private _onTouchMove(event: cc.Event.EventTouch) {
let touchPointInWorldSpace = event.getLocation();
let touchPointInNodeSpace = this.node.convertToNodeSpaceAR(touchPointInWorldSpace);
// 将触摸点转换为OPENGL坐标系并归一化
// OpenGl 坐标系原点在左上角
this._pointLightUBO.centerPoint = cc.v2(
this.node.anchorX + touchPointInNodeSpace.x / this.node.width,
1 - (this.node.anchorY + touchPointInNodeSpace.y / this.node.height)
);
this._updateMaterial();
}
private _onPropertyChange(pointLightUBO: PointLightUBO) {
this._pointLightUBO.centerColor = pointLightUBO.centerColor;
this._pointLightUBO.radius = pointLightUBO.radius;
this._pointLightUBO.cropAlpha = pointLightUBO.cropAlpha;
this._pointLightUBO.enableFog = pointLightUBO.enableFog;
this._updateMaterial();
}
private _updateMaterial() {
this.getComponents(cc.RenderComponent).forEach(renderComponent => {
let material: cc.Material = renderComponent.getMaterial(0);
material.setProperty("centerColor", this._pointLightUBO.centerColor);
material.setProperty("centerPoint", this._pointLightUBO.centerPoint);
material.setProperty("radius", this._pointLightUBO.radius);
material.setProperty("cropAlpha", this._pointLightUBO.cropAlpha);
material.setProperty("enableFog", this._pointLightUBO.enableFog);
renderComponent.setMaterial(0, material);
});
}
}
export class PointLightUBO {
/**
* 中心点颜色
*/
centerColor: cc.Color = cc.Color.YELLOW;
/**
* 中心点坐标 ([0.0, 1.0], [0.0, 1.0])
*/
centerPoint: cc.Vec2 = cc.v2(0.5, 0.5);
/**
* 扩散半径 [0.0, 1.0]
*/
radius: number = 0.5;
/**
* 是否裁剪掉透明区域上的点光
*/
cropAlpha: boolean = true;
/**
* 是否开启战争迷雾效果
*/
enableFog: boolean = false;
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "ababac41-a736-4cbf-ad03-248962dd06e7",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,94 @@
import PointLightCtrlComponent, { PointLightUBO } from "./PointLightCtrlComponent";
const { ccclass, property } = cc._decorator;
@ccclass
export default class PointLightEffectScene extends cc.Component {
private _redSlider: cc.Slider = null;
private _redSliderLabel: cc.Label = null;
private _greenSlider: cc.Slider = null;
private _greenSliderLabel: cc.Label = null;
private _blueSlider: cc.Slider = null;
private _blueSliderLabel: cc.Label = null;
private _alphaSlider: cc.Slider = null;
private _alphaSliderLabel: cc.Label = null;
private _radiuSlider: cc.Slider = null;
private _radiuSliderLabel: cc.Label = null;
private _cropAlphaToggle: cc.Toggle = null;
private _enableFogToggle: cc.Toggle = null;
private _examplesParentNode: cc.Node = null;
onLoad() {
cc.dynamicAtlasManager.enabled = false;
this._redSlider = cc.find("Canvas/Content/Controller/ColorRedSlider/Slider").getComponent(cc.Slider);
this._redSliderLabel = cc.find("Canvas/Content/Controller/ColorRedSlider/ValueLabel").getComponent(cc.Label);
this._greenSlider = cc.find("Canvas/Content/Controller/ColorGreenSlider/Slider").getComponent(cc.Slider);
this._greenSliderLabel = cc.find("Canvas/Content/Controller/ColorGreenSlider/ValueLabel").getComponent(cc.Label);
this._blueSlider = cc.find("Canvas/Content/Controller/ColorBlueSlider/Slider").getComponent(cc.Slider);
this._blueSliderLabel = cc.find("Canvas/Content/Controller/ColorBlueSlider/ValueLabel").getComponent(cc.Label);
this._alphaSlider = cc.find("Canvas/Content/Controller/ColorAlphaSlider/Slider").getComponent(cc.Slider);
this._alphaSliderLabel = cc.find("Canvas/Content/Controller/ColorAlphaSlider/ValueLabel").getComponent(cc.Label);
this._radiuSlider = cc.find("Canvas/Content/Controller/RadiuSlider/Slider").getComponent(cc.Slider);
this._radiuSliderLabel = cc.find("Canvas/Content/Controller/RadiuSlider/ValueLabel").getComponent(cc.Label);
this._cropAlphaToggle = cc.find("Canvas/Content/Controller/CropAlphaToggle/Toggle").getComponent(cc.Toggle);
this._enableFogToggle = cc.find("Canvas/Content/Controller/EnableFogToggle/Toggle").getComponent(cc.Toggle);
// 代码添加控制脚本
this._examplesParentNode = cc.find("Canvas/Content/Examples");
this._examplesParentNode.children.forEach(childNode => {
childNode.addComponent(PointLightCtrlComponent);
});
}
onEnable() {
this._redSlider.node.on("slide", this._onPropertyChanged, this);
this._greenSlider.node.on("slide", this._onPropertyChanged, this);
this._blueSlider.node.on("slide", this._onPropertyChanged, this);
this._alphaSlider.node.on("slide", this._onPropertyChanged, this);
this._radiuSlider.node.on("slide", this._onPropertyChanged, this);
this._cropAlphaToggle.node.on("toggle", this._onPropertyChanged, this);
this._enableFogToggle.node.on("toggle", this._onPropertyChanged, this);
}
onDisable() {
this._redSlider.node.off("slide", this._onPropertyChanged, this);
this._greenSlider.node.off("slide", this._onPropertyChanged, this);
this._blueSlider.node.off("slide", this._onPropertyChanged, this);
this._alphaSlider.node.off("slide", this._onPropertyChanged, this);
this._radiuSlider.node.off("slide", this._onPropertyChanged, this);
this._cropAlphaToggle.node.off("toggle", this._onPropertyChanged, this);
this._enableFogToggle.node.off("toggle", this._onPropertyChanged, this);
}
start() {
this._onPropertyChanged();
}
private _onPropertyChanged() {
// 更新进度条值 Label 文本
this._redSliderLabel.string = `${this._redSlider.progress.toFixed(2)} | ${Math.round(255 * this._redSlider.progress)}`;
this._greenSliderLabel.string = `${this._greenSlider.progress.toFixed(2)} | ${Math.round(255 * this._greenSlider.progress)}`;
this._blueSliderLabel.string = `${this._blueSlider.progress.toFixed(2)} | ${Math.round(255 * this._blueSlider.progress)}`;
this._alphaSliderLabel.string = `${this._alphaSlider.progress.toFixed(2)} | ${Math.round(255 * this._alphaSlider.progress)}`;
this._radiuSliderLabel.string = `${this._radiuSlider.progress.toFixed(2)}`;
// 通知子节点更新材质
this._examplesParentNode.children.forEach(childNode => {
childNode.emit("on_property_change", <PointLightUBO>{
centerColor: cc.color(
Math.round(255 * this._redSlider.progress),
Math.round(255 * this._greenSlider.progress),
Math.round(255 * this._blueSlider.progress),
Math.round(255 * this._alphaSlider.progress)
),
radius: this._radiuSlider.progress,
cropAlpha: this._cropAlphaToggle.isChecked,
enableFog: this._enableFogToggle.isChecked
});
});
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "3a212efa-8118-4c79-a0f7-a51f36262ff7",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -1,9 +1,9 @@
const { ccclass, property } = cc._decorator;
@ccclass
export default class RoundCornerCropEffectScene extends cc.Component {
private _roundCornerRadiuSlider: cc.Slider = null;
private _roundCornerRadiuLabel: cc.Label = null;
export default class RoundCornerCropV1EffectScene extends cc.Component {
private _radiuSlider: cc.Slider = null;
private _radiuLabel: cc.Label = null;
private _examplesParentNode: cc.Node = null;
@@ -11,18 +11,18 @@ export default class RoundCornerCropEffectScene extends cc.Component {
// 关闭动态合图
cc.dynamicAtlasManager.enabled = false;
this._roundCornerRadiuSlider = cc.find("Canvas/Content/Sliders/RoundCornerRadiusSlider/Slider").getComponent(cc.Slider);
this._roundCornerRadiuLabel = cc.find("Canvas/Content/Sliders/RoundCornerRadiusSlider/ValueLabel").getComponent(cc.Label);
this._radiuSlider = cc.find("Canvas/Content/Controller/RadiusSlider/Slider").getComponent(cc.Slider);
this._radiuLabel = cc.find("Canvas/Content/Controller/RadiusSlider/ValueLabel").getComponent(cc.Label);
this._examplesParentNode = cc.find("Canvas/Content/Examples");
}
onEnable() {
this._roundCornerRadiuSlider.node.on("slide", this._onSliderChanged, this);
this._radiuSlider.node.on("slide", this._onSliderChanged, this);
}
onDisable() {
this._roundCornerRadiuSlider.node.off("slide", this._onSliderChanged, this);
this._radiuSlider.node.off("slide", this._onSliderChanged, this);
}
start() {
@@ -30,11 +30,11 @@ export default class RoundCornerCropEffectScene extends cc.Component {
}
private _onSliderChanged() {
this._roundCornerRadiuLabel.string = `${this._roundCornerRadiuSlider.progress.toFixed(2)}`;
this._radiuLabel.string = `${this._radiuSlider.progress.toFixed(2)}`;
// 更新材质
this._updateRenderComponentMaterial({
roundCornerRadius: this._roundCornerRadiuSlider.progress
radius: this._radiuSlider.progress
});
}
@@ -49,12 +49,12 @@ export default class RoundCornerCropEffectScene extends cc.Component {
/**
* [0.0, 0.5] 0.5
*/
roundCornerRadius: number;
radius: number;
}) {
this._examplesParentNode.children.forEach(childNode => {
childNode.getComponents(cc.RenderComponent).forEach(renderComponent => {
let material: cc.Material = renderComponent.getMaterial(0);
material.setProperty("roundCornerRadius", param.roundCornerRadius);
material.setProperty("radius", param.radius);
renderComponent.setMaterial(0, material);
});
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "d27658c5-a966-4e50-a162-09c7af01579e",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,80 @@
const { ccclass, property } = cc._decorator;
@ccclass
export default class RoundCornerCropV2EffectScene extends cc.Component {
private _radiuSlider: cc.Slider = null;
private _radiuLabel: cc.Label = null;
private _examplesParentNode: cc.Node = null;
onLoad() {
// 关闭动态合图
cc.dynamicAtlasManager.enabled = false;
this._radiuSlider = cc.find("Canvas/Content/Controller/RadiusSlider/Slider").getComponent(cc.Slider);
this._radiuLabel = cc.find("Canvas/Content/Controller/RadiusSlider/ValueLabel").getComponent(cc.Label);
this._examplesParentNode = cc.find("Canvas/Content/Examples");
}
onEnable() {
this._radiuSlider.node.on("slide", this._onSliderChanged, this);
}
onDisable() {
this._radiuSlider.node.off("slide", this._onSliderChanged, this);
}
start() {
this._onSliderChanged();
}
private _onSliderChanged() {
// 计算半径px
let radiusInPx = Math.floor(100 * this._radiuSlider.progress);
this._radiuLabel.string = radiusInPx + "";
// 更新材质
this._updateRenderComponentMaterial({
radiusInPx: radiusInPx
});
}
/**
* 更新渲染组件的材质
*
* 1. 获取材质
* 2. 给材质的 unitform 变量赋值
* 3. 重新将材质赋值回去
*/
private _updateRenderComponentMaterial(param: {
/**
* 圆角半径px
*/
radiusInPx: number;
}) {
this._examplesParentNode.children.forEach(childNode => {
childNode.getComponents(cc.RenderComponent).forEach(renderComponent => {
// 计算半径px分别相对于纹理宽高的比例也叫归一化
let xRadiux = param.radiusInPx / childNode.width;
// 约束范围在区间 [0.0, 0.5]
xRadiux = xRadiux >= 0.5 ? 0.5 : xRadiux;
let yRadius = param.radiusInPx / childNode.height;
yRadius = yRadius >= 0.5 ? 0.5 : yRadius;
if (childNode.name === "Rectangle1") cc.log(`${childNode.name} : (${xRadiux}, ${yRadius})`);
// 更新材质
let material: cc.Material = renderComponent.getMaterial(0);
// 圆角x轴半径长度相对于纹理宽度[0.0, 0.5]
material.setProperty("xRadius", xRadiux);
// 圆角y轴半径长度相对于纹理高度[0.0, 0.5]
material.setProperty("yRadius", yRadius);
renderComponent.setMaterial(0, material);
});
});
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "24bbe7ba-5d1e-42d9-b2dd-f219fef90367",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@@ -0,0 +1,34 @@
{
"ver": "2.3.3",
"uuid": "c879710d-0419-46be-bf96-92ee1ca52324",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"platformSettings": {},
"subMetas": {
"gaussian_blur": {
"ver": "1.0.4",
"uuid": "91f28953-0d5f-4379-9ae6-f3f6afb3241c",
"rawTextureUuid": "c879710d-0419-46be-bf96-92ee1ca52324",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 317,
"height": 178,
"rawWidth": 317,
"rawHeight": 178,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

@@ -1,6 +1,6 @@
{
"engine": "cocos2d-html5",
"packages": "packages",
"version": "2.2.1",
"version": "2.2.2",
"id": "7e74e9ed-5c28-4e81-ae0e-5a67f548022c"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB