Files
agame/character/player/face/face_paint.gdshader
T
2026-10-03 05:40:26 +08:00

58 lines
2.9 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 spatial;
// 全身 shader:body_mesh 只有一个材质 mat_body —— 身体底色照常取它的 BaseColor,
// 脸部不再换材质,只在这一个 shader 里把表情和手绘叠到指定 UV 矩形上。
// 脸和周围走的是同一套材质、同一套光照,所以不会再出现独立面片的色块边界。
//
// 贴图 alpha 只代表「墨线覆盖率」,绝不写进空间 ALPHA —— body_mesh 的面片必须保持不透明。
// ================= 调表情就改这一段 =================
// 头部那一段 UV 孤岛的实测范围:u 0.695~0.996(左右),v 0.682~0.996(上下,v 越大越靠头顶)。
// 下面三个值就是「表情画在哪 / 多大 / 正不正」,FaceRig 不会覆盖它们,改完存盘即可。
//
// 表情中心点:**想往下挪就减小 .y**,往左挪就减小 .x
uniform vec2 face_center = vec2(0.8455, 0.639);
// 表情大小:.x 是左右宽度,.y 是上下高度(想只盖住半张脸就把 .y 改小)
uniform vec2 face_size = vec2(0.301, 0.314);
// 上下颠倒了就改成 false(头部 UV 的 v 朝上、贴图第 0 行在上边,所以默认要翻)
uniform bool face_flip_y = true;
// ====================================================
//
// 中心 ± 半个大小必须整个落在上面那段 UV 孤岛里,否则表情会糊到肚子 / 背上去。
uniform sampler2D body_tex : source_color, filter_linear, repeat_disable,
hint_default_white;
uniform vec4 body_tint : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform float surface_roughness : hint_range(0.0, 1.0) = 0.65;
uniform float surface_metallic : hint_range(0.0, 1.0) = 0.0;
// 表情底图:内置表情是保留原排布、已去底的透明图集;本地表情是整张透明 PNG。
uniform sampler2D base_tex : source_color, filter_linear, repeat_disable,
hint_default_transparent;
uniform vec2 base_uv_min = vec2(0.0, 0.0);
uniform vec2 base_uv_size = vec2(1.0, 1.0);
// 玩家笔画层(透明底)
uniform sampler2D paint_tex : source_color, filter_linear, repeat_disable,
hint_default_transparent;
void fragment() {
// 全身底色都来自 mat_body 的 BaseColor,表情只是盖在脸上
vec3 albedo = texture(body_tex, UV).rgb * body_tint.rgb;
vec2 face_uv = (UV - (face_center - face_size * 0.5)) / face_size;
if (face_flip_y) {
face_uv.y = 1.0 - face_uv.y;
}
// 用 step 而不是 if:采样留在统一控制流里,免得 mipmap 的导数在分支里未定义
float mask = step(0.0, face_uv.x) * step(face_uv.x, 1.0)
* step(0.0, face_uv.y) * step(face_uv.y, 1.0);
vec4 base = texture(base_tex, base_uv_min + face_uv * base_uv_size);
vec4 paint = texture(paint_tex, face_uv);
// 透明处保持身体底色 —— 所以脸和周围不可能出现底色差
albedo = mix(albedo, base.rgb, base.a * mask);
albedo = mix(albedo, paint.rgb, paint.a * mask);
ALBEDO = albedo;
ROUGHNESS = surface_roughness;
METALLIC = surface_metallic;
}