|
|
|
|
Reply From: |
Zylann |
I played around with color replacement and started with this simple shader which is able to replace only a specific color:
shader_type canvas_item;
uniform vec4 u_color_key : hint_color;
uniform vec4 u_replacement_color : hint_color;
void fragment() {
vec4 col = texture(TEXTURE, UV);
vec4 d4 = abs(col - u_color_key);
float d = max(max(d4.r, d4.g), d4.b);
if(d < 0.01) {
col = u_replacement_color;
}
COLOR = col;
}
Then I went further and made a shader that can replace a color by another while keeping the shading and transparency intact:
shader_type canvas_item;
// Which color you want to change
uniform vec4 u_color_key : hint_color;
// Which color to replace it with
uniform vec4 u_replacement_color : hint_color;
// How much tolerance for the replacement color (between 0 and 1)
uniform float u_tolerance;
void fragment() {
// Get color from the sprite texture at the current pixel we are rendering
vec4 original_color = texture(TEXTURE, UV);
vec3 col = original_color.rgb;
// Get a rough degree of difference between the texture color and the color key
vec3 diff3 = col - u_color_key.rgb;
float m = max(max(abs(diff3.r), abs(diff3.g)), abs(diff3.b));
// Change color of pixels below tolerance threshold, while keeping shades if any (a bit naive, there may better ways)
float brightness = length(col);
col = mix(col, u_replacement_color.rgb * brightness, step(m, u_tolerance));
// Assign final color for the pixel, and preserve transparency
COLOR = vec4(col.rgb, original_color.a);
}
But I found a bug when trying it, I hope it will gets fixed: If two sprites have the same shader but different materials, the second one's parameters are ignored · Issue #14012 · godotengine/godot · GitHub
thanks, it really helped me understand how to shade what i want, anyway hope they will fix that bug(even tho it doesn’t matter to me right now)
rustyStriker | 2017-12-06 11:08
Thanks! Why can’t I just compare the color values directly like:
if (original_color.rgb == u_color_key.rgb)
I tried and it did not work, and I see that you do some math, I think comparing the difference between the colors to a very small quantity, but… why? The color I get from the gimp color picker tool is not “really” the color shown on screen by godot?
tonyrh | 2018-11-12 14:41
This is to rule out floating point error. Shaders work with floating point math, and colors you set in shader parameters are 32-bit floats, not 8-bit RGB values like GIMP shows them. So unless you make sure that every color at any point is clamped to the 8-bit value range, it’s just safer to handle a threshold because comparing two floats for equality doesn’t alway works out.
Zylann | 2018-11-12 19:21