// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd. CCEffect %{ techniques: - passes: - vert: sprite-vs:vert frag: circle-hole-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: alphaThreshold: { value: 0.5 } # 修复核心:只定义一组默认值 (4个float),避免 YAML 解析长度错误 # 实际使用时,请务必通过脚本 material.setProperty('circles', [...]) 传入完整数组 circles: { value: [0.5, 0.5, 0.1, 0.02] } holeCount: { value: 1 } globalEdgeSoftness: { value: 0.02 } maskColor: { value: [1, 1, 1, 1] } textureSize: { value: [300, 300] } }% CCProgram sprite-vs %{ precision highp float; #include #if USE_LOCAL #include #endif #if SAMPLE_FROM_RT #include #endif in vec3 a_position; in vec2 a_texCoord; in vec4 a_color; out vec4 color; out vec2 uv0; vec4 vert() { vec4 pos = vec4(a_position, 1); #if USE_LOCAL pos = cc_matWorld * pos; #endif #if USE_PIXEL_ALIGNMENT pos = cc_matView * pos; pos.xyz = floor(pos.xyz); pos = cc_matProj * pos; #else pos = cc_matViewProj * pos; #endif uv0 = a_texCoord; #if SAMPLE_FROM_RT CC_HANDLE_RT_SAMPLE_FLIP(uv0); #endif color = a_color; return pos; } }% CCProgram circle-hole-fs %{ precision highp float; #include #include in vec4 color; in vec2 uv0; #pragma builtin(local) layout(set = 2, binding = 12) uniform sampler2D cc_spriteTexture; uniform ufs { // 即使 properties 只定义了4个,这里声明 20 个也是安全的 // 只要脚本传入的数组长度 >= holeCount * 4 即可 vec4 circles[20]; vec4 maskColor; vec2 textureSize; float holeCount; float globalEdgeSoftness; }; float sdf_circle(vec2 uv, vec2 center, float r, float softness) { float dist = distance(uv, center); return smoothstep(r, r + softness, dist); } vec4 frag() { vec4 o = maskColor; #if USE_TEXTURE o *= texture(cc_spriteTexture, uv0); #endif o *= color; float holeMask = 1.0; int maxHoles = int(holeCount); if (maxHoles > 20) maxHoles = 20; if (maxHoles < 0) maxHoles = 0; for (int i = 0; i < 20; ++i) { if (i >= maxHoles) break; vec4 circle = circles[i]; if (circle.z <= 0.0) continue; vec2 center = circle.xy; // --- 开始修复椭圆问题 --- float aspect = textureSize.x / textureSize.y; if (aspect <= 0.0) aspect = 1.0; vec2 correctedUV = uv0; correctedUV.x *= aspect; vec2 correctedCenter = center; correctedCenter.x *= aspect; float refDim = textureSize.y; if (refDim <= 0.0) refDim = 1.0; float uvRadius = circle.z / refDim; float softness = circle.w > 0.0 ? circle.w : globalEdgeSoftness; float dist = distance(correctedUV, correctedCenter); float circleMask = smoothstep(uvRadius, uvRadius + softness, dist); // --- 结束修复 --- holeMask *= circleMask; } o.a *= holeMask; ALPHA_TEST(o); return o; } }%