Color curves (Godot 3.x – GLES2)
This shader adjusts colors with curves, similar to the filter found in art/photo editing software such as Krita and GIMP. Supports RGB, Red, Green, Blue, Alpha, Hue, Saturation and Value channels. It takes a CurveTexture as a uniform sampler2D for each channel.
NOTE: This shader only works as intended using Godot 3’s GLES2 renderer. For the GLES3/Godot 4 version, see: https://godotshaders.com/shader/color-curves-2/
Artwork in the cover image is made by Erevoid, with Pixelorama.
Shader code
shader_type canvas_item;
// CurveTexture(s)
uniform sampler2D rgb_curve;
uniform sampler2D red_curve;
uniform sampler2D green_curve;
uniform sampler2D blue_curve;
uniform sampler2D alpha_curve;
uniform sampler2D hue_curve;
uniform sampler2D sat_curve;
uniform sampler2D value_curve;
vec3 rgb2hsb(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);
}
vec3 hsb2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void fragment() {
COLOR = texture(TEXTURE, UV);
float red_curve_color = texture(red_curve, vec2(COLOR.r, 0.0)).a;
float green_curve_color = texture(green_curve, vec2(COLOR.g, 0.0)).a;
float blue_curve_color = texture(blue_curve, vec2(COLOR.b, 0.0)).a;
float alpha_curve_color = texture(alpha_curve, vec2(COLOR.a, 0.0)).a;
COLOR.r = red_curve_color;
COLOR.g = green_curve_color;
COLOR.b = blue_curve_color;
COLOR.a = alpha_curve_color;
vec3 hsb = rgb2hsb(COLOR.rgb);
float hue_curve_color = texture(hue_curve, vec2(hsb.r, 0.0)).a;
float sat_curve_color = texture(sat_curve, vec2(hsb.g, 0.0)).a;
float value_curve_color = texture(value_curve, vec2(hsb.b, 0.0)).a;
hsb.r = hue_curve_color;
hsb.g = sat_curve_color;
hsb.b = value_curve_color;
COLOR.rgb = hsb2rgb(hsb);
float rgb_curve_color_r = texture(rgb_curve, vec2(COLOR.r, 0.0)).a;
float rgb_curve_color_g = texture(rgb_curve, vec2(COLOR.g, 0.0)).a;
float rgb_curve_color_b = texture(rgb_curve, vec2(COLOR.b, 0.0)).a;
COLOR.rgb = vec3(rgb_curve_color_r, rgb_curve_color_g, rgb_curve_color_b);
}
Thanks for making this shader!
Unfortunately, I cant get it to work on any texture (Sprite2D node).
Everything just shows up as white. Any instructions on how to use it?
Hello. I tested it again, and it seems to be indeed white on GLES3, but it does work as intended in GLES2. I’m not sure why this happens, I’ll try to look into it.
Hello! I have edited the original post to add a note about GLES3. The solution seems to be to just replace all of the
.a
s to.r
s in the texture() functions, in order to get the red values instead of alpha. I’m not sure why CurveTextures work differently in GLES2 and GLES3.Thanks a lot for the shader! But I have changed .a to .r and still can’t get it to work in Godot 4. Here is the code with the changes. Am I missing something? Tried to change ALL the .a to .r (not just in texture()), didn’t work either.
Hmm this is weird. I am just testing it in Godot 4.3 and it is working as intended. I published a Godot 4 version here, but it seems identical to your code so I’m not sure what may be the issue.