## Fisheye Lens (Hyperbolic Lens) Vertex Shader in GLSL

Today I will write about my fisheye (hyperbolic) lens shader. It was part of a larger project to simulate a wide depth of field and imperfections in human eyesight. Anyway, I like the way it came out, so I will describe how I went about the process in GLSL. A fisheye lens allows an extremely wide field of view, nearly 180 degrees, but it also bends the light in order to fit it all on a square so you get an interesting effect where the edges become distorted and straight lines become curved. Since it’s just an approximation, and it works on vertices, the quality is limited to the amount of vertices on screen. Here are some pictures which describe how it works. (10,000 hours in ms paint)

First we project A which is the vector from the camera to the point we are looking at, unto B, which is the lookat point. This is the point that is in the center of the frustum, basically the Z axis in the current coordinate system. Then after projecting we get C. Then we subtract and get the C-A vector. Then we find a halfway point of that and calculate D by subtracting camera_pos – C-A/2.

Then we take the magnitude of A and multiply it by the direction of D effectively rotating point A and bringing it closer to the center of the camera.

Here is a scene with a regular 45 degree field of view.

And now what we’ve all been waiting for. Per pixel phong shading + fisheye lens shader.

The vertex shader:

1: varying vec4 normal,light_dir,eye_vec,lookat;2:constfloatPI = 3.14159265;3: 4:voidmain()5:{6: vec4 ambient,diffuse,specular;7:floatNdotL,RdotV;8: 9: normal = vec4(gl_NormalMatrix * gl_Normal,0.0);10: vec4 vVertex = gl_ModelViewMatrix * gl_Vertex;11: light_dir = gl_LightSource[0].position - vVertex;12: eye_vec = -vVertex;13: 14: vec4 temp_pos = ftransform();15: 16:floatdist = length(eye_vec);17: lookat = eye_vec - temp_pos;18: vec4 dir = temp_pos - eye_vec;19: vec4 center = normalize(-eye_vec);20: vec4 proj = dot(temp_pos,normalize(-lookat))* normalize(-lookat);21: 22: vec4 c = temp_pos - proj;23: 24:floatmagnitude = .01;//1-acos(dot(normalize(-eye_vec), normalize(temp_pos))); 25:26: c = length(c)* magnitude * normalize(c);27: 28: vec4 dir2 = normalize(c-lookat);29: 30: dir2 =(dir2 * dist);31: 32: gl_Position.xyz = dir2.xyz;33: gl_Position.w = ftransform().w;34: 35:}

The pixel shader:

1: varying vec4 normal,light_dir,eye_vec;2: 3: uniform vec4 camera_pos;4: 5:voidmain()6:{7: 8: vec4 ambient,diffuse,specular;9:floatNdotL,RdotV;10: 11: vec4 N = normalize(normal);12: vec4 L = normalize(light_dir);13: NdotL = dot(N,L);14://RdotV = max(dot(R, V), 0.0); 15:gl_FragColor = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;16: 17:if(NdotL > 0.0)18:{19: ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;20: diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;21: specular = gl_FrontMaterial.specular * gl_LightSource[0].specular;22: vec4 E = normalize(eye_vec);23: vec4 R = reflect(-L,N);24: 25: gl_FragColor +=(NdotL * diffuse)+ 26: specular * pow(max(dot(R,E),0.0),gl_FrontMaterial.shininess);27:}28:}

nice, thanks you, helped me!

This is awsome. I have been attempting this for so long but in python + opengl. Do you have the full code. Thats executable or how would some one be able to execute it.

Thanks.

I wrote this a while ago so I don’t have the original exe, but there’s an implementation here in an android library: http://codeanticode.wordpress.com/2010/08/22/glgraphics-0-9-4/

You can just directly compile the shaders right off this site. I’d follow a GLSL tutorial for more info.

Hi! This is great! I’ve been looking for clear explanations of this. Thank you!

I’ve tested it out but I’m getting a weird effect. I get the fisheye transformation but all my normals are reversed (I see the inside of objects)…!

Something like if the projection was made behind the camera.. Have you run into this during your development? And if not, do you have an idea of what I’m experimenting?

Thanks 🙂

Check your state – set different cull mode like ccw or cw or maybe alter the winding order of your geometry.

This shader doesn’t work 😦

Can anyone upload the whole C++ or Qt project?

Yup, check your email.

please share the total codes(c++)

Nice work!

Can the intensity of the warping be increased? 🙂