xiandie/scene/ground/script/c04/s09_除晦游戏反色效果.gdshader
2025-09-17 22:41:06 +08:00

62 lines
2.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}