I am trying to create an ios 9 application for a project that will render 3d scenes using these special types of theoretical lenses called glenses .
A ray tracing program called TIM has already been written from scratch to simulate these glenses and more, but it cannot just port it to ios.
My understanding of site search (i.e. this answer and many others about shaders) is that it should be possible, but it's hard for me to get the desired effect.
I decided that I would start by implementing a simpler form of refraction before moving on to more complex refraction like glens:
I managed to get the barrel distortion effect (fisheye) affecting the camera using SCNTechnique
, however, it seems that you can only use methods on the camera or the entire scene, and not individual parts of the geometry.
After that, I tried to get the barrel distortion effect applied to the geometry by entering the opengl code using the SCNMaterial
shaderModifiers
property:
var shaders = [SCNShaderModifierEntryPoint: String]() try! shaders[SCNShaderModifierEntryPoint.fragment] = String(contentsOfFile: Bundle.main.path(forResource: "FishEye", ofType: "fsh")!, encoding: String.Encoding.utf8) try! shaders[SCNShaderModifierEntryPoint.geometry] = String(contentsOfFile: Bundle.main.path(forResource: "FishEye", ofType: "vsh")!, encoding: String.Encoding.utf8) let material = SCNMaterial() material.shaderModifiers = shaders object.geometry?.materials = [material]
I used the slightly modified shaders found here :
fisheye.vsh
varying vec2 uv; #pragma body gl_Position = a_position; uv = a_position.xy;
fisheye.fsh
uniform sampler2D colorSampler; const float PI = 3.1415926535; const float barrelPower = 0.5; uniform vec2 rg; uniform vec2 uv2; varying vec2 uv; uniform float d; uniform vec2 xy; uniform vec2 Vertex_UV; vec2 Distort(vec2 p) { float theta = atan(py, px); float radius = length(p); radius = pow(radius, barrelPower); px = radius * cos(theta); py = radius * sin(theta); return 0.5 * (p + 1.0); } #pragma body #pragma transparent vec2 xy = 2.0 * Vertex_UV.xy - 1.0; 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);
These shaders are compiled and loaded onto my object in the scene, but do nothing; an object is opaque and white when it is almost transparent without injected shaders, and the #pragma transparent
should make it transparent anyway.
To make it clear what I'm trying to achieve here is to have a three-dimensional lens in the scene, which you can view and see the refracted image of what is on the other side.
Any help would be greatly appreciated!