xiandie/scene/ground/script/c04/s09_除晦游戏反色效果.gdshader

62 lines
2.6 KiB
Plaintext
Raw Normal View History

2025-09-17 14:41:06 +00:00
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 UV0~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 的 UV0~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;
}