Search code examples
three.jsglslshaderwebglfragment-shader

How can I give a border blur effect with GLSL?


To give it the feel of a real beam project, I created a shader using a RawShaderMaterial that shows the blur coming in from the edges.

However, I'm getting diagonal lines in each corner, and I'm having trouble getting it to work.

Can anyone help me modify my code to make it work correctly? Or if you have any other ideas to implement the blur shader naturally, please let me know.


Solution

  • Bearing in mind that vUv ranges [0 .. 1] in both x and y, the area where the map is not faded, is an axis-aligned rectangle over [edge .. 1 - 2 * edge] in both dimensions. We can drop all the conditionals and use the distance from vUv to that rectangle.

        void main(){
          float edgeMin = edge;
          float edgeMax = 1.0 - edge;
    
          gl_FragColor = texture2D( map, vUv );
          // dx => lilnear distance parallel to x from vUv to rectangle
          // (0.5, 0.5) is the center of the rectangle in uv
          // the abs and max work together to make any vUv inside the 
          // rectangle return 0
          float dx = max(abs(vUv.x - 0.5) - (0.5 - edge), 0.);
          // similarly for dy, along the parallel to y
          float dy = max(abs(vUv.y - 0.5) - (0.5 - edge), 0.);
          // d is the result of a Euclidean distance; this rounds the corners
          float d = sqrt(dx * dx + dy * dy);
          // alpha should be opacity at the edge of the rectangle, and also 
          // inside of it (all where d == 0), and 0. at the edge of the plane
          // (where d == edge).  So we do an inverse lerp.
          gl_FragColor.a = opacity - opacity * d / edge;
    
        }