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

前端 未结 1 1757
无人及你
无人及你 2020-12-11 16:58

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:

相关标签:
1条回答
  • 2020-12-11 17:35

    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;
    
    0 讨论(0)
提交回复
热议问题