Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fish Eye Wide-angle with a Scene Kit Camera: Possible?

How do I get a distortion like what a fisheye lens does to a view with a SCNCamera in Scene Kit?

Something like this kind of "bowing" of the imagery:

enter image description here

// as Rickster pointed out, this kind of distortion is known as "Barrel Distortion".

From the docs, this is the part that got me intrigued by the possibility of doing this kind of distortion with the camera:

If you compute your own projection transform matrix, you can use this method to set it directly, overriding the transformation synthesized from the camera’s geometric properties.

Unfortunately I know nothing about the powers and possibilities of computing ones own projection transform matrix. I'm hoping it's possible to do this kind of distortion via it... but dunno, hence the question.

Any other means via a camera is ideal. Too. Wanting to avoid post processing trickery and get the more "organic" look of this kind of distortion when the camera rotates and moves through the scene.

See any skateboarding video for how this looks in real life.

like image 467
Confused Avatar asked Jul 21 '15 22:07

Confused


People also ask

Is fisheye wide angle?

A fisheye lens is a special type of ultra-wide angle lens. It is small and ultra-wide, and shows a distorted, spherical view of the world, most evident in the curved outer corners of the photo, known as the "fisheye effect".

Is fisheye lens the same as wide angle?

It helps to remember that they're similar but not interchangeable. A fisheye lens is a wide angle lens, but not all wide angle lenses are fisheyes. Wide angle lenses are versatile and useful. If your goal is to achieve a wide field of view with minimal distortion, then you may want to consider a wide angle lens.

Why does my camera look like a fish eye?

If your camera is mounted at a high distance and is focusing on a short point, then it results in Fisheye Effect. Fisheye effect occurs at a wider viewing angle. The effect produces an image that appears distorted.

How does a fisheye lens camera work?

Full-frame fisheye lenses produce an enlarged image circle that covers the entire image frame. Because of this, the picture angle produced by these lenses only measures 180 degrees when measured from corner to corner. This type of fisheye is the most commonly used by photographers.


1 Answers

What you are looking for is called Barrel Distrortion.

There are a few ways of doing this, all of them using GLSL shaders.

You can either use classic OpenGL code, such as this example for the Occulus Rift (you will need to change the shader a little bit), or my personal favorite: SCNTechnique.

Create a technique containing a Barrel Fragment Shader (.fsh), and set its draw parameter to DRAW_QUAD. Then, simply apply the technique to your camera.

You can find an example of Barrel Distortion shader here : http://www.geeks3d.com/20140213/glsl-shader-library-fish-eye-and-dome-and-barrel-distortion-post-processing-filters/2/


EDIT: here's a sample code:

barrel.json (this should go in your scnassets bundle)

{
  "passes" : {
    "barrel" : {
      "outputs" : {
        "color" : "COLOR"
      },
      "inputs" : {
        "colorSampler" : "COLOR",
        "noiseSampler" : "noiseSymbol",
        "a_position" : "a_position-symbol"
      },
      "program" : "art.scnassets/barrel",
      "draw" : "DRAW_QUAD"
    }
  },
  "sequence" : [
    "barrel"
  ],
  "symbols" : {
    "a_position-symbol" : {
      "semantic" : "vertex"
    },
    "noiseSymbol" : {
      "image" : "noise.png",
      "type" : "sampler2D"
    },
    "barrelPower" : {
      "type" : "float"
    }
  }
}

barrel.vsh

attribute vec4 a_position;
varying vec2 uv;

void main() {
    gl_Position = a_position;
    uv = a_position.xy;
}

barrel.fsh

// Adapted from :
// http://www.geeks3d.com/20140213/glsl-shader-library-fish-eye-and-dome-and-barrel-distortion-post-processing-filters/2/

uniform sampler2D colorSampler;
const float PI = 3.1415926535;
uniform float barrelPower;

varying vec2 uv;


vec2 Distort(vec2 p)
{
    float theta  = atan(p.y, p.x);
    float radius = length(p);
    radius = pow(radius, barrelPower);
    p.x = radius * cos(theta);
    p.y = radius * sin(theta);
    return 0.5 * (p + 1.0);
}


void main() {

    vec2 rg = 2.0 * uv.xy - 1.0;
    vec2 uv2;
    float d = length(xy);
    if (d < 1.0){
        uv2 = Distort(xy);
    }else{
        uv2 = uv.xy;
    }

    gl_FragColor = texture2D(colorSampler, uv2);
}

something.m

NSURL *url = [[NSBundle mainBundle] URLForResource:@"art.scnassets/barrel" withExtension:@"json"];
NSDictionary *tecDic = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL: url] options:nil error:nil];

SCNTechnique* technique = [SCNTechnique techniqueWithDictionary:tecDic];

[technique setValue: [NSNumber numberWithFloat:0.5]  forKey:@"barrelPower"];


cameraNode.technique = technique;
like image 164
Moustach Avatar answered Oct 04 '22 18:10

Moustach