用红、绿、蓝、黑分别在遮罩图上标识不同的部分,以便在Shader里进行着色处理:
Shader "Custom/ColorAdjustmentWithMaskHSVOptimized"
{
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_MaskTex ("Mask Texture", 2D) = "white" {}
_HueR ("Red Hue", Range(-0.5, 0.5)) = 0
_SaturationR ("Red Saturation", Range(0, 2)) = 1
_ValueR ("Red Value", Range(0, 2)) = 1
_HueG ("Green Hue", Range(-0.5, 0.5)) = 0
_SaturationG ("Green Saturation", Range(0, 2)) = 1
_ValueG ("Green Value", Range(0, 2)) = 1
_HueB ("Blue Hue", Range(-0.5, 0.5)) = 0
_SaturationB ("Blue Saturation", Range(0, 2)) = 1
_ValueB ("Blue Value", Range(0, 2)) = 1
}
SubShader
{
Tags
{
"RenderType"="Opaque"
}
LOD 200
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _MaskTex;
float _HueR, _SaturationR, _ValueR;
float _HueG, _SaturationG, _ValueG;
float _HueB, _SaturationB, _ValueB;
float3 rgb2hsv(float3 c)
{
// RGB 转 HSV
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
float3 hsv2rgb(float3 c)
{
// HSV 转 RGB
c = float3(c.x, clamp(c.yz, 0.0, 1.0));
float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
fixed4 adjustColor(fixed4 color, float H, float S, float V)
{
float3 hsv = rgb2hsv(color.rgb);
hsv.x += H;
hsv.y *= S;
hsv.z *= V;
return fixed4(hsv2rgb(hsv), color.a);
}
fixed3 adjustColorSimple(fixed3 hsv, float H, float S, float V)
{
hsv.x += H;
hsv.y *= S;
hsv.z *= V;
return hsv2rgb(hsv);
}
struct appdata_t
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 mainColor = tex2D(_MainTex, i.uv);
fixed4 maskColor = tex2D(_MaskTex, i.uv);
// 使用直接比较判断掩码颜色是否为黑色
float isBlackMask = step(1.0, maskColor.r + maskColor.g + maskColor.b);
// 调整颜色并组合
float3 hsvColor = rgb2hsv(mainColor.rgb);
fixed3 finalColor =
adjustColorSimple(hsvColor, _HueR, _SaturationR, _ValueR) * maskColor.r +
adjustColorSimple(hsvColor, _HueG, _SaturationG, _ValueG) * maskColor.g +
adjustColorSimple(hsvColor, _HueB, _SaturationB, _ValueB) * maskColor.b;
// 确保颜色在 [0, 1] 范围内
finalColor.rgb = clamp(finalColor.rgb, 0.0, 1.0);
// 如果是黑色掩码,返回原色
return lerp(mainColor, float4(finalColor, mainColor.a), isBlackMask);
}
ENDCG
}
}
FallBack "Diffuse"
}
本来想用PhotoShop的HSL调色方案的,折腾半天没搞定,就用HSV了。
其实A通道也可以用上,不过目前3个已经够了,先保留吧。
这个也可以用在Spine上,保持相同的图集布局即可,没了。