Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to decide if a fragment's color is white or not?

I have many circles next to each other in my scene (white circles and circles with different colors). I would like to blur the white circles only. (White means (1,1,1) in my case.)

My question is: how should I select and blur the white fragments only with my fragment shader?

I want to do something like this in GLSL:

if (my_current_fragment's_color == white)
{blur current fragment;}
else
{do not blur current fragment}

(I have a working blur effect, but it's bluring the whole scene unappropriately because I cannot make a decision in my code based on my fragments' color.)

How should I do this? What is the exact match of the above code in GLSL language? How can I decide if a fragment's color is white? Do you guys have any idea?


If you may need, here is my code:

    vertexShader: [
        //"#define KERNEL_SIZE 25.0",
        "uniform vec2 uImageIncrement;",
        "varying vec2 vUv;",
        "void main() {",
        "vUv = uv - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * uImageIncrement;",
        "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
        "}"
    ].join("\n"),
    fragmentShader: [
        //"#define KERNEL_SIZE 25",
        "uniform float cKernel[ KERNEL_SIZE ];",
        "uniform sampler2D tDiffuse;",
        "uniform vec2 uImageIncrement;",
        "varying vec2 vUv;",
        "void main() {",
            "vec2 imageCoord = vUv;",
            "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );",
            "for( int i = 0; i < KERNEL_SIZE; i ++ ) {",


            "sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];",
            //THE ABOVE LINE SHOULD BE RUN FOR WHITE FRAGMENTS ONLY. BUT HOW?


            "imageCoord += uImageIncrement;",
            "}",
            "gl_FragColor = sum;",
        "}"
like image 924
Fract Avatar asked Feb 18 '23 01:02

Fract


1 Answers

This is going to be really hard, and you're going to have to figure out some compromise, unless you can render the white circles to a different framebuffer to begin with.

Let's say you start with this.

white circle over pink triangle with blue background

If you only apply the blur kernel to the white pixels, you'll get this:

white circle with blurred interior over pink triangle with blue background

Since the blue pixels don't get the blur kernel, the white pixels can't bleed into the blue. Only the pink and blue pixels can bleed into the white.

So you try to separate the image into the white parts and the non-white parts:

white circleblack circle over pink triangle with blue background

And then you can blur the white parts separately, and recombine (either in multiple steps, or all in the same shader). But you have to figure out what to recombine it with. If you recombine it with the original image, the hard-edge white will still be there. If you recombine it with the image with only the non-white parts, you'll get a hard black edge instead.

white circle with halo over pink triangle with blue backgroundwhite circle with halo and black edge over pink triangle with blue background

Solutions

  • You can render the white circles into a separate texture to begin with, blur that, and layer it on top of everything else.

  • You can scale the kernel so that the kernel blurs "outwards" (dilates), so when you blur the white circle against the black background, white pixels stay white. This will eliminate the edges.

  • You can blur an area of the image near, but not exactly equal to, the white circles. For example, you can use the blurred white circles as an alpha mask to blend between the blurred image and the sharp image.

  • You can figure out a way to make the white circles look blurry to begin with.

like image 188
Dietrich Epp Avatar answered Mar 05 '23 08:03

Dietrich Epp