2
$\begingroup$

I'm trying to re-implement Blenders (libmv) polynomial lens distortion model using shadertoy, in order to apply the lens distortion in another application ideally by generating a STMap for that. I think I'm close, but when passing the same values k1=0.1 k2=0.0 k3=0.0 the resulting distortion is still too heavy in comparison to the distorted image out of Blender.

// Based on: 
// https://www.shadertoy.com/view/lslGRN
// https://www.shadertoy.com/view/XdfGzH

vec3 color = vec3(0.4,0.4,0.4);
float lens = 24.0; 

//note: period of 2, [-1;1]=/\ 
float sawtooth( float t ) 
{
    return abs(mod(abs(t), 2.0)-1.0);
}

vec2 BarrelDistort(vec2 p)
{
    float theta  = atan(p.y, p.x);
    float radius = length(p);
    radius = pow(radius, 1.2);
    p.x = radius * cos(theta);
    p.y = radius * sin(theta);
    return (1.0 * (p));
}   

vec2 BlenderDistort(vec2 p)
{
    // https://en.wikipedia.org/wiki/Distortion_(optics)
    // https://github.com/sobotka/blender/blob/master/intern/libmv/libmv/simple_pipeline/distortion_models.h#L66
    float x = p.x;
    float y = p.y;

    float k1 = .1/2.0;
    float k2 = .0;
    float k3 = .0;

    float p1 = .0;
    float p2 = .0;

    float r2 = x*x + y*y;
    float r4 = r2 * r2;
    float r6 = r4 * r2;
    //float r_coeff = (T(1) + k1*r2 + k2*r4 + k3*r6);
    float r_coeff = (1.0 + k1*r2 + k2*r4 + k3*r6);
    //float xd = x * r_coeff + T(2)*p1*x*y + p2*(r2 + T(2)*x*x);
    float xd = x * r_coeff + 2.0*p1*x*y + p2*(r2 + 2.0*x*x);
    float yd = y * r_coeff + 2.0*p2*x*y + p1*(r2 + 2.0*y*y);

    return vec2(xd, yd);
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord.xy / iResolution.xy;    
    vec2 normalizedUV = (fragCoord.xy/(iResolution.xy/2.0))-1.0;

    vec2 dist = BlenderDistort(normalizedUV);   
    vec2 uv_transform = vec2(.5)+vec2(.5)*dist;

    vec3 outcol = vec3(0.0);
    //outcol += texture( iChannel0, vec2(0,1)+vec2(1,-1)*uv ).rgb;
    outcol += texture( iChannel0, uv_transform ).rgb;


    // Draw Lines
    vec2 div = 30.0 * vec2(1.0, iResolution.y / iResolution.x );
    float lines = 0.0;
    lines += smoothstep( 0.2, 0.0, sawtooth( dist.x*2.0*div.x ) );
    lines += smoothstep( 0.2, 0.0, sawtooth( dist.y*2.0*div.y ) );
    lines = clamp( lines, 0.0, 1.0 );

    //outcol *= vec3(1.0-lines); //black
    //outcol += vec3(lines); //white

    //note: force black outside valid range 
    vec2 valid = step( vec2(-1.0), dist ) * step( dist, vec2(1.0) );
    outcol *= valid.x*valid.y;

    fragColor = vec4( outcol,1.0 );


}

enter image description here Test image undistorted

enter image description here Test image distorted in Blender k1=0.1 k2=0.0 k3=0.0

Q: What I'm missing in order to match Blender's polynomial lens distortion model?

$\endgroup$
0
$\begingroup$

Not sure what's wrong with your implementation, but it looks like the blender's distortion model is not proportional to the image aspect ratio, producing equal curvature in both axis..

Can you compare the input coordinates between the two implementations?

$\endgroup$
  • $\begingroup$ Thanks @zeno! Probably you are right, but I don't know how to compare both without compiling blender by myself. I still think there is just something wrong in my equation so I'm not sure whether that's worth it going through that entire process setting up that thing ;) In case you are interested in how different the distortion is, you can easily compare both results using Natron and its shadertoy node (but you probably know that). $\endgroup$ – brockmann Nov 17 '18 at 10:09

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.