/*
*----- fjs_fisheyelens.sl
*
* Description:
* A near clip-plane shader that uses raytracing to provide
* a simple fisheye lens for the camera.
*
* Usage:
* User must define a square polygon just beyond the
* near clip-plane distance. Generally, this polygon
* fills the entire viewing frustrum.
*
* This shader is applied to the polygon and the user
* should specify the polygon placement and the maximum
* angle of the lens.
*
* The result is a circular lensed image on the square
* polygon, with black corners. The angular distribution
* is like polar graph paper, with angle increasing
* linearly with distance from the center.
*
* Corners of polygon are assumed to be (in camera space):
* [ scale, scale, zdistance]
* [-scale, scale, zdistance]
* [-scale, -scale, zdistance]
* [ scale, -scale, zdistance]
*
* RIB example:
* Clipping 0.099 1000.0
* Declare "lens_angle" "uniform float"
* Declare "zdistance" "uniform float"
* Declare "scale" "uniform float"
* Surface "fjs_fisheyelens" "lens_angle" [180] "zdistance" [0.1] "scale" [0.1]
* Polygon "P" [0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]
*
* History:
* 12/17/01 - 1.0 - Cleaned up and documented - Frank Summers,
* summers@SpamSucks_stsci.edu
*
*/
surface fjs_fisheyelens (float lens_angle = 180.0;
float zdistance = 0.1;
float scale = 0.1)
{
/* Do not shade near clip-plane polygon more than once
*
* The code below will begin the fisheye raytrace from the
* camera. The near clip-plane polygon will then be hit a
* second time by those rays. Checking raylevel ensures
* that only rays originally from the camera will be shaded.
*/
if (raylevel() > 0) {
Oi = 0.0;
Ci = color(0,0,0);
/* Otherwise, shade with fisheyelens */
} else {
/* Transform the point being shaded into camera coordinates */
varying point Pcam = transform("camera", P);
/* Generate coordinates relative to the center of the polygon */
varying float ss = 0.5*xcomp(Pcam)/scale;
varying float tt = 0.5*ycomp(Pcam)/scale;
/* Calculate distance from center of the polygon */
varying float r = sqrt(ss*ss + tt*tt);
/* If point is outside of polygon filling circle, paint it opaque and black */
if (r > 0.5) {
Oi = 1.0;
Ci = color(0,0,0);
/* Otherwise, calculate ray to trace */
} else {
/* Angle increases linearly with distance from center */
varying float polar_angle = radians(lens_angle)*r;
/* Direction is calculated from angle and shade point coordinates */
varying float z = cos(polar_angle);
varying float x = sin(polar_angle)*ss/r;
varying float y = sin(polar_angle)*tt/r;
/* Set trace direction and start point (at camera) */
varying vector tracedir = vector "camera" (x, y, z);
varying point startpoint = point "camera" (0, 0, 0);
/* Call trace function to perform the raytrace */
Oi = 1.0;
Ci = trace(startpoint, tracedir);
}
}
}