前言
对于颜色值,
RGB
可能是我们接触最多的颜色模型,图像中的任何颜色都是由
红色(R)
、
绿色(G)
、
蓝色(B)
这三个通道合成的,这三种颜色可以组合成几乎所有的颜色。
然而,它并不直观,比如我随便说一个rgb值,你能猜到他是什么颜色吗?几乎不可能,所以,后面引入了
HSV
、
HSL
等颜色模型。
HSV
相对于
RGB
来说 是一种更加直观的颜色模型,
HSV
更加符合我们人类视觉。
HSL和HSV 概念:
HSL
即色相、饱和度、亮度(英语:Hue, Saturation, Lightness)。
HSV
即色相、饱和度、明度(英语:Hue, Saturation, Value),又称HSB,其中B即英语:Brightness。
-
色相(H)是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等。
-
饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。
-
明度(V),亮度(L),取0-100%
HSL和HSV色彩空间比较:
二者在数学上都是圆柱,但
HSV
在概念上可以被认为是颜色的倒圆锥体(黑点在下顶点,白色在上底面圆心);
HSL
在概念上表示了一个双圆锥体和圆球体(白色在上顶点,黑色在下顶点,最大横切面的圆心是半程灰色)。
HSV 和 RGB 之间的相互转换
以下函数由国外大神
Inigo Quilez
提供
https://www.shadertoy.com/view/MsS3Wc
HSB/HSV 转 RGB
// Official HSV to RGB conversion
vec3
hsv2rgb
(
in
vec3
c
)
{
vec3
rgb
=
clamp
(
abs
(
mod
(
c
.
x
*
6.0
+
vec3
(
0.0
,
4.0
,
2.0
)
,
6.0
)
-
3.0
)
-
1.0
,
0.0
,
1.0
)
;
return
c
.
z
*
mix
(
vec3
(
1.0
)
,
rgb
,
c
.
y
)
;
}
// Smooth HSV to RGB conversion
// https://www.shadertoy.com/view/MsS3Wc
vec3
hsv2rgb_smooth
(
in
vec3
c
)
{
vec3
rgb
=
clamp
(
abs
(
mod
(
c
.
x
*
6.0
+
vec3
(
0.0
,
4.0
,
2.0
)
,
6.0
)
-
3.0
)
-
1.0
,
0.0
,
1.0
)
;
rgb
=
rgb
*
rgb
*
(
3.0
-
2.0
*
rgb
)
;
// cubic smoothing
return
c
.
z
*
mix
(
vec3
(
1.0
)
,
rgb
,
c
.
y
)
;
}
ShaderLab版:
float3
hsb2rgb
(
float3
c
)
{
float3
rgb
=
clamp
(
abs
(
fmod
(
c
.
x
*
6.0
+
float3
(
0.0
,
4.0
,
2.0
)
,
6
)
-
3.0
)
-
1.0
,
0
,
1
)
;
rgb
=
rgb
*
rgb
*
(
3.0
-
2.0
*
rgb
)
;
return
c
.
z
*
lerp
(
float3
(
1
,
1
,
1
)
,
rgb
,
c
.
y
)
;
}
RGB 转 HSB/HSV
vec3
rgb2hsb
(
in
vec3
c
)
{
vec4
K
=
vec4
(
0.0
,
-
1.0
/
3.0
,
2.0
/
3.0
,
-
1.0
)
;
vec4
p
=
mix
(
vec4
(
c
.
bg
,
K
.
wz
)
,
vec4
(
c
.
gb
,
K
.
xy
)
,
step
(
c
.
b
,
c
.
g
)
)
;
vec4
q
=
mix
(
vec4
(
p
.
xyw
,
c
.
r
)
,
vec4
(
c
.
r
,
p
.
yzx
)
,
step
(
p
.
x
,
c
.
r
)
)
;
float
d
=
q
.
x
-
min
(
q
.
w
,
q
.
y
)
;
float
e
=
1.0e-10
;
return
vec3
(
abs
(
q
.
z
+
(
q
.
w
-
q
.
y
)
/
(
6.0
*
d
+
e
)
)
,
d
/
(
q
.
x
+
e
)
,
q
.
x
)
;
}
ShaderLab版:
float3
RGB2HSV
(
float3
c
)
{
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
)
;
}
实践
下面我们在Unity Shader 中来看看
在笛卡尔坐标系下的SHV
由下图我们可以清晰的看到
X 轴 决定 色相,Y 轴 决定 饱和度
代码如下:
Shader
"lcl/shader2D/HSV"
{
SubShader
{
Pass
{
CGPROGRAM
// vert_img 是 UnityCG.cginc 内置的
#
pragma
vertex vert_img
#
pragma
fragment frag
#include
"UnityCG.cginc"
// 该函数由国外大神 Iñigo Quiles 提供
// https://www.shadertoy.com/view/MsS3Wc
float3
hsb2rgb
(
float3
c
)
{
float3
rgb
=
clamp
(
abs
(
fmod
(
c
.
x
*
6.0
+
float3
(
0.0
,
4.0
,
2.0
)
,
6
)
-
3.0
)
-
1.0
,
0
,
1
)
;
rgb
=
rgb
*
rgb
*
(
3.0
-
2.0
*
rgb
)
;
return
c
.
z
*
lerp
(
float3
(
1
,
1
,
1
)
,
rgb
,
c
.
y
)
;
}
// ---------------------------【片元着色器】---------------------------
fixed4
frag
(
v2f_img
i
)
:
SV_Target
{
fixed4
col
;
// hsb 转换为 rgb
// uv.x 决定 色相,
// uv.y 决定 亮度,
col
.
rgb
=
hsb2rgb
(
float3
(
i
.
uv
.
x
,
1
,
1
-
i
.
uv
.
y
)
)
;
return
col
;
}
ENDCG
}
}
}
在极坐标系下的SHV
在极坐标系下,我们可以看到,
角度 决定 色相, 半径 决定 饱和度, 亮度固定
Shader代码如下:
Shader
"lcl/shader2D/HSVInPolarCoordinate"
{
SubShader
{
Pass
{
CGPROGRAM
// vert_img 是 UnityCG.cginc 内置的
#
pragma
vertex vert_img
#
pragma
fragment frag
#include
"UnityCG.cginc"
#
define
TWO_PI 6.28318530718
// 该函数由国外大神 Iñigo Quiles 提供
// https://www.shadertoy.com/view/MsS3Wc
float3
hsb2rgb
(
float3
c
)
{
float3
rgb
=
clamp
(
abs
(
fmod
(
c
.
x
*
6.0
+
float3
(
0.0
,
4.0
,
2.0
)
,
6
)
-
3.0
)
-
1.0
,
0
,
1
)
;
rgb
=
rgb
*
rgb
*
(
3.0
-
2.0
*
rgb
)
;
return
c
.
z
*
lerp
(
float3
(
1
,
1
,
1
)
,
rgb
,
c
.
y
)
;
}
// ---------------------------【片元着色器】---------------------------
fixed4
frag
(
v2f_img
i
)
:
SV_Target
{
fixed4
col
;
// 笛卡尔坐标系转换到极坐标系
float2
center
=
float2
(
0.5
,
0.5
)
-
i
.
uv
;
float
angle
=
atan2
(
center
.
y
,
center
.
x
)
;
float
radius
=
length
(
center
)
*
2.0
;
// 将角度 从(-PI, PI) 映射到 (0,1)范围
// 角度决定色相, 半径决定饱和度, 亮度固定
col
.
rgb
=
hsb2rgb
(
float3
(
(
angle
/
TWO_PI
)
+
0.5
,
radius
,
1.0
)
)
;
return
col
;
}
ENDCG
}
}
}
最后
欢迎来我
GitHub
点个Star,谢谢! 里面有我平时学习unity shader过程中实现的一些特效demo。
本文深入探讨HSV和HSL颜色模型,解释其与RGB模型的区别,包括色相、饱和度和明度的概念。提供了HSV和RGB之间的转换算法,并通过Unity Shader实例展示了HSV在不同坐标系下的表现。
1943

被折叠的 条评论
为什么被折叠?



