shader_type spatial; render_mode depth_draw_always, cull_back; uniform sampler2D albedo_texture : source_color; uniform vec4 hat_color : source_color = vec4(1.0); uniform vec4 gloves_color : source_color = vec4(1.0); uniform vec4 cloth_color : source_color = vec4(1.0); uniform vec4 skin_color : source_color = vec4(1.0); uniform vec2 hat_uv_min = vec2(0.6, 0.1); uniform vec2 hat_uv_max = vec2(1.0, 0.5); uniform vec2 hat_uv_min2 = vec2(-1.0); uniform vec2 hat_uv_max2 = vec2(-1.0); uniform vec2 gloves_uv_min = vec2(0.6, 0.5); uniform vec2 gloves_uv_max = vec2(1.0, 0.7); uniform vec2 gloves_uv_min2 = vec2(-1.0); uniform vec2 gloves_uv_max2 = vec2(-1.0); uniform vec2 cloth_uv_min = vec2(0.0, 0.7); uniform vec2 cloth_uv_max = vec2(1.0, 1.0); uniform vec2 cloth_uv_min2 = vec2(-1.0); uniform vec2 cloth_uv_max2 = vec2(-1.0); uniform vec4 hat_match_color : source_color = vec4(0.0); uniform vec4 gloves_match_color : source_color = vec4(0.0); uniform vec4 cloth_match_color : source_color = vec4(0.0); uniform float color_tolerance = 0.05; uniform int highlight_part = -1; // -1: none, 0: hat, 1: gloves, 2: cloth, 3: skin uniform float alpha_scissor_threshold : hint_range(0.0, 1.0) = 0.5; uniform bool is_selected = false; instance uniform int mesh_category : hint_range(-1, 3) = -1; bool in_rect(vec2 uv, vec2 mi, vec2 ma) { if (mi.x < 0.0) return false; return uv.x >= mi.x && uv.x <= ma.x && uv.y >= mi.y && uv.y <= ma.y; } bool color_match(vec3 c1, vec3 c2) { if (length(c2) < 0.01) return false; // Ignore black/empty targets return distance(c1, c2) < color_tolerance; } void fragment() { vec4 tex = texture(albedo_texture, UV); if (tex.a < alpha_scissor_threshold) discard; vec3 final_color = tex.rgb; float emission_mult = 0.0; if (is_selected) emission_mult = 0.4; int cat = mesh_category; // If no manual mesh assignment, use UV Detection + Color Match (Magic Wand) if (cat == -1) { if (in_rect(UV, hat_uv_min, hat_uv_max) || in_rect(UV, hat_uv_min2, hat_uv_max2) || color_match(tex.rgb, hat_match_color.rgb)) cat = 0; else if (in_rect(UV, gloves_uv_min, gloves_uv_max) || in_rect(UV, gloves_uv_min2, gloves_uv_max2) || color_match(tex.rgb, gloves_match_color.rgb)) cat = 1; else if (in_rect(UV, cloth_uv_min, cloth_uv_max) || in_rect(UV, cloth_uv_min2, cloth_uv_max2) || color_match(tex.rgb, cloth_match_color.rgb)) cat = 2; else cat = 3; } if (cat == 0) { final_color *= hat_color.rgb; if (highlight_part == 0) emission_mult = 0.5; } else if (cat == 1) { final_color *= gloves_color.rgb; if (highlight_part == 1) emission_mult = 0.5; } else if (cat == 2) { final_color *= cloth_color.rgb; if (highlight_part == 2) emission_mult = 0.5; } else { final_color *= skin_color.rgb; if (highlight_part == 3) emission_mult = 0.5; } ALBEDO = final_color; EMISSION = final_color * emission_mult; ALPHA = tex.a; }