4

I am looking for a shader (or at least the right terminology) for crushing an image. It should be something very similar to barrel distortion, but instead of the center crushing outward to the edges, I want to edges to crush inward to the center.

So, this image:
enter image description here

instead of being deformed like this:
enter image description here

Should rather be deformed like this:
enter image description here

This will be used for a Godot project, but even regular shading language would be tremendously helpful. I tried modifying this gist to no avail.

Edit

Here is the final result using the accepted answer's solution: enter image description here

1 Answers1

4

Your example images do not make the desired effect very apparent, but the opposite of a barrel distortion is a pincushion distortion: enter image description here

I found a fisheye shader on ShaderToy which produces the following image:

enter image description here

By slightly modifying the shader code:

// This shader is based on cafe's fisheye shader:
// https://www.shadertoy.com/view/ll2GWV

vec3 checker(vec2 uv){
    return vec3(abs(floor(mod(uv.x*10.,2.))-floor(mod(uv.y*10.,2.))));   
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord.xy*2. / iResolution.xy-vec2(1.);

    //------------------------------------------------
    // To use in Godot, port this section:
    //------------------------------------------------

    // I picked these somewhat arbitrarily
    const float BARREL = -1.0;
    const float PINCUSHION = 0.1;

    float effect = PINCUSHION; // Set effect to either BARREL or PINCUSHION
    float effect_scale = 1.0;  // Play with this to slightly vary the results

    /// Fisheye Distortion ///
    float d=length(uv);
    float z = sqrt(1.0 + d * d * effect);
    float r = atan(d, z) / 3.14159;
    r *= effect_scale;
    float phi = atan(uv.y, uv.x);

    uv = vec2(r*cos(phi)+.5,r*sin(phi)+.5);

    //------------------------------------------------
    // end relevant logic
    //------------------------------------------------

    fragColor = vec4(checker(uv),1.);
}

We can easily obtain the opposite effect:

enter image description here

If this is not the exact effect you're looking for, I recommend playing around with the code a bit yourself. Change some signs from + to -, add scale factors and explore the possibilities. You may even stumble across a more interesting effect than what were you looking for.

Dan
  • 156
  • 6
  • Wait, does pincushion distortion actually crush inward? I always got the idea it just pulls the edges outward :P – aggregate1166877 Dec 21 '19 at 19:51
  • Please disregard my previous deleted comments, I was being a dumbass. Your solution does 100% what I need. I'll be creating a gist tonight which you may include in your answer if you'd like. – aggregate1166877 Dec 21 '19 at 22:04
  • Here is the gist for the final solution: https://gist.github.com/aggregate1166877/a889083801d67917c26c12a98e7f57a7 . I've added a preview to my question for the sake of completion. – aggregate1166877 Dec 22 '19 at 07:13
  • @aggregate1166877 Nice work! Glad my answer was useful. Thanks for sharing your final solution. – Dan Dec 23 '19 at 00:36