Hi fabulous people, I’m fairly new coding HLSL.
I’m trying to influence the HUE of an Albedo and I found this way to do:
Because the need for color manipulation comes up fairly often in computer graphics, particularly transformations of hue, saturation, and value, and because some of this math is a bit tricky, here’s how to do HSV color transforms on RGB data using...
I implemented it, succeed for the Saturation and Value, working Great ! But the HUE won’t work.
Afterward I noticed that the input should be in degrees . What range should I expose for the slider ? Have we to declare this variable as a float ? or other type ?
Thx
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Texture", 2D) = "white" {}
_ColorizeTex ("Colorize", 2D) = "white" {}
H ("Hue", Range(0.0, 1.1)) = 0 //should be degrees !!!
S ("Saturation", Range(0.0, 1.0)) = 1.0 //Working great
V ("Value", Range(0.0, 1.0)) = 1.0 //Working great
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
float4 BaseColor;
float H;
float S;
float V;
float PI = float(3.14159265);
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float VSU = float(V*S*cos(H*PI/180));
float VSW = float(V*S*sin(H*PI/180));
float4 BaseColor = tex2D(_MainTex, i.uv) *_Color;
float retr = float((0.299*V+0.701*VSU+0.168*VSW)*BaseColor.r + (0.587*V-0.587*VSU+0.330*VSW)*BaseColor.g + (0.114*V-0.114*VSU-0.497*VSW)*BaseColor.b);
float retg = float((0.299*V-0.299*VSU-0.328*VSW)*BaseColor.r + (0.587*V+0.413*VSU+0.035*VSW)*BaseColor.g + (0.114*V-0.114*VSU+0.292*VSW)*BaseColor.b);
float retb = float((0.299*V-0.3*VSU+1.25*VSW)*BaseColor.r + (0.587*V-.588*VSU-1.05*VSW)*BaseColor.g + (0.114*V+.886*VSU-0.203*VSW)*BaseColor.b);
fixed4 col = fixed4 (retr, retg, retb, 1);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
float3 hsv_to_rgb(float3 HSV)
{
float3 RGB = HSV.z;
float var_h = HSV.x * 6;
float var_i = floor(var_h); // Or ... var_i = floor( var_h )
float var_1 = HSV.z * (1.0 - HSV.y);
float var_2 = HSV.z * (1.0 - HSV.y * (var_h-var_i));
float var_3 = HSV.z * (1.0 - HSV.y * (1-(var_h-var_i)));
if (var_i == 0) { RGB = float3(HSV.z, var_3, var_1); }
else if (var_i == 1) { RGB = float3(var_2, HSV.z, var_1); }
else if (var_i == 2) { RGB = float3(var_1, HSV.z, var_3); }
else if (var_i == 3) { RGB = float3(var_1, var_2, HSV.z); }
else if (var_i == 4) { RGB = float3(var_3, var_1, HSV.z); }
else { RGB = float3(HSV.z, var_1, var_2); }
return (RGB);
}
try that in reverse to get the HSV, from how to get hsv(hsb) color in shader
or converting these:
TL;DR: Go here to get the RGB->HSV and HSV->RGB conversion functions for shaders.
The other day I tried to tint a colour in a texture (or rather all texture) with a different colour. It's quite easy to rotate things around, but, if you want...
1 Like
Thx a lot @MadeFromPolygons_1
I had hardtime trying to fit your code (surface albedo) to a frag unlit (experience I need, indeed).
But, I tried to troubleshoot which value in my first implementation was doing nothing.
Now it’s working Hourra !
* of course it will be properly clean, if I’m setting the range of the slider from 0 to 1.0 and doing this 6.28 scale in the SIN and COS (H*6.28).
Here’s what I changed, the full code working below:
The definition of VSU and VSW pass SIN and COS on the HUE value entered with PI, etc… I simply put the HUE input direct to the SIN and COS
float VSU = float(VS cos(H ));
float VSW = float(VS sin(H ));
Than manually (screenshot comparisons), found that the range for the HUE is 0 to 6.28 [yes, I can hear mathematician saying “haaaa, these little artists, lol”. But, it’s working, in this colorspace, lol]
Shader "DaPrato/Colorize_Unlit_Hue"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Texture", 2D) = "white" {}
H ("Hue", Range(0.0, 6.28)) = 0
S ("Saturation", Range(0.0, 1.0)) = 1.0
V ("Value", Range(0.0, 1.0)) = 1.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
float4 BaseColor;
float H;
float S;
float V;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//cos and sin was on (H*PI/180)
float VSU = float(V*S*cos(H));
float VSW = float(V*S*sin(H));
float4 BaseColor = tex2D(_MainTex, i.uv) *_Color;
float retr = float((0.299*V+0.701*VSU+0.168*VSW)*BaseColor.r + (0.587*V-0.587*VSU+0.330*VSW)*BaseColor.g + (0.114*V-0.114*VSU-0.497*VSW)*BaseColor.b);
float retg = float((0.299*V-0.299*VSU-0.328*VSW)*BaseColor.r + (0.587*V+0.413*VSU+0.035*VSW)*BaseColor.g + (0.114*V-0.114*VSU+0.292*VSW)*BaseColor.b);
float retb = float((0.299*V-0.3*VSU+1.25*VSW)*BaseColor.r + (0.587*V-.588*VSU-1.05*VSW)*BaseColor.g + (0.114*V+.886*VSU-0.203*VSW)*BaseColor.b);
fixed4 col = fixed4 (retr, retg, retb, 1);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
2 Likes
daprato:
Thx a lot @MadeFromPolygons1
I had hardtime trying to fit your code (surface albedo) to a frag unlit (experience I need, indeed).
But, I tried to troubleshoot which value in my first implementation was doing nothing.
Now it’s working Hourra !
* of course it will be properly clean, if I’m setting the range of the slider from 0 to 1.0 and doing this 6.28 scale in the SIN and COS (H*6.28).
Here’s what I changed, the full code working below:
The definition of VSU and VSW pass SIN and COS on the HUE value entered with PI, etc… I simply put the HUE input direct to the SIN and COS
float VSU = float(VS cos(H ));
float VSW = float(VS sin(H ));
Than manually (screenshot comparisons), found that the range for the HUE is 0 to 6.28 [yes, I can hear mathematician saying “haaaa, these little artists, lol”. But, it’s working, in this colorspace, lol]
Shader "DaPrato/Colorize_Unlit_Hue"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Texture", 2D) = "white" {}
H ("Hue", Range(0.0, 6.28)) = 0
S ("Saturation", Range(0.0, 1.0)) = 1.0
V ("Value", Range(0.0, 1.0)) = 1.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
float4 BaseColor;
float H;
float S;
float V;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//cos and sin was on (H*PI/180)
float VSU = float(V*S*cos(H));
float VSW = float(V*S*sin(H));
float4 BaseColor = tex2D(_MainTex, i.uv) *_Color;
float retr = float((0.299*V+0.701*VSU+0.168*VSW)*BaseColor.r + (0.587*V-0.587*VSU+0.330*VSW)*BaseColor.g + (0.114*V-0.114*VSU-0.497*VSW)*BaseColor.b);
float retg = float((0.299*V-0.299*VSU-0.328*VSW)*BaseColor.r + (0.587*V+0.413*VSU+0.035*VSW)*BaseColor.g + (0.114*V-0.114*VSU+0.292*VSW)*BaseColor.b);
float retb = float((0.299*V-0.3*VSU+1.25*VSW)*BaseColor.r + (0.587*V-.588*VSU-1.05*VSW)*BaseColor.g + (0.114*V+.886*VSU-0.203*VSW)*BaseColor.b);
fixed4 col = fixed4 (retr, retg, retb, 1);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
Excellent work! thank you very much for detailing your fix process too
1 Like