CCEffect %{ techniques: - passes: - vert: cover-vs:vert frag: cover-fs:frag depthStencilState: depthTest: false depthWrite: false blendState: targets: - blend: true blendSrc: src_alpha blendDst: one_minus_src_alpha blendDstAlpha: one_minus_src_alpha rasterizerState: cullMode: none properties: uvTransform: { value: [1, 1, 0.5, 0.5] } cornerRadii: { value: [20, 20, 20, 20], editor: { tooltip: "圆角半径(节点单位):x左上、y右上、z右下、w左下;0为直角" } } nodeInfo: { value: [207, 412, 1, 0], editor: { tooltip: "xy节点宽高(脚本同步),z边缘柔化宽度" } } nodeUVRowX: { value: [1, 0, 0, 0], editor: { visible: false } } nodeUVRowY: { value: [0, -1, 1, 0], editor: { visible: false } } }% CCProgram cover-vs %{ precision highp float; #include #if USE_LOCAL #include #endif in vec3 a_position; in vec2 a_texCoord; in vec4 a_color; out vec2 v_uv; out vec4 v_color; vec4 vert () { vec4 pos = vec4(a_position, 1.0); #if USE_LOCAL pos = cc_matWorld * pos; #endif v_uv = a_texCoord; v_color = a_color; return cc_matViewProj * pos; } }% CCProgram cover-fs %{ precision highp float; #include in vec2 v_uv; in vec4 v_color; #pragma builtin(local) layout(set = 2, binding = 11) uniform sampler2D cc_spriteTexture; uniform CoverParams { vec4 uvTransform; vec4 cornerRadii; vec4 nodeInfo; vec4 nodeUVRowX; vec4 nodeUVRowY; }; vec4 frag () { // Geometry stays inside the node rectangle; only the sampled region shrinks. vec2 uv = (v_uv - uvTransform.zw) * uvTransform.xy + uvTransform.zw; vec4 color = CCSampleWithAlphaSeparated(cc_spriteTexture, uv) * v_color; // Use the original, uncropped UV to recover node coordinates. The two // rows also account for SpriteFrames stored in a rotated atlas rectangle. vec3 sourceUV = vec3(v_uv, 1.0); vec2 nodeUV = vec2(dot(nodeUVRowX.xyz, sourceUV), dot(nodeUVRowY.xyz, sourceUV)); vec2 halfSize = max(nodeInfo.xy, vec2(0.001)) * 0.5; vec2 p = (nodeUV - 0.5) * nodeInfo.xy; float radius = p.y >= 0.0 ? (p.x < 0.0 ? cornerRadii.x : cornerRadii.y) : (p.x < 0.0 ? cornerRadii.w : cornerRadii.z); radius = clamp(radius, 0.0, min(halfSize.x, halfSize.y)); vec2 q = abs(p) - halfSize + vec2(radius); float distanceToEdge = length(max(q, vec2(0.0))) + min(max(q.x, q.y), 0.0) - radius; color.a *= 1.0 - smoothstep(-max(nodeInfo.z, 0.001), 0.0, distanceToEdge); return color; } }%