shader_type canvas_item; // sprite_texture 即为 Sprite2D 自身的纹理(内置:TEXTURE) // 外部参数:mask_texture(与 sprite_texture 高度相同,宽度 = width_ratio * sprite_width) // width_ratio < 1 为常量(运行时不变) // offset_ratio 会在物理帧中不断更新,控制 mask 在 sprite 上的水平起点(0 表示最左端,1 - width_ratio 表示最右端) uniform sampler2D mask_texture; uniform float modulate_a : hint_range(0.0, 1.0) = 1.0; // mask_texture.width / sprite_texture.width uniform float half_width_ratio : hint_range(0.1, 1.0) = 0.5; // mask_texture.width / sprite_texture.width uniform float offset_ratio : hint_range(0.01, 1.0) = 0.01; // mask 左边界起点在 sprite UV(0~1)中的比例 // 当 mask 的 alpha > 0.5(或你需要的阈值)时显示 sprite,对应区域 alpha = 原纹理 alpha,否则 alpha = 0。 uniform float alpha_threshold : hint_range(0.0, 1.0) = 0.5; void fragment() { // 基础 sprite 采样 vec4 sprite_col = texture(TEXTURE, UV); // 将 sprite 的 UV(0~1)映射到 mask 的 UV: // mask 横向只覆盖 [offset_ratio, offset_ratio + width_ratio] 的区间 // 在该区间内,线性映射到 mask 的 [0, 1] 横向。区间之外,直接视为 mask alpha = 0。 float u = UV.x; float v = UV.y; // 判断是否在 mask 的横向覆盖范围内 float left = offset_ratio - half_width_ratio; float right = offset_ratio + half_width_ratio; // 缩放到 mask 的 U 坐标(0~1) float mask_u = 0.5 * (u - left) / half_width_ratio; float mask_v = v; // 高度一致,直接使用同一 v 坐标(0~1) // 默认 mask alpha = 0 float mask_a = 0.0; // 仅在覆盖范围内采样 mask 纹理 if (u >= left && u <= right) { vec4 mask_col = texture(mask_texture, vec2(mask_u, mask_v)); mask_a = mask_col.a; } // 应用阈值或直接乘 alpha(两种方式任选其一) // 方式 A:阈值裁剪(更硬边) float visible = step(alpha_threshold, mask_a); // visible && white float col_rgb = step(alpha_threshold, visible * COLOR.a); // 输出:颜色保持原纹理(也可以乘 mask_a 做软边),alpha 由 visible 控制 // 如果你想要软边,替换为 sprite_col.a *= mask_a; vec4 out_col = sprite_col; out_col.rgb = vec3(col_rgb); // 纯黑手掌 out_col.a = visible * modulate_a; // 半透明的手掌 //out_col.a = visible * modulate_a * max(col_rgb, 0.2); // 可选:也让 RGB 乘以 visible,避免半透明像素渗色 //out_col.rgb *= visible; COLOR = out_col; }