修复玩家脸部
This commit is contained in:
@@ -1,23 +1,23 @@
|
||||
shader_type spatial;
|
||||
// 全身 shader:body_mesh 只有一个材质 mat_body —— 身体底色照常取它的 BaseColor,
|
||||
// 脸部不再换材质,只在这一个 shader 里把表情和手绘叠到指定 UV 矩形上。
|
||||
// 脸和周围走的是同一套材质、同一套光照,所以不会再出现独立面片的色块边界。
|
||||
// 全身 shader:body_mesh 只有一个材质 mat_body —— 身体底色照常取它的 BaseColor。
|
||||
// 脸不再靠 UV 矩形,而是「贴在身体正面上的一块贴花」:用**模型本地坐标**的 (x, y) 定位,
|
||||
// 再用「法线朝前的程度」当遮罩。
|
||||
// 这样它和 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 行在上边,所以默认要翻)
|
||||
// 中心点是**模型本地坐标**(和 mesh 顶点同一个空间,模型整体大约 x -3~3、y -3~3)。
|
||||
// 想往下挪就减小 .y,往左挪就减小 .x。
|
||||
uniform vec2 face_center = vec2(0.0, 0.6);
|
||||
// 表情大小:.x 是左右宽度,.y 是上下高度
|
||||
uniform vec2 face_size = vec2(4.0, 4.0);
|
||||
// 只在身体正面出现:朝**模型本地 -Z**(模型自己的正面)的那面才画。
|
||||
// 调大就只留最正面的一小块,调小会往侧面包过去。
|
||||
uniform float face_front_edge : hint_range(0.0, 1.0) = 0.0;
|
||||
// 上下颠倒了就改成 false
|
||||
uniform bool face_flip_y = true;
|
||||
// ====================================================
|
||||
//
|
||||
// 中心 ± 半个大小必须整个落在上面那段 UV 孤岛里,否则表情会糊到肚子 / 背上去。
|
||||
|
||||
uniform sampler2D body_tex : source_color, filter_linear, repeat_disable,
|
||||
hint_default_white;
|
||||
@@ -34,17 +34,33 @@ uniform vec2 base_uv_size = vec2(1.0, 1.0);
|
||||
uniform sampler2D paint_tex : source_color, filter_linear, repeat_disable,
|
||||
hint_default_transparent;
|
||||
|
||||
// 贴花要用「模型本地坐标」,而 fragment 里拿不到,所以从顶点阶段传过来
|
||||
varying vec3 object_position;
|
||||
varying vec3 object_normal;
|
||||
|
||||
void vertex() {
|
||||
object_position = VERTEX;
|
||||
object_normal = NORMAL;
|
||||
}
|
||||
|
||||
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;
|
||||
vec2 face_uv = (object_position.xy - (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)
|
||||
float inside = step(0.0, face_uv.x) * step(face_uv.x, 1.0)
|
||||
* step(0.0, face_uv.y) * step(face_uv.y, 1.0);
|
||||
// 背面的点 (x, y) 和正面一样,也会落进矩形,所以要再按「朝不朝前」筛一遍。
|
||||
// 注意模型自己的正面是**本地 -Z**(预览和玩家场景里那层 Transform 都把它转了 180°),
|
||||
// 所以这里取 -normal.z;写成 +normal.z 表情就会跑到背上。
|
||||
float front = smoothstep(face_front_edge, face_front_edge + 0.3,
|
||||
normalize(object_normal).z);
|
||||
float mask = inside * front;
|
||||
|
||||
vec4 base = texture(base_tex, base_uv_min + face_uv * base_uv_size);
|
||||
vec4 paint = texture(paint_tex, face_uv);
|
||||
// 透明处保持身体底色 —— 所以脸和周围不可能出现底色差
|
||||
|
||||
Reference in New Issue
Block a user