From 6ba48af6aa363c5f5af6631ee9ed93310c2588d3 Mon Sep 17 00:00:00 2001 From: caizhitao Date: Thu, 9 Jan 2020 10:47:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../effects/sprite-round-corner-crop.effect | 46 ++++++++++++++++--- .../sprite-round-corner-crop.effect.meta | 4 +- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/assets/effects/sprite-round-corner-crop.effect b/assets/effects/sprite-round-corner-crop.effect index 672793d..e894a2a 100644 --- a/assets/effects/sprite-round-corner-crop.effect +++ b/assets/effects/sprite-round-corner-crop.effect @@ -96,13 +96,47 @@ CCProgram fs %{ ALPHA_TEST(o); #if ENABLE_ROUNDCORNER + // 约束圆角半径范围在 [0.0, 0.5] + float radius = clamp(0.0, 0.5, roundCornerRadius); + + // 将纹理uv往左下偏移,实现偏移后的纹理中心点在 OpenGL 坐标系的原点 vec2 uv = v_uv0.xy - vec2(0.5, 0.5); - float rx = abs(uv.x) - (0.5 - roundCornerRadius); - float ry = abs(uv.y) - (0.5 - roundCornerRadius); - float mx = step(0.5 - roundCornerRadius, abs(uv.x)); - float my = step(0.5 - roundCornerRadius, abs(uv.y)); - float radius = length(vec2(rx, ry)); - float a = 1.0 - mx * my * step(roundCornerRadius, radius) * smoothstep(0., roundCornerRadius * 0.01, radius - roundCornerRadius); + + // 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); + + // 区分 以第一象限圆角所在圆心坐标为原点的坐标的四个象限 + // + // 第一象限 mx = 1, my = 1 + // 第二象限 mx = 0, my = 1 + // 第三象限 mx = 0, my = 0 + // 第四象限 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)); + + // 计算相对uv坐标到圆心的距离 + float len = length(vec2(rx, ry)); + + // mx * my = 0 时,代表非圆角区域,a 值为1,代表完全采用原始纹理的透明度 + // mx * my = 1 时,代表园所所在矩形区域 + // step(radius, len) 可以区分出圆角所在矩形区域的 圆角区域 和 非圆角区域 + // 其中圆角区域值为0,非圆角区域值为1 + // 当为圆角区域时,a 值为1,代表完全采用原始纹理透明度 + // 当为非圆角区域时,a 值为0,代表完全透明 + // 至此已经实现圆角裁剪 + // + // smoothstep(0., radius * 0.01, len - radius) 是用于抗锯齿优化 + // 原理:针对点在非圆角区域的情况,针对点在大于「圆半径一点点」地方的区域,进行平滑过渡,以实现抗锯齿 + // 其中, + // 「圆半径一点点」用 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); 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.effect.meta index eb8a892..4f9bb47 100644 --- a/assets/effects/sprite-round-corner-crop.effect.meta +++ b/assets/effects/sprite-round-corner-crop.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 vec2 uv = v_uv0.xy - vec2(0.5, 0.5);\n float rx = abs(uv.x) - (0.5 - roundCornerRadius);\n float ry = abs(uv.y) - (0.5 - roundCornerRadius);\n float mx = step(0.5 - roundCornerRadius, abs(uv.x));\n float my = step(0.5 - roundCornerRadius, abs(uv.y));\n float radius = length(vec2(rx, ry));\n float a = 1.0 - mx * my * step(roundCornerRadius, radius) * smoothstep(0., roundCornerRadius * 0.01, radius - roundCornerRadius);\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 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" }, "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 vec2 uv = v_uv0.xy - vec2(0.5, 0.5);\n float rx = abs(uv.x) - (0.5 - roundCornerRadius);\n float ry = abs(uv.y) - (0.5 - roundCornerRadius);\n float mx = step(0.5 - roundCornerRadius, abs(uv.x));\n float my = step(0.5 - roundCornerRadius, abs(uv.y));\n float radius = length(vec2(rx, ry));\n float a = 1.0 - mx * my * step(roundCornerRadius, radius) * smoothstep(0., roundCornerRadius * 0.01, radius - roundCornerRadius);\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 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" } } ],