foreword
For color values,
RGB
Probably the color model we have the most exposure to, any color in an image is determined by
red (R)
,
Green (G)
,
blue (B)
Synthesized by these three channels, these three colors can be combined into almost any color.
However, it is not intuitive. For example, if I say an rgb value casually, can you guess what color it is? It is almost impossible, so the introduction of
HSV
,
HSL
and other color models.
HSV
compared to
RGB
is a more intuitive color model,
HSV
It is more in line with our human vision.
HSL and HSV concepts:
HSL
That is, hue, saturation, and brightness (English: Hue, Saturation, Lightness).
HSV
Hue, Saturation, Value (English: Hue, Saturation, Value), also known as HSB, where B is English: Brightness.
-
Hue (H) is the basic attribute of color, which is commonly referred to as the color name, such as red, yellow, etc.
-
Saturation (S) refers to the purity of the color, the higher the color, the purer the color, and the lower it will gradually become gray, taking the value of 0-100%.
-
Brightness (V), brightness (L), take 0-100%
HSL and HSV color space comparison:
Both are mathematically cylindrical, but
HSV
Conceptually, it can be thought of as an inverted cone of color (the black point is at the lower apex, and the white is at the center of the upper base);
HSL
Conceptually represents a double cone and sphere (white at the upper apex, black at the lower apex, the center of the largest cross-section is half gray).
Convert between HSV and RGB
The following functions are provided by foreign gods
Inigo Quilez
supply
https://www.shadertoy.com/view/MsS3Wc
HSB/HSV to RGB
<pre> // 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 . the 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 . the y ) ; }
ShaderLab version:
<pre> 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 . the y ) ; }
RGB to HSB/HSV
<pre> 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 . w ) , 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 . the y ) ; float e = 1.0e-10 ; return vec3 ( abs ( q . z + ( q . w - q . the y ) / ( 6.0 * d + e ) ) , d / ( q . x + e ) , q . x ) ; }
ShaderLab version:
<pre> 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 . w ) , 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 . the y ) ; float e = 1.0e-10 ; return float3 ( abs ( q . z + ( q . w - q . the y ) / ( 6.0 * d + e ) ) , d / ( q . x + e ) , q . x ) ; }
to practice
Let’s take a look in Unity Shader
SHV in Cartesian coordinate system
From the figure below, we can clearly see
X-axis determines Hue, Y-axis determines Saturation
code show as below:
<pre> Shader "lcl/shader2D/HSV" {<!-- --> SubShader {<!-- --> Pass {<!-- --> CGPROGRAM // vert_img is built into UnityCG.cginc # pragma vertex vert_img # pragma fragment frag #include "UnityCG.cginc" // This function is provided by the foreign god 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 . the y ) ; } // ---------------------------【Fragment Shader】--------------------------- fixed4 frag ( v2f_img i ) : SV_Target {<!-- --> fixed4 col ; // convert hsb to rgb // uv.x determines hue, // uv.y determines brightness, col . rgb = hsb2rgb ( float3 ( i . uv . x , 1 , 1 - i . uv . the y ) ) ; return col ; } ENDCG } } }
SHV in polar coordinates
In polar coordinates, we can see that,
Angle determines hue, radius determines saturation, brightness is fixed
Shader code is as follows:
<pre> Shader "lcl/shader2D/HSVInPolarCoordinate" {<!-- --> SubShader {<!-- --> Pass {<!-- --> CGPROGRAM // vert_img is built into UnityCG.cginc # pragma vertex vert_img # pragma fragment frag #include "UnityCG.cginc" # define TWO_PI 6.28318530718 // This function is provided by the foreign god 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 . the y ) ; } // ---------------------------【Fragment Shader】--------------------------- fixed4 frag ( v2f_img i ) : SV_Target {<!-- --> fixed4 col ; // Convert Cartesian coordinate system to polar coordinate system float2 center = float2 ( 0.5 , 0.5 ) - i . uv ; float the angle = atan2 ( center . the y , center . x ) ; float radius = length ( center ) * 2.0 ; // map angles from (-PI, PI) to (0,1) range // The angle determines the hue, the radius determines the saturation, and the brightness is fixed col . rgb = hsb2rgb ( float3 ( ( the angle / TWO_PI ) + 0.5 , radius , 1.0 ) ) ; return col ; } ENDCG } } }
at last
welcome to me
GitHub
Order a star, thank you! There are some special effect demos that I usually realize in the process of learning unity shader.