Geometric distortion for dome (fisheye) projectionWritten by Paul Bourke
In an earlier project I described a multi-pass texture based algorithm by which one can create fisheye images using OpenGL. In that approach, the scene (described by OpenGL drawing commands) is rendered 4 times based upon frustums from the virtual camera position to the sides of a cube. These 4 images are used as textures mapped onto a special surface with texture coordinates arranged so that the resulting orthographic projection is a fisheye projection.
In what follows an alternative is discussed, namely, the geometry is distorted in such a way that when viewed using an orthographic projection the result is a correct fisheye image. Which approach is most appropriate depends on the content, for example, the former approach in general gives better results for highly textured scenes while the later is better for crisp geometry, as is often the case in many raw data representations.Additional features
Besides the straightforward fisheye transformation there are some other important features that need to be supported to cope with some features of practical fisheye projection systems in common use. These are given below and are all supported in the proof-of-concept application described here.
A geometric reality of fisheye projection is that the shortest distance between two points is not a straight line in fisheye space, like it is in a perspective projection. So lines, triangles, and polygons that are used to represent the model in OpenGL need to be tessellated. This greatly increases the amount of geometry eventually passed to the graphics card and therefore it's important to do this tessellation efficiently. The approach tested here is to project the geometric entities into fisheye space and recursively bisect them until the distance between points is below some threshold. This means that short lines don't get split into many segments and long lines that are close to being parallel to the view direction also aren't bisected many times. An additional option is provided where the user can control the degree of bisection, for example, the bisection may be reduced for more demanding models in order to trade off interactive performance with image quality.
Note that geometric attributes also need to be split on each bisection stage. For example when splitting lines the colour (which may be different at each end) also needs to be estimated for the new vertices. When splitting quads, the colour, normals, and texture coordinates need to be estimated.
This process certainly needs to be efficient and more work could be done. For example: long thin quads should be split along the long length first.
The coordinate system conventions are given below, the camera model includes the camera position (vp), the orientation is specified by the view direction (vd), the up vector (vu), and right vector (vr)....all are unit vectors and normal to each other.
The fisheye coordinates are just theta and r, or as Cartesian coordinates (r cos(theta0, r sin(theta)) where r is proportional to phi.
The projection onto the up and right vector is found by using the dot product with the unit vector ||p-vp||. The radius of the vector in fisheye space is derived from the dot product of the view direction with ||p-vp||. The total expression is
z = acos(vd . ||p-vp||) (||p-vp|| . vu) / (pi/2)
Modifications to this to support off-axis projection involve adding the off-axis vector to the unit vector ||p-vp||. The modification to support smaller fisheye angles is to divide the acos() term by the fisheye angle rather than pi/2. A sensible depth is required so OpenGL can deal with z-buffer depth occlusion, a suitable depth is the projection onto the view direction (vd).
After the geometry has been transformed, it is viewed with an orthographic projection. Geometry below the rim of the hemisphere will have a negative depth (y, as calculated above) and can be removed as such and not passed onto the graphics card, or drawn and let them be pruned by OpenGL with an appropriate use of a near cutting plane.
Test pattern for checking any distortion on the dome.
Support for truncated fisheye projection.
Star field and resolution tests.
Control of tessellation precision.
Ring tunnel (animation).
Toroidal tunnel (Animation).
Hal1200, elumenati projector/lens
Updated to support spherical mirror projection