diff --git a/assets/effects/sprite-round-corner-crop.effect b/assets/effects/sprite-round-corner-crop.effect new file mode 100644 index 0000000..e894a2a --- /dev/null +++ b/assets/effects/sprite-round-corner-crop.effect @@ -0,0 +1,144 @@ +// 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 + +CCEffect %{ + techniques: + - passes: + - vert: vs + frag: fs + blendState: + targets: + - blend: true + rasterizerState: + cullMode: none + properties: + texture: { value: white } + alphaThreshold: { value: 0.5 } + # 圆角半径 + roundCornerRadius: { + value: 0.1, + inspector: { + tooltip: "圆角半径", + 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 { + // 圆角半径 + float roundCornerRadius; + } + #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] + float radius = clamp(0.0, 0.5, roundCornerRadius); + + // 将纹理uv往左下偏移,实现偏移后的纹理中心点在 OpenGL 坐标系的原点 + 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); + + // 区分 以第一象限圆角所在圆心坐标为原点的坐标的四个象限 + // + // 第一象限 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 new file mode 100644 index 0000000..4f9bb47 --- /dev/null +++ b/assets/effects/sprite-round-corner-crop.effect.meta @@ -0,0 +1,17 @@ +{ + "ver": "1.0.23", + "uuid": "a4afedba-5234-44d7-9031-cba83051d521", + "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 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\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" + } + } + ], + "subMetas": {} +} \ No newline at end of file diff --git a/assets/materials/sprite-round-corner-crop.mtl b/assets/materials/sprite-round-corner-crop.mtl new file mode 100644 index 0000000..a1346a7 --- /dev/null +++ b/assets/materials/sprite-round-corner-crop.mtl @@ -0,0 +1,16 @@ +{ + "__type__": "cc.Material", + "_name": "", + "_objFlags": 0, + "_native": "", + "_effectAsset": { + "__uuid__": "a4afedba-5234-44d7-9031-cba83051d521" + }, + "_defines": { + "USE_TEXTURE": true, + "ENABLE_ROUNDCORNER": true + }, + "_props": { + "roundCornerRadius": 0.1 + } +} \ No newline at end of file diff --git a/assets/materials/sprite-round-corner-crop.mtl.meta b/assets/materials/sprite-round-corner-crop.mtl.meta new file mode 100644 index 0000000..3c0bafe --- /dev/null +++ b/assets/materials/sprite-round-corner-crop.mtl.meta @@ -0,0 +1,6 @@ +{ + "ver": "1.0.2", + "uuid": "642c2d0e-7eb6-4d65-96f2-d6e0d0305310", + "dataAsSubAsset": null, + "subMetas": {} +} \ No newline at end of file diff --git a/assets/scenes/RoundCornerCropEffectScene.fire b/assets/scenes/RoundCornerCropEffectScene.fire new file mode 100755 index 0000000..4f320fb --- /dev/null +++ b/assets/scenes/RoundCornerCropEffectScene.fire @@ -0,0 +1,2159 @@ +[ + { + "__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__": 47 + }, + { + "__id__": 48 + } + ], + "_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, + 418.2902700278839, + 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__": 46 + } + ], + "_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": "Sliders", + "_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": "RoundCornerRadiusSlider", + "_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