From c64f1ab1443f33c2ed6e37bf9ce30db747b15f0f Mon Sep 17 00:00:00 2001 From: caizhitao Date: Thu, 16 Jan 2020 22:59:41 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E5=8A=A0=E5=85=A5v2=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=9C=86=E8=A7=92=E8=A3=81=E5=89=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sprite-round-corner-crop-v2.effect | 167 ++++++++++++++++++ .../sprite-round-corner-crop-v2.effect.meta | 17 ++ 2 files changed, 184 insertions(+) create mode 100644 assets/effects/sprite-round-corner-crop-v2.effect create mode 100644 assets/effects/sprite-round-corner-crop-v2.effect.meta diff --git a/assets/effects/sprite-round-corner-crop-v2.effect b/assets/effects/sprite-round-corner-crop-v2.effect new file mode 100644 index 0000000..8c59f66 --- /dev/null +++ b/assets/effects/sprite-round-corner-crop-v2.effect @@ -0,0 +1,167 @@ +// 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.1026, + inspector: { + tooltip: "圆角x轴半径长度(相对于纹理宽度)", + range: [0.0, 0.5] + } + } + + # 圆角y轴半径长度(相对于纹理高度) + yRadius: { + value: 0.0741, + inspector: { + tooltip: "圆角x轴半径长度(相对于纹理高度)", + range: [0.0, 0.5] + } + } +}% + + +CCProgram vs %{ + precision highp float; + + #include + #include + + 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 + + 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(max(xRadius, yRadius), 2.0) + pow(ry, 2.0) / pow(min(xRadius, yRadius), 2.0)); + + // mx * my = 0 时,代表非椭圆角区域,alpha 值为1,代表完全采用原始纹理的透明度 + // mx * my = 1 时,代表椭圆角所在矩形区域 + // isOutOfEllipse: + // 当点在椭圆外部时,此值为1,导致 alpha 最终值为0.0,即表示不显示椭圆外部的像素 + // 当点在椭圆内部时,此值为0,导致 alpha 最终值为1.0,即表示显示椭圆内部的像素 + float alpha = 1.0 - mx * my * isOutOfEllipse; + o = vec4(o.rgb, o.a * alpha); + #endif + gl_FragColor = o; + } +}% diff --git a/assets/effects/sprite-round-corner-crop-v2.effect.meta b/assets/effects/sprite-round-corner-crop-v2.effect.meta new file mode 100644 index 0000000..815dafb --- /dev/null +++ b/assets/effects/sprite-round-corner-crop-v2.effect.meta @@ -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(max(xRadius, yRadius), 2.0) + pow(ry, 2.0) / pow(min(xRadius, yRadius), 2.0));\n\n float alpha = 1.0 - mx * my * isOutOfEllipse;\n o = vec4(o.rgb, o.a * alpha);\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(max(xRadius, yRadius), 2.0) + pow(ry, 2.0) / pow(min(xRadius, yRadius), 2.0));\n\n float alpha = 1.0 - mx * my * isOutOfEllipse;\n o = vec4(o.rgb, o.a * alpha);\n #endif\n gl_FragColor = o;\n}\n" + } + } + ], + "subMetas": {} +} \ No newline at end of file From bfe61e6494541c5961c64c154496993ce4a52c65 Mon Sep 17 00:00:00 2001 From: caizhitao Date: Thu, 16 Jan 2020 23:05:32 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=9C=86=E8=A7=92?= =?UTF-8?q?=E8=A3=81=E5=89=AAdemo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ect => sprite-round-corner-crop-v1.effect} | 28 +- ...> sprite-round-corner-crop-v1.effect.meta} | 4 +- .../sprite-round-corner-crop-v2.effect | 2 + ...op.mtl => sprite-round-corner-crop-v1.mtl} | 4 +- ...a => sprite-round-corner-crop-v1.mtl.meta} | 0 .../materials/sprite-round-corner-crop-v2.mtl | 14 + .../sprite-round-corner-crop-v2.mtl.meta | 6 + .../scenes/RoundCornerCropV1EffectScene.fire | 1868 +++++++++++++++++ ...=> RoundCornerCropV1EffectScene.fire.meta} | 0 ...fire => RoundCornerCropV2EffectScene.fire} | 198 +- .../RoundCornerCropV2EffectScene.fire.meta | 7 + ...ene.ts => RoundCornerCropV1EffectScene.ts} | 20 +- ...a => RoundCornerCropV1EffectScene.ts.meta} | 2 +- 13 files changed, 2025 insertions(+), 128 deletions(-) rename assets/effects/{sprite-round-corner-crop.effect => sprite-round-corner-crop-v1.effect} (79%) rename assets/effects/{sprite-round-corner-crop.effect.meta => sprite-round-corner-crop-v1.effect.meta} (60%) rename assets/materials/{sprite-round-corner-crop.mtl => sprite-round-corner-crop-v1.mtl} (83%) rename assets/materials/{sprite-round-corner-crop.mtl.meta => sprite-round-corner-crop-v1.mtl.meta} (100%) create mode 100644 assets/materials/sprite-round-corner-crop-v2.mtl create mode 100644 assets/materials/sprite-round-corner-crop-v2.mtl.meta create mode 100755 assets/scenes/RoundCornerCropV1EffectScene.fire rename assets/scenes/{RoundCornerCropEffectScene.fire.meta => RoundCornerCropV1EffectScene.fire.meta} (100%) rename assets/scenes/{RoundCornerCropEffectScene.fire => RoundCornerCropV2EffectScene.fire} (99%) create mode 100644 assets/scenes/RoundCornerCropV2EffectScene.fire.meta rename assets/scripts/{RoundCornerCropEffectScene.ts => RoundCornerCropV1EffectScene.ts} (57%) rename assets/scripts/{RoundCornerCropEffectScene.ts.meta => RoundCornerCropV1EffectScene.ts.meta} (74%) diff --git a/assets/effects/sprite-round-corner-crop.effect b/assets/effects/sprite-round-corner-crop-v1.effect similarity index 79% rename from assets/effects/sprite-round-corner-crop.effect rename to assets/effects/sprite-round-corner-crop-v1.effect index 9b4b299..8a444a5 100644 --- a/assets/effects/sprite-round-corner-crop.effect +++ b/assets/effects/sprite-round-corner-crop-v1.effect @@ -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,7 +19,7 @@ CCEffect %{ texture: { value: white } alphaThreshold: { value: 0.5 } # 圆角半径 - roundCornerRadius: { + radius: { value: 0.1, inspector: { tooltip: "圆角半径", @@ -77,7 +79,7 @@ CCProgram fs %{ #if ENABLE_ROUNDCORNER uniform RoundCorner { // 圆角半径 - float roundCornerRadius; + float radius; } #endif @@ -97,7 +99,7 @@ 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往左上偏移,实现偏移后的坐标系原点在纹理中心 vec2 uv = v_uv0.xy - vec2(0.5, 0.5); @@ -106,8 +108,8 @@ CCProgram fs %{ // 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; diff --git a/assets/effects/sprite-round-corner-crop.effect.meta b/assets/effects/sprite-round-corner-crop-v1.effect.meta similarity index 60% rename from assets/effects/sprite-round-corner-crop.effect.meta rename to assets/effects/sprite-round-corner-crop-v1.effect.meta index 4f9bb47..3e3ff59 100644 --- a/assets/effects/sprite-round-corner-crop.effect.meta +++ b/assets/effects/sprite-round-corner-crop-v1.effect.meta @@ -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" } } ], diff --git a/assets/effects/sprite-round-corner-crop-v2.effect b/assets/effects/sprite-round-corner-crop-v2.effect index 8c59f66..bd6f330 100644 --- a/assets/effects/sprite-round-corner-crop-v2.effect +++ b/assets/effects/sprite-round-corner-crop-v2.effect @@ -1,5 +1,7 @@ // 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 diff --git a/assets/materials/sprite-round-corner-crop.mtl b/assets/materials/sprite-round-corner-crop-v1.mtl similarity index 83% rename from assets/materials/sprite-round-corner-crop.mtl rename to assets/materials/sprite-round-corner-crop-v1.mtl index a1346a7..279cad8 100644 --- a/assets/materials/sprite-round-corner-crop.mtl +++ b/assets/materials/sprite-round-corner-crop-v1.mtl @@ -10,7 +10,5 @@ "USE_TEXTURE": true, "ENABLE_ROUNDCORNER": true }, - "_props": { - "roundCornerRadius": 0.1 - } + "_props": {} } \ No newline at end of file diff --git a/assets/materials/sprite-round-corner-crop.mtl.meta b/assets/materials/sprite-round-corner-crop-v1.mtl.meta similarity index 100% rename from assets/materials/sprite-round-corner-crop.mtl.meta rename to assets/materials/sprite-round-corner-crop-v1.mtl.meta diff --git a/assets/materials/sprite-round-corner-crop-v2.mtl b/assets/materials/sprite-round-corner-crop-v2.mtl new file mode 100644 index 0000000..e8c7371 --- /dev/null +++ b/assets/materials/sprite-round-corner-crop-v2.mtl @@ -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": {} +} \ No newline at end of file diff --git a/assets/materials/sprite-round-corner-crop-v2.mtl.meta b/assets/materials/sprite-round-corner-crop-v2.mtl.meta new file mode 100644 index 0000000..c7d5f5d --- /dev/null +++ b/assets/materials/sprite-round-corner-crop-v2.mtl.meta @@ -0,0 +1,6 @@ +{ + "ver": "1.0.2", + "uuid": "a86e8864-5390-443f-b41b-b38e9d584c43", + "dataAsSubAsset": null, + "subMetas": {} +} \ No newline at end of file diff --git a/assets/scenes/RoundCornerCropV1EffectScene.fire b/assets/scenes/RoundCornerCropV1EffectScene.fire new file mode 100755 index 0000000..6b49e68 --- /dev/null +++ b/assets/scenes/RoundCornerCropV1EffectScene.fire @@ -0,0 +1,1868 @@ +[ + { + "__type__": "cc.SceneAsset", + "_name": "", + "_objFlags": 0, + "_native": "", + "scene": { + "__id__": 1 + } + }, + { + "__type__": "cc.Scene", + "_objFlags": 0, + "_parent": null, + "_children": [ + { + "__id__": 2 + } + ], + "_active": false, + "_components": [], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 0, + "height": 0 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_is3DNode": true, + "_groupIndex": 0, + "groupIndex": 0, + "autoReleaseAssets": false, + "_id": "6c351889-b6c8-409f-b36c-4263b06d0b23" + }, + { + "__type__": "cc.Node", + "_name": "Canvas", + "_objFlags": 0, + "_parent": { + "__id__": 1 + }, + "_children": [ + { + "__id__": 3 + }, + { + "__id__": 5 + } + ], + "_active": true, + "_components": [ + { + "__id__": 41 + }, + { + "__id__": 42 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 252, + "g": 252, + "b": 252, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 960, + "height": 640 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 480, + 320, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "a286bbGknJLZpRpxROV6M94" + }, + { + "__type__": "cc.Node", + "_name": "Main Camera", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 4 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 0, + "height": 0 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 0, + 0, + 351.60631393648214, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "fbL5wf1mhFa6PPZbeZvnZ9" + }, + { + "__type__": "cc.Camera", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 3 + }, + "_enabled": true, + "_cullingMask": 4294967295, + "_clearFlags": 7, + "_backgroundColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_depth": -1, + "_zoomRatio": 1, + "_targetTexture": null, + "_fov": 60, + "_orthoSize": 10, + "_nearClip": 1, + "_farClip": 4096, + "_ortho": true, + "_rect": { + "__type__": "cc.Rect", + "x": 0, + "y": 0, + "width": 1, + "height": 1 + }, + "_renderStages": 1, + "_alignWithScreen": true, + "_id": "adItdqNzZHbYUhDAmfCr9b" + }, + { + "__type__": "cc.Node", + "_name": "Content", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [ + { + "__id__": 6 + }, + { + "__id__": 9 + }, + { + "__id__": 29 + } + ], + "_active": true, + "_components": [ + { + "__id__": 40 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 960, + "height": 640 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "faqYlnbttBCaJJgkn4Ntv/" + }, + { + "__type__": "cc.Node", + "_name": "Bg", + "_objFlags": 0, + "_parent": { + "__id__": 5 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 7 + }, + { + "__id__": 8 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 27, + "g": 38, + "b": 46, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 960, + "height": 640 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "e2e0crkOLxGrpMxpbC4iQg1" + }, + { + "__type__": "cc.Widget", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 6 + }, + "_enabled": true, + "alignMode": 0, + "_target": null, + "_alignFlags": 45, + "_left": 0, + "_right": 0, + "_top": 0, + "_bottom": 0, + "_verticalCenter": 0, + "_horizontalCenter": 0, + "_isAbsLeft": true, + "_isAbsRight": true, + "_isAbsTop": true, + "_isAbsBottom": true, + "_isAbsHorizontalCenter": true, + "_isAbsVerticalCenter": true, + "_originalWidth": 200, + "_originalHeight": 150, + "_id": "89IA6P0/5JEZERosKJJo6k" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 6 + }, + "_enabled": true, + "_materials": [ + { + "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" + } + ], + "_srcBlendFactor": 770, + "_dstBlendFactor": 771, + "_spriteFrame": { + "__uuid__": "410fb916-8721-4663-bab8-34397391ace7" + }, + "_type": 1, + "_sizeMode": 0, + "_fillType": 0, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_atlas": null, + "_id": "2azjUbJNxALLAfDZrJ8TV0" + }, + { + "__type__": "cc.Node", + "_name": "Controller", + "_objFlags": 0, + "_parent": { + "__id__": 5 + }, + "_children": [ + { + "__id__": 10 + } + ], + "_active": true, + "_components": [ + { + "__id__": 27 + }, + { + "__id__": 28 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 576, + "height": 60 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 1 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + -192, + 320, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "d0PWmVX95D3LEcvBQBPDr+" + }, + { + "__type__": "cc.Node", + "_name": "RadiusSlider", + "_objFlags": 0, + "_parent": { + "__id__": 9 + }, + "_children": [ + { + "__id__": 11 + }, + { + "__id__": 14 + }, + { + "__id__": 23 + } + ], + "_active": true, + "_components": [ + { + "__id__": 26 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 576, + "height": 60 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 0, + -30, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "669o93+gJMWJFGUDKSDUJ7" + }, + { + "__type__": "cc.Node", + "_name": "SliderDescLabel", + "_objFlags": 0, + "_parent": { + "__id__": 10 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 12 + }, + { + "__id__": 13 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 144, + "height": 40 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 1, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + -144, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "d9MLgZpaFCEZu70E0LAUbn" + }, + { + "__type__": "cc.Label", + "_name": "SliderDescLabel