.
Optical Effects within Water 30.june.1998 GFX

by Hin Jang

Optical effects within water are shafts of light, caustics, and variation in colour. The convergence and divergence of refracted light (i.e., atmospheric scattering) from the water surface creates the shafts of light [1]. Caustics are formed by the intersection of reflected or refracted parallel light rays from the curved nature of the water surface. Varying densities of suspensions account for the colour of the water. The particles scatter and/or absorb light, creating the subtle shifts of colour at different depths. Nishita and Nakamae developed a method of displaying these optical effects [2]. The algorithm avoids a pre-processing step by using a scanline Z-buffer and accumulation buffer. The shafts of light and caustics are formed in a manner similar to calculating the intensity distribution of flux of light in space.


   Render_OpticalEffects()
   {

      subdivide surface of the water into an N by M mesh of triangles
      calculate normal vector at each lattice point
      calculate refracting direction of incident light at each lattice point
      define illumination volumes as the swept area of a triangle along 
         the refracted vectors
      clear accumulation buffer

      for (each scanline) {

         perform hidden surface removal
         store depths of object(s) in Z-buffer

         caustic triangles = intersection points between the illumination
                             volumes and the scan plane

         for (each caustic triangle T) {

            calculate the maximum intensity of scattered light for T
            calculate projected range of T into screen space
            calculate intensity at each pixel in the range via
               linear interpolation 
            store these intensities in an accumulation buffer

         }

         display pixels in accumulation buffer

      }

   }



[1] Klassen, R.V., "Modeling the Effect of the Atmosphere on Light," ACM Transactions on Graphics, 6(3):215-237

[2] Nishita, T., and E. Nakamae, "Method of Displaying Optical Effects within Water using Accumulation Buffer," Computer Graphics, SIGGRAPH 1994 Proceedings, 28(4):373-379


.
Multiresolution Analysis 05.august.1998 GFX

by Hin Jang

Multiresolution analysis, the result of the pioneering efforts by Mallat and Meyer, is the act of decomposing a complex function to a lower level resolution. Detail that is lost from the process is captured in wavelet (or detail) coefficients. As applied to geometry compression, the function is the spatial arrangement of a tesselated surface. Given a mesh of triangles, for example, the vertices of the mesh M j are the weighted averages of the vertices in the refined mesh M j + 1. These averages form a low-pass filter A. The weighted difference of the vertices of the refined mesh yield a high-pass filter B consisting of an array of wavelet coefficients.

               A
      Mj + 1   --->  Mj

      |
      | B
      |
      V

   wavelet
 coefficients


Successive analysis is referred to as a filter bank algorithm. Recovery involves refining the triangles in M j by introducing new vertices at edge midpoints. After applying the refining filter P, the collection of new vertices are perturbed to their correct locations according to the wavelet coefficients. The perturbing is described in the filter Q.
               P
      Mj + 1   <---   Mj

      ^
      |
      | Q
      |

   wavelet
 coefficients

Derivation of the analysis (A, B) and synthesis (P, Q) filters is steeped in wavelet theory [1] [2] [3].



[1] Lounsbery, M., T.D. DeRose, and J. Warren, "Multiresolution Analysis for Surfaces of Arbitrary Topological Type," ACM Transactions on Graphics, 16(1):34-73, January 1997

[2] Mallat, S., "A Theory for Multiresolution Signal Decomposition: The Wavelet Representation," IEEE Transactions on Pattern Analysis and Machine Intelligence, 11(7):674-693, July 1989

[3] Meyer, Y., Wavelets and Operators, Cambridge University Press, 1993

[4] Ponenti, P.J., and J. Liandrat, Numerical Algorithms Based on Biorthogonal Wavelets, NASA CR-198290 ICASE Report No. 96-13, February 1996


.
Adaptive Forward Differencing 03.january.1999 GFX

by Hin Jang

Forward differencing is an ideal method to evaluate a d-dimensional Bézier curve of degree n in that only dn additions per sample are performed. In general, the concept can be derived as follows. Given that

   y  =  f(x)

represents a function that is differentiable in an open interval containing x, the differential of y is
   dy  =  f'(x)dx

where dx is the differential of x. If f(x) is known, then f(x + k) can be approximated via differentials where
   f(x + k)  ~=  f(x) + dy  =  f(x) + f'(x)dx

   k > 0

Within the context of computer graphics programming, the forward difference Df(t) of a function f(t) is
   Df(t)  =  f(t + k) - f(t)

so
   f(t + k)  =  f(t) + Df(t)

in iterative terms,
   fn+1  =  fn + Dfn

evaluating successive function values using the forward difference(s) is known as forward differencing.

The equation for a quadratric Bézier curve is

   p(t)  =  (1 - t)2p0  +  2t(1 - t)p1  +  t2p2

as derived from the general form
             n
            ----
   p(t)  =  \     pi Bi,n(t)
            /
            ----
            i=0

   0 <= t <= 1

with blending functions
                  n!
   Bi,n(t)  =  ----------  (1 - t)n - i ti
               i!(n - i)!
   

For p(t) then,


    p(t)  =  (1 - t)2p0  +  2t(1 - t)p1  +  t2p2
          =  (t2 - 2t + 1)p0  +  (-2t2 + 2t)p1  +  t2p2

   Dp(t)   =  p(t + k)  -  p(t)
           =  ((t + k)2 - 2(t + k) + 1)p0  + (-2(t + k)2 + 2(t + k))p1  +
              (t + k)2p2  -  [(t2 - 2t + 1)p0  +  (-2t2 + 2t)p1  +  t2p2]
           =  (2tk + k2 - 2k)p0  +  (-4tk - 2k2 + 2k)p1  +  (2tk + k2)p2

   D2p(t)  =  Dp(t + k)  -  Dp(t)
           =  (2(t + k)k + k2 - 2k)p0  +  (-4(t + k)k - 2k2 + 2k)p1  +
              (2(t + k)k + k2)p2  -  [(2tk + k2 - 2k)p0  +  (-4tk - 2k2 + 2k)p1  +
              (2tk + k2)p2]
           =  2k2p0  -  4k2p1  +  2k2p2

At initial condition t = 0 with k = STEP = 0.1

     p(0)  =  p0

    Dp(0)  =  (k2 - 2k)p0  +  (-2k2 + 2k)p1  +  k2p2
           =  -0.19p0  +  0.18p1  +  0.01p2

   D2p(0)  =  2k2p0  -  4k2p1  +  2k2p2
           =  0.02p0  -  0.04p1  +  0.02p2


Thus, an implementation of forward differencing to render p(t) would be

   #include <stdio.h>
   #define STEP   0.1      // range = (0, 1]

   typedef struct point   Point;

   struct point {
      float x, y, z;
   };


   //
   // entries are valid for STEP equal to 0.1

   static float M[3][3] = {
      {  1.00,  0.00, 0.00 },
      { -0.19,  0.18, 0.01 },
      {  0.02, -0.04, 0.02 },
   };

   int main(int args, char *argv[]) {

      FILE    *fp;
      Point   p[3];      // control points
      int     i;

      if (args < 2) {
         fprintf(stderr, "usage: %s <filename>", argv[0]);
         exit(1);
      }

      if ((fp = fopen(argv[1], "r")) == NULL) {
         fprintf(stderr, "%s not found\n", argv[1]);
         exit(1);
      }

      i = 0;


      //
      // the call to fscanf() assumes the datafile consists of
      // three rows of three floating point numbers

      while (fscanf(fp, "%f %f %f", &p[i].x, &p[i].y, &p[i].z) != EOF)
         i++;

      Render_Quadratic_BezierCurve(p);

      return 0;
   }


   //
   // replace fprintf() with additional code or appropriate
   // function calls

   void Render_Quadratic_BezierCurve(Point p[3]) {

      float   x, y, z, dx, dy, dz, ddx, ddy, ddz, t;

      x   = p[0].x;
      y   = p[0].y;
      z   = p[0].z;

      dx  = M[1][0]*p[0].x  +  M[1][1]*p[1].x  +  M[1][2]*p[2].x; 
      dy  = M[1][0]*p[0].y  +  M[1][1]*p[1].y  +  M[1][2]*p[2].y; 
      dz  = M[1][0]*p[0].z  +  M[1][1]*p[1].z  +  M[1][2]*p[2].z; 

      ddx = M[2][0]*p[0].x  +  M[2][1]*p[1].x  +  M[2][2]*p[2].x; 
      ddy = M[2][0]*p[0].y  +  M[2][1]*p[1].y  +  M[2][2]*p[2].y; 
      ddz = M[2][0]*p[0].z  +  M[2][1]*p[1].z  +  M[2][2]*p[2].z; 

      fprintf(stdout, "(%f, %f, %f)\n", x, y, z);

      for (t = 0.0; t <= 1.0; t += STEP) {

         x += dx; dx += ddx;
         y += dy; dy += ddy;
         z += dz; dz += ddz;

         fprintf(stdout, "(%f, %f, %f)\n", x, y, z);

      }
   }

Although efficient, Render_Quadratic_BezierCurve( ) can be optimised further. Regardless of the geometry of the curve, p(t) is always evaluated at fixed increments of size STEP. Ideally, however, we want
   || p(t)  -  p(t + k) ||  >>  0

Satisfying this condition for all sample points for all quadratic Bézier curves p(t) requires that k be a function of curvature. In other words, the curve is sampled at non-fixed intervals of the paramteric variable. An adaptive foward differencing algorithm evaluates p(t) at non-fixed intervals [3] [5].



[1] Klassen, R.V., "Integer Forward Differencing of Cubic Polynomials: Analysis and Algorithms," ACM Transactions on Graphics, 10(2):152-181, April 1991

[2] Klassen, R.V., "Exact Integer Hybrid Subdivision and Forward Differencing of Cubics," ACM Transactions on Graphics, 13(3):240-255, July 1994

[3] Lien, S.L., M. Shantz, and V. Pratt, "Adaptive Forward Differencing for Rendering Curves and Surfaces," Computer Graphics, SIGGRAPH 1987 Proceedings, 21(4):111-117

[4] Rappoport, A., "Renderings Curves and Surfaces with Hybrid Subdivision and Forward Differencing," ACM Transcations on Graphics, 10(4):323-341, October 1991

[5] Shantz, M., and S.L. Chang, "Rendering Trimmed NURBS with Adaptive Forward Differencing," Computer Graphics, SIGGRAPH 1988 Proceedings, 22(4):189-196