4
$\begingroup$

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

$\endgroup$
4
$\begingroup$

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.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Wait, does pincushion distortion actually crush inward? I always got the idea it just pulls the edges outward :P $\endgroup$ – aggregate1166877 Dec 21 '19 at 19:51
  • $\begingroup$ 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. $\endgroup$ – aggregate1166877 Dec 21 '19 at 22:04
  • $\begingroup$ Here is the gist for the final solution: gist.github.com/aggregate1166877/… . I've added a preview to my question for the sake of completion. $\endgroup$ – aggregate1166877 Dec 22 '19 at 7:13
  • $\begingroup$ @aggregate1166877 Nice work! Glad my answer was useful. Thanks for sharing your final solution. $\endgroup$ – Dan Dec 23 '19 at 0:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.