62 lines
2.6 KiB
Plaintext
62 lines
2.6 KiB
Plaintext
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;
|
||
} |