2

I'm currently trying to achieve an animated kind of gradient by melting 3 blobs with each other where each blob is separately animated. You can find an image of the desired result in the end.

I have been able to create and animated 3 blobs/circles using the following fragment shader:

uniform vec2 resolution;
uniform vec3 blobs[3];
uniform vec3 colors[3];

vec3 draw_circle(vec2 position, vec3 color, float size) {
    float circle = sqrt(pow(position.x, 2.0) + pow(position.y, 2.0));
    circle = smoothstep(size, size + 0.003, 1.0 - circle);

    return color * circle;
}

void main() {
    vec2 coord = gl_FragCoord.xy / resolution;
    vec3 canvas = vec3(0);

    for (int i = 0; i < 3; i++) {
        vec3 circle = draw_circle(coord - blobs[i].xy / resolution, colors[i], blobs[i].z);
        canvas += circle;
    }

    gl_FragColor = vec4(canvas, 1.0);
}

How do I have to adjust my shader and the respective circles to achieve this kind of blurriness you can see in the last image? Do I need a different approach?

What I Have
Result

What I Want
Goal

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Johnny Kontrolletti
  • 727
  • 1
  • 10
  • 22

1 Answers1

2

Use smoothstep to blur the circle from the center to the outside:

vec3 draw_circle(vec2 position, vec3 color, float size) {
    float circle = length(position.xy);
    
    //circle = smoothstep(size, size + 0.003, 1.0-circle);
    circle = 1.0-smoothstep(0.0, size, circle);

    return color * circle;
}

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Thanks! Using length and changing smoothstep make my circles disappear, what values do you use? – Johnny Kontrolletti Jul 07 '21 at 12:46
  • @Tim [`length(v.xy)`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/length.xhtml) is the same as `sqrt(pow(v.x, 2.0) + pow(v.y, 2.0))` – Rabbid76 Jul 07 '21 at 12:49
  • Yep my bad, using `circle = 1.0 - smoothstep(0, size, 1.0 - circle)` instead of `circle = smoothstep(size, size + 0.003, 1.0 - circle)` makes my circles disappear though – Johnny Kontrolletti Jul 07 '21 at 13:00
  • I'm new to glsl - is there anything else besides the shader that could affect the outcome? F.e. the values for size? – Johnny Kontrolletti Jul 07 '21 at 13:02
  • Why do you `circle = 1.0 - smoothstep(0, size, 1.0 - circle)`? In my code I used `circle = 1.0-smoothstep(0, size, circle);`. Note, `circle` is the distance from the center to the fragment and `size` is the radius of the circle. So [`smoothstep`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/smoothstep.xhtml) returns 0.0 in the center and 1.0 when the distance of the fragment to the center is greater than the radius => `1.0 - smoothstep(...)`. – Rabbid76 Jul 07 '21 at 13:11
  • Thanks the explanation! What odd is that changing it to your snippet will throw the following error: `ERROR: 0:98: 'smoothstep' : no matching overloaded function found`, even though `smoothstep` was available before – Johnny Kontrolletti Jul 07 '21 at 13:22
  • 1
    @Tim Sorry, my bad. `0` -> `0.0`. (`circle = 1.0-smoothstep(0.0, size, circle);`) – Rabbid76 Jul 07 '21 at 13:25
  • By the way, would you have gone for the same approach to achieve the desired result or a different direction to achieve a even closer result? – Johnny Kontrolletti Jul 07 '21 at 14:55