0 votes

I'm trying to achieve an effect similar to this one but instead of drawing the original pixels using a shader, I want to draw them using a sprite node.

Light color mixing.

This is what each sprite currently looks like:
Current state.

Overlapping sprite areas:
Overlapping areas.

Approximate desired shader effect:
Desired effect.

I tried importing the textures using uniform sampler2Ds and experimenting with textureLod, SCREENTEXTURE and SCREENUV but I couldn't find a way to calculate the area where the sprites are overlapping.

Any help is appreciated.

asked Feb 25 in Engine by Mariothedog (154 points)

This is the shader code that I'm using for the top image's shader.

shader_type canvas_item;
render_mode unshaded; // No lighting/shading

uniform vec4 colour_one : hint_color;
uniform vec4 colour_two : hint_color;
uniform vec4 colour_three : hint_color;
uniform vec2 colour_one_pos = vec2(0.333, 0.4);
uniform vec2 colour_two_pos = vec2(0.666, 0.4);
uniform vec2 colour_three_pos = vec2(0.5, 0.6);

uniform float circle_radius = 0.3;

void fragment(){
    COLOR.a = 0.0;

    bool in_colour_one = distance(colour_one_pos, UV) <= circle_radius;
    bool in_colour_two = distance(colour_two_pos, UV) <= circle_radius;
    bool in_colour_three = distance(colour_three_pos, UV) <= circle_radius;

    if (in_colour_one && in_colour_two && in_colour_three){
        COLOR = colour_one + colour_two + colour_three;
    }
    else if (in_colour_one && in_colour_two){
        COLOR = colour_one + colour_two;
    }
    else if (in_colour_one && in_colour_three){
        COLOR = colour_one + colour_three;
    }
    else if(in_colour_two && in_colour_three){
        COLOR = colour_two + colour_three;
    }
    else{
        if (in_colour_one){
            COLOR = colour_one;
        }
        if (in_colour_two){
            COLOR = colour_two;
        }
        if (in_colour_three){
            COLOR = colour_three;
        }
    }
}

Have you tried the additive blend mode?

render_mode unshaded, blend_add;

Sorry, I'm still new to shaders. I have not tried the additive blend mode but how would I use it to combine the colors in the area where two sprites overlap?

1 Answer

+3 votes
Best answer

You don't need a shader to achieve this effect. It is done through additive blend mode, which is closer to how light behaves. Basically, colors are combined by adding them together.

Go to the inspector for each of your sprites and add a new CanvasItemMaterial in their material property. Then in that material, change blend mode to Add.

If you use a shader, this is essentially the same, except you write render_mode blend_add on the top.
Note that there is no way to implement a custom blending operation with shader code (at least not with more than 2 layers), only the predefined modes are available.

If however you want to blend between colors within your shader, you could write it as a simple addition (same as the code you already posted, simplified a bit):

bool in_colour_one = distance(colour_one_pos, UV) <= circle_radius;
bool in_colour_two = distance(colour_two_pos, UV) <= circle_radius;
bool in_colour_three = distance(colour_three_pos, UV) <= circle_radius;

if (in_colour_one) {
    COLOR.rgb += colour_one.rgb;
}
if (in_colour_two) {
    COLOR.rgb += colour_two.rgb;
}
if (in_colour_three) {
    COLOR.rgb += colour_three.rgb;
}
answered Feb 25 by Zylann (27,004 points)
selected Feb 26 by Mariothedog
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.