<p>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..</p>

<p>Can you compare the input coordinates between the two implementations?</p>

CC BY-SA 4.0
2018-11-17T10:09:34.123Z
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).
brockmann
CC BY-SA 4.0
2018-11-16T22:43:30.033Z
2018-11-16T22:43:30.033Z
zeno
<p>I'm trying to re-implement Blenders (<a href="https://github.com/libmv/libmv" rel="noreferrer">libmv</a>) <a href="https://github.com/sobotka/blender/blob/master/intern/libmv/libmv/simple_pipeline/distortion_models.h#L66" rel="noreferrer">polynomial lens distortion model</a> using <a href="https://www.shadertoy.com/" rel="noreferrer">shadertoy</a>, 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 <code>k1=0.1 k2=0.0 k3=0.0</code> the resulting distortion is still too heavy in comparison to the distorted image out of Blender.</p>

<pre><code>// 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 );


}
</code></pre>

<p><a href="https://i.sstatic.net/s2evX.png" rel="noreferrer"><img src="https://i.sstatic.net/s2evX.png" alt="enter image description here"></a>
<em>Test image undistorted</em></p>

<p><a href="https://i.sstatic.net/hPh8I.jpg" rel="noreferrer"><img src="https://i.sstatic.net/hPh8I.jpg" alt="enter image description here"></a>
<em>Test image distorted in Blender k1=0.1 k2=0.0 k3=0.0</em></p>

<p><strong>Q:</strong> What I'm missing in order to match Blender's polynomial lens distortion model?</p>

<shader><mathematics><fragment-shader><camera><distortion>
How to match Blenders polynomial lens distortion model with GLSL?
brockmann
# How to match Blenders polynomial lens distortion model with GLSL?

(Asked by: username_0 on 2018-11-13)

I'm trying to re-implement Blenders ([libmv](https://github.com/libmv/libmv)) [polynomial lens distortion model](https://github.com/sobotka/blender/blob/master/intern/libmv/libmv/simple_pipeline/distortion_models.h#L66) using [shadertoy](https://www.shadertoy.com/), 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](https://i.sstatic.net/s2evX.png)](https://i.sstatic.net/s2evX.png)
*Test image undistorted*

[![enter image description here](https://i.sstatic.net/hPh8I.jpg)](https://i.sstatic.net/hPh8I.jpg)
*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?

**Tags:** shader, mathematics, fragment-shader, camera, distortion


---

## 1 answers

### Answer by username_1 on 2018-11-16. Score: 0

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?

> **Comments:**
> **username_0**: Thanks @username_1! 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).  

---

