home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / PHONG.ZIP / PHONG.TXT
Encoding:
Text File  |  1996-04-26  |  24.7 KB  |  933 lines

  1.  
  2.  
  3.         OTMPHONG.DOC - A new approximation technique for the Phong
  4.  
  5.                        shading model based on linear interpolation
  6.  
  7.                        of angles
  8.  
  9.  
  10.         released 3-30-95
  11.  
  12.         by Voltaire/OTM [Zach Mortensen]
  13.  
  14.  
  15.         email -
  16.  
  17.         mortens1@nersc.gov
  18.  
  19.  
  20.         IRC -
  21.  
  22.         Volt in #otm, #coders
  23.  
  24.  
  25.  
  26. INTRODUCTION
  27.  
  28.  
  29.                 Realtime phong shading has always been a goal for 3d
  30.  
  31.         coders, however the massive amount of calculations involved
  32.  
  33.         has (until recently) hampered progress in this area.  When I
  34.  
  35.         first heard the term 'realtime phong shading' mentioned about 6
  36.  
  37.         months ago, I laughed to myself at what I perceived was an
  38.  
  39.         oxymoron.  In my experience at the time (derived from reading
  40.  
  41.         several 3d documents), phong shading required a tremendous
  42.  
  43.         amount of interpolation and one square root per pixel.  Even
  44.  
  45.         with lookup tables for the square root function, there was no
  46.  
  47.         way that this algorithm would be fast enough to use in
  48.  
  49.         realtime.  Early reports from other coders attempting realtime
  50.  
  51.         phong shading proved this, the fastest code I heard of could
  52.  
  53.         draw around 1500 triangles per second.
  54.  
  55.  
  56.                 Phong shading never really was a goal of mine.  I am a
  57.  
  58.         pretty lazy person, I could think of a thousand ways I would
  59.  
  60.         rather spend my time than implementing an inherently slow
  61.  
  62.         algorithm in my code and trying to optimize it.  Until about a
  63.  
  64.         week ago that is, when I received a little demo called CHEERIO
  65.  
  66.         by Phred/OTM.  Phred and I have been good friends for quite
  67.  
  68.         awhile, and we both write vector code.  We have helped each
  69.  
  70.         other improve the speed of our code dramatically by sharing our
  71.  
  72.         ideas, 2 heads are definitely better than 1!  Anyway, there
  73.  
  74.         were rumors flying around that CHEERIO was phong shaded, when
  75.  
  76.         in reality it was really nice gouraud shading.  I took a close
  77.  
  78.         look and...well, it looked like phong but Phred wasn't around
  79.  
  80.         to correct us, so I went on believing he had coded a phong fill
  81.  
  82.         that was as fast as my gouraud fill.  Part of the reason Phred
  83.  
  84.         and I have made our code so fast is competition, neither of us
  85.  
  86.         can stand being outdone by the other.  So whether I wanted to
  87.  
  88.         or not, I had to come up with a fast phong fill SOON if I were
  89.  
  90.         to save face.
  91.  
  92.  
  93.                 The fastest method I knew of was using a Taylor series
  94.  
  95.         to approximate color values.  This method involves a fairly
  96.  
  97.         fast inner loop with a lot of precalculation.  It also requires
  98.  
  99.         a thorough knowledge of calculus.  Believe me, doing Taylor
  100.  
  101.         series on your homework is a lot easier than trying to
  102.  
  103.         implement one in the real world for some strange reason.  So
  104.  
  105.         that is where I started, I was deriving the Taylor
  106.  
  107.         approximation for phong shading when I stumbled upon what
  108.  
  109.         seemed to me an obvious shortcut that would make phong filling
  110.  
  111.         nearly as fast as gouraud filling.  I also believe I am the
  112.  
  113.         first to come up with this method, since I have seen no
  114.  
  115.         articles about it, and I have yet to see realtime phong shading
  116.  
  117.         in a demo or game.
  118.  
  119.  
  120.                 OK, now on to the fun stuff...
  121.  
  122.  
  123.  
  124.  
  125. THE PHONG ILLUMINATION MODEL
  126.  
  127.  
  128.  
  129.                 This is not a text on phong illumination, but on phong
  130.  
  131.         SHADING.  They are two very different things.  Whether you use
  132.  
  133.         phong shading or not, you can use phong illumination with your
  134.  
  135.         lambert or gouraud shading to make your colors look more
  136.  
  137.         realistic.  I don't want to get into how this formula is
  138.  
  139.         derived, so I will just give you the low down dirty goods.
  140.  
  141.  
  142.  
  143.         color = specular + (cos x) * diffuse + (cos x)^n * specular
  144.  
  145.  
  146.  
  147.                 Make sure you set up your palette in this way. In a
  148.  
  149.         nutshell, the ambient component defines the color of an object
  150.  
  151.         when no light is directly striking it, the diffuse component
  152.  
  153.         defines the color of the object, and the specular component
  154.  
  155.         defines the color of the highlight made when light strikes the
  156.  
  157.         object directly.  x should have a range of 0 to 90 degrees,
  158.  
  159.         since that is the range of angles possible when light
  160.  
  161.         intersects a visible plane.  The power n in the specular
  162.  
  163.         component defines certain attributes about the material, the
  164.  
  165.         greater the power n, the shinier the material will appear to be
  166.  
  167.         (i.e. the specular highlight will be smaller and brighter as n
  168.  
  169.         increases).
  170.  
  171.  
  172.  
  173.  
  174. THE PHONG SHADING MODEL
  175.  
  176.  
  177.  
  178.                 The idea behind phong shading is to find the exact
  179.  
  180.         color value of each pixel.  In its most common form, the phong
  181.  
  182.         shading model is as follows:
  183.  
  184.  
  185.         1) determine a normal vector at each vertex of a polygon, the
  186.  
  187.            same normal vector used in gouraud shading.
  188.  
  189.  
  190.         2) interpolate normal vectors along the edges of the polygon.
  191.  
  192.  
  193.         3) interpolate normal vectors across each scanline, so you have
  194.  
  195.            one normal vector for each pixel in the polygon.
  196.  
  197.  
  198.         3) determine the color at each pixel using the dot product of
  199.  
  200.            the normal vector at that pixel and the light vector, the
  201.  
  202.            same method used in gouraud and lambert shading.  Since the
  203.  
  204.            interpolated normals are not of constant length, this step
  205.  
  206.            requires a square root to find the length of the normal.
  207.  
  208.  
  209.  
  210.                 This shading model produces impressive results.  A new
  211.  
  212.         color is calculated for each pixel, and the color gradient
  213.  
  214.         across a plane is non linear.
  215.  
  216.  
  217.                 However it is also VERY SLOW if implemented as it is
  218.  
  219.         shown here.  In order to linearly interpolate a vector, one
  220.  
  221.         must interpolate x, y, and z coordinates.  This task is not
  222.  
  223.         nearly as time consuming as the dot product, which requires 4
  224.  
  225.         multiplies, 2 adds, a divide and a square root per PIXEL.  A
  226.  
  227.         few optimizations can be performed that eliminate one multiply
  228.  
  229.         and replace the square root with a table lookup, but 3
  230.  
  231.         multiplies and a divide per pixel are far too slow to be used
  232.  
  233.         in realtime.
  234.  
  235.  
  236.  
  237. OPTIMIZING THE PHONG SHADING MODEL
  238.  
  239.  
  240.  
  241.                 Lets mathematically break down the phong shading model.
  242.  
  243.         After all is said and done, you are left with the dot product
  244.  
  245.         of the pixel normal vector and the light vector divided by the
  246.  
  247.         product of the magnitudes of these two vectors.  Another way to
  248.  
  249.         express this value is (cos Θ), where Θ is the smallest angle
  250.  
  251.         between the two vectors.
  252.  
  253.  
  254.         u = pixel normal vector
  255.  
  256.         v = light vector
  257.  
  258.  
  259.         u dot v = cos Θ * |u| * |v|
  260.  
  261.  
  262.                  u dot v
  263.  
  264.         cos Θ = ---------
  265.  
  266.                 |u| * |v|
  267.  
  268.  
  269.                 So the dot product of a normal vector and a light vector
  270.  
  271.         divided by the product of the magnitudes of the two vectors is equal
  272.  
  273.         to the cosine of the smallest angle between the two vectors.  This
  274.  
  275.         should be nothing new, it is the same technique used to find color
  276.  
  277.         values in the lambert and gouraud shading techniques.  Lets attempt
  278.  
  279.         to graphically represent what is going on with phong, gouraud and
  280.  
  281.         lambert shading.
  282.  
  283.  
  284.  
  285.                                 graph of y = cos Θ (*)
  286.  
  287.         |
  288.  
  289.         |
  290.  
  291.         |*    *
  292.  
  293.         |          *
  294.  
  295.         |             *
  296.  
  297.         |                *
  298.  
  299.         |                   *
  300.  
  301.         |                     *
  302.  
  303.         |                       *
  304.  
  305.         |                         *
  306.  
  307.       y |                          *
  308.  
  309.         |                           *
  310.  
  311.         |                            *
  312.  
  313.         |                             *
  314.  
  315.         |                              *
  316.  
  317.         |                               *
  318.  
  319.         |                                *
  320.  
  321.         |                                 *
  322.  
  323.         |                                  *
  324.  
  325.         |                                   *
  326.  
  327.         +------------------------------------------
  328.  
  329.                             Θ
  330.  
  331.  
  332.                 The phong shading model states that the intensity of light
  333.  
  334.         at a given point is given by the dot product of the light and normal
  335.  
  336.         vectors divided by the product of the magnitudes of the two vectors.
  337.  
  338.         Flat shading is the roughest approximation of this, planes are
  339.  
  340.         rendered in a single color which is determined by the cosine of the
  341.  
  342.         angle between the plane's normal vector and the light vector.  If
  343.  
  344.         we graph the intensity of light striking flat shaded planes, we
  345.  
  346.         should find that they roughly form a cosine curve, since the color
  347.  
  348.         values at certain points are determined by the cosine of the angle
  349.  
  350.         between two vectors
  351.  
  352.  
  353.  
  354.                           graph of Intensity = cos Θ (*)
  355.  
  356.         |      flat shading approximations of light intensity shown as (X)
  357.  
  358.         |
  359.  
  360.         |*XXXX*XX               dΘ  (angle between normal vectors)
  361.  
  362.         |          *       -------------
  363.  
  364.         |        XXXXX*XXXX            |
  365.  
  366.         |                *             | dI  (change in intensity)
  367.  
  368.         |                   *          |
  369.  
  370.         |                  XXX*XXXXXX  |
  371.  
  372.         |                       *
  373.  
  374.       I |                         *
  375.  
  376.         |                          *
  377.  
  378.         |                           *XXXXXX
  379.  
  380.         |                            *
  381.  
  382.         |                             *
  383.  
  384.         |                              *
  385.  
  386.         |                               *
  387.  
  388.         |                                *
  389.  
  390.         |                                 *XXXXX
  391.  
  392.         |                                  *
  393.  
  394.         |                                   *
  395.  
  396.         +------------------------------------------
  397.  
  398.                              Θ
  399.  
  400.  
  401.                 This graph tells us something that we already know by
  402.  
  403.         practical experience, that flat shading is very inaccurate for large
  404.  
  405.         values of dΘ, and much more accurate for small values of dΘ.  This
  406.  
  407.         means that the shading appears smoother when the angle between
  408.  
  409.         normals (and therefore between planes) is very small.
  410.  
  411.  
  412.                 Now lets consider gouraud shading.  Gouraud shading is a
  413.  
  414.         linear interpolation of color between known intensities of light.
  415.  
  416.         The known intensities in gouraud shading are defined at each
  417.  
  418.         vertex, once again by use of the dot product.  In this case, the
  419.  
  420.         normal vector at each polygon vertex is the average of the normal
  421.  
  422.         vectors (the ones used in flat shading) for all planes which share
  423.  
  424.         that vertex.  Normals of planes which are greater than 90 and less
  425.  
  426.         than 270 degrees from the plane containing the vertex in question are
  427.  
  428.         not considered in the average because the two planes are facing
  429.  
  430.         away from each other.  If we plot interpolated intensities used in
  431.  
  432.         gouraud shading against the cosine curve, it is evident that gouraud
  433.  
  434.         shading is a much more accurate approximation than flat shading.
  435.  
  436.  
  437.  
  438.                         graph of Intensity = cos Θ (*)
  439.  
  440.         |        interpolated light intensities shown as (X)
  441.  
  442.         | ---------------------------------+
  443.  
  444.         |*X   *                            | in this region, the linear
  445.  
  446.         |  XXXX ---*--------+              | approximation is always going to
  447.  
  448.         |      XXX    *     | dI (error)   | be inaccurate without a very
  449.  
  450.         |         XXXX --*--+              | small value for dΘ
  451.  
  452.         |             XXX   *              |
  453.  
  454.         |                XXXXX*  --------------+
  455.  
  456.         ||____________________|X*              |
  457.  
  458.       I |        dΘ              X*            |
  459.  
  460.         |                         X*           | in this region, a gouraud
  461.  
  462.         |                          X*          | approximation is nearly
  463.  
  464.         |                           X*         | perfect because cos x is
  465.  
  466.         |                            X*        | nearly linear
  467.  
  468.         |                             X*       |
  469.  
  470.         |                              X*      |
  471.  
  472.         |                               X*     |
  473.  
  474.         |                                X*    |
  475.  
  476.         |                                 X*   |
  477.  
  478.         |                                  X*  |
  479.  
  480.         +------------------------------------------
  481.  
  482.                            Θ
  483.  
  484.  
  485.                 This graph tells us that gouraud shading is very accurate
  486.  
  487.         as Θ->90.  However, if Θ is small and dΘ is large, gouraud shading
  488.  
  489.         will look like an obvious linear approximation.  This can be avoided
  490.  
  491.         by using smaller values of dΘ (i.e. use more polygons to fill in the
  492.  
  493.         gaps in the interpolation).  With enough polygons, gouraud shading
  494.  
  495.         can be 100% correct.
  496.  
  497.  
  498.                 Phong shading is the most correct method of shading because
  499.  
  500.         it is not an approximation, distinct colors are determined for each
  501.  
  502.         pixel.  These values follow the cosine curve exactly, because the
  503.  
  504.         intensity of each pixel was calculated using a dot product, which
  505.  
  506.         eventually yields the cosine of the angle between the plane at 
  507.  
  508.         that pixel and the light vector.  If we plot phong shading 
  509.  
  510.         intensities with the cosine curve, we find that the values 
  511.  
  512.         follow the function exactly.
  513.  
  514.  
  515.  
  516.                         graph of Intensity = cos Θ (*)
  517.  
  518.         |            phong light intensities shown as (X)
  519.  
  520.         |
  521.  
  522.         |X    X
  523.  
  524.         |          X
  525.  
  526.         |             X
  527.  
  528.         |                X
  529.  
  530.         |                   X
  531.  
  532.         |                     X
  533.  
  534.         |                       X
  535.  
  536.         |                         X
  537.  
  538.       I |                          X
  539.  
  540.         |                           X
  541.  
  542.         |                            X
  543.  
  544.         |                             X
  545.  
  546.         |                              X
  547.  
  548.         |                               X
  549.  
  550.         |                                X
  551.  
  552.         |                                 X
  553.  
  554.         |                                  X
  555.  
  556.         |                                   X
  557.  
  558.         +------------------------------------------
  559.  
  560.                              Θ
  561.  
  562.  
  563.                 Once again, shadings calculated using the phong model follow
  564.  
  565.         the cosine curve, because the dot product between the normal vector
  566.  
  567.         at each pixel and the light vector can be simplified to a function
  568.  
  569.         involving cos Θ.
  570.  
  571.  
  572.  
  573. TAYLOR APPROXIMATIONS
  574.  
  575.  
  576.                 Now that we know a function which gives the intensity of
  577.  
  578.         light at a given pixel, we need to find a fast way to evaluate that
  579.  
  580.         function.  Most people seem to know that Taylor series can be used
  581.  
  582.         for phong shading, but I have never met anyone that was able to
  583.  
  584.         tell me that the cosine function would be the function that is
  585.  
  586.         approximated.  The fact that vector coders are afraid of math is
  587.  
  588.         disturbing to me.
  589.  
  590.  
  591.                 The Taylor approximation for cos(x) is given by the following
  592.  
  593.         series:
  594.  
  595.  
  596.                     x^2   x^4   x^6                      x^(2n)
  597.  
  598.         cos x = x - --- + --- - --- + ... + (-1)^(n-1) * ------
  599.  
  600.                      2!    4!    6!                       (2n)!
  601.  
  602.  
  603.         Actually I think that is a Maclaurin series, which is nothing more
  604.  
  605.         than a Taylor series expanded about the point x = 0.  In any case,
  606.  
  607.         you can use any number of terms in a Taylor series to approximate
  608.  
  609.         a function.  The more terms you use, the more accurate your
  610.  
  611.         approximation will be...and the slower your approximation will be.
  612.  
  613.         The first two terms of the series for cos x are sufficient to give
  614.  
  615.         an accurate approximation from x = 0 to x = 90, which are the limits
  616.  
  617.         of Θ between the light and visible facets.
  618.  
  619.  
  620.                 This is about as far as I got with the Taylor approximation
  621.  
  622.         method for phong shading.  Once I got to this point, the proverbial
  623.  
  624.         light bulb clicked on inside my head, and I forgot all about Taylor
  625.  
  626.         series because I came up with a faster method.
  627.  
  628.  
  629.  
  630. LINEAR INTERPOLATION OF ANGLES
  631.  
  632.  
  633.                 To set the scene for you, I was riding the bus to school
  634.  
  635.         about at about 8:00 in the morning when I thought I would do a bit
  636.  
  637.         of work on the phong algorithm.  The bus ride is about 30 minutes and
  638.  
  639.         is usually devoid of any excitement, so I whipped out my trust pad
  640.  
  641.         of graph paper and started grinding out formulas.  I got really
  642.  
  643.         excited when I arrived at the Taylor approximation, but I just about
  644.  
  645.         jumped through the roof when this thought entered my mind.
  646.  
  647.  
  648.                 I realized that the Taylor approximation for phong shading
  649.  
  650.         basically interpolates values along the curve I = cos(Θ) just as
  651.  
  652.         gouraud shading linearly interpolates values, except the values for
  653.  
  654.         phong shading happen to fall directly ON the cosine curve.  The
  655.  
  656.         problem is that the cosine curve is not linear, therefore phong
  657.  
  658.         interpolation is much more complicated than gouraud interpolation.
  659.  
  660.  
  661.                 Then I stepped back and looked at the problem from another
  662.  
  663.         angle (punny).  If it were possible to interpolate some other value
  664.  
  665.         related to cos(Θ), and if this other value changed in a linear
  666.  
  667.         fashion, it would be possible to create a lookup table that related
  668.  
  669.         cos(Θ) to this other value.  After a bit of deep thinking, I realized
  670.  
  671.         that I was staring right at such a value, Θ!  The angle between the
  672.  
  673.         light vector and the normal vector at each vertex of a plane
  674.  
  675.         changes in a linear fashion as you go from one vertex to the next, and
  676.  
  677.         from one edge of the plane to the next across each scanline.
  678.  
  679.  
  680.                 As soon as it hit me, this idea made perfect sense.  The phong
  681.  
  682.         shading model calls for normal vectors to be linearly interpolated
  683.  
  684.         from vertex to vertex and from edge to edge.  When I thought about
  685.  
  686.         this a bit further, it seemed totally ridiculous.  The actual
  687.  
  688.         <x,y,z> coordinates of these normals do not matter one bit, only
  689.  
  690.         the angle between the vector defined by these coordinates and the
  691.  
  692.         light vector.  Why interpolate 3 coordinates per pixel when they are
  693.  
  694.         just an intermediate step in finding the angle between two vectors?
  695.  
  696.  
  697.                 So angular interpolation eliminates the interpolation of a
  698.  
  699.         whole vector.  But that's not all, it also eliminates the dot product
  700.  
  701.         which was previously needed to find the cosine of the angle between
  702.  
  703.         the normals and the light.  Without the dot product or vector
  704.  
  705.         interpolation,  there is nothing left of the traditional method of
  706.  
  707.         phong shading.  All that needs to be done is interpolate angles
  708.  
  709.         across the plane, and look up the cosine of those angles in a lookup
  710.  
  711.         table.  Once you know the cosine, the rest is easy.
  712.  
  713.  
  714.                 Using this method, an existing gouraud fill can be converted
  715.  
  716.         to a phong fill very very easily.  Instead of interpolating colors
  717.  
  718.         across the plane, interpolate angles instead.  If you are smart about
  719.  
  720.         the way you express your angles, they can be represented in a single
  721.  
  722.         byte.  Remember that the only possible values for the smallest angle
  723.  
  724.         between a normal vector and a light vector are 0 to 90 degrees.
  725.  
  726.  
  727.                 After you have interpolated an angle and looked up its
  728.  
  729.         cosine, all you need to do is plot a pixel of the correct color.
  730.  
  731.         The color calculations for each pixel are the same as those for
  732.  
  733.         lambert and gouraud shading.  Multiply the cosine by the number of
  734.  
  735.         colors in the gradated palette range and add the result to the base
  736.  
  737.         color of the range.
  738.  
  739.  
  740.                 Of course, you need to determine the angle between the light
  741.  
  742.         and the normal vectors at each vertex.  This can be accomplished by
  743.  
  744.         the inverse cosine function.  By taking the inverse cosine of the
  745.  
  746.         cosine, you get the angle as a result.  Try to remember your trig
  747.  
  748.         classes.
  749.  
  750.  
  751.  
  752. LIMITATIONS
  753.  
  754.  
  755.                 Angular interpolation is correct in 99% of all possible
  756.  
  757.         cases.  The only cases when it will not be correct is when the
  758.  
  759.         angles at any two or more vertices are equal.  Interpolated vector
  760.  
  761.         phong shading will display a specular highlight inside the plane in
  762.  
  763.         such a case, but interpolated angle phong shading will render the
  764.  
  765.         plane in a solid color because the difference between the angles at
  766.  
  767.         the vertices is 0, there will be no change in the angle across the
  768.  
  769.         plane.
  770.  
  771.  
  772.  
  773. CRITICISM AND RESPONSE SESSION
  774.  
  775.  
  776.                 The preliminary release of demos incorporating this technique
  777.  
  778.         were met with a bit of criticism, most of which was caused by
  779.  
  780.         ignorance.  Here are a few common criticisms of this technique and
  781.  
  782.         my responses.
  783.  
  784.  
  785.  
  786.         "You are interpolating something linearly, and linear interpolation
  787.  
  788.         is gouraud shading"
  789.  
  790.  
  791.         Do your homework.  The phong model calls for linear interpolation of
  792.  
  793.         normal vectors, and it is obviously not gouraud shading.
  794.  
  795.  
  796.  
  797.         "It looks a lot like gouraud shading"
  798.  
  799.  
  800.         Yes it does.  Refer to the section where I plotted intensities based
  801.  
  802.         on various shading techniques, and take a look at the graphs of
  803.  
  804.         Intensity vs. Θ.  You will find that for a small dΘ, gouraud shading
  805.  
  806.         looks very much like phong shading.  However, phong shading can
  807.  
  808.         achieve this result with a much larger dΘ, which means less facets.
  809.  
  810.  
  811.  
  812.         "I see no specular highlight"
  813.  
  814.  
  815.         The first version I released used a linear palette, not a palette
  816.  
  817.         based on the phong illumination model.  Without the phong
  818.  
  819.         illumination model, it is very hard to make specular highlights look
  820.  
  821.         correct.  The palette has now been corrected to conform to the phong
  822.  
  823.         illumination model.
  824.  
  825.  
  826.  
  827.         "You still can't get a highlight in the center of a single polygon"
  828.  
  829.  
  830.         Well, I think that the speed of this method is a reasonable tradeoff.
  831.  
  832.         Specular highlights appear between polygons with this method, and
  833.  
  834.         the difference is not too noticeable.
  835.  
  836.  
  837.  
  838.         "The specular highlights are no different than gouraud specular
  839.  
  840.          highlights"
  841.  
  842.  
  843.         Take a closer look.  With gouraud shading, specular highlights are
  844.  
  845.         gradated in a linear manner.  With phong shading, the gradation of
  846.  
  847.         colors is nonlinear because it follows the cosine curve.
  848.  
  849.  
  850.  
  851. CLOSING COMMENTS
  852.  
  853.  
  854.                 Angular interpolated phong shading is new as far as I know.
  855.  
  856.         If you decide to use this technique in any of your code, please give
  857.  
  858.         me appropriate credit.  I am not asking for a cut of your royalties,
  859.  
  860.         just to have my name mentioned somewhere.  I have always made it a
  861.  
  862.         point to give credit where credit is due, and I would appreciate if
  863.  
  864.         you would do the same.  Someone along the line actually has to put in
  865.  
  866.         some hard work to develop the algorithms that we all use.
  867.  
  868.  
  869.  
  870. GREETS
  871.  
  872.  
  873.         Siri                    - you are the love of my life
  874.  
  875.         OTM                     - I...have...nothing...to...say
  876.  
  877.         Phred/OTM               - good vector conversation
  878.  
  879.         Rich Beerman            - our game will rule
  880.  
  881.         Darkshade               - for always being helpful
  882.  
  883.         THEFAKER/S!P            - infinite humility :)
  884.  
  885.         Sami Nopanen            - cacheman...
  886.  
  887.         Tran and Daredevil      - PMODE/W, gotta love it
  888.  
  889.         VLA                     - for not releasing any more 3d docs :)
  890.  
  891.  
  892.         all my #coders buddies
  893.  
  894.         bri_acid
  895.  
  896.         MainFrame
  897.  
  898.         StarScream
  899.  
  900.         ae-
  901.  
  902.         fysx
  903.  
  904.         phoebus
  905.  
  906.         doom
  907.  
  908.         Moomin
  909.  
  910.         Simm
  911.  
  912.         LiveFire
  913.  
  914.         MArtist
  915.  
  916.         Zed-
  917.  
  918.         Omni
  919.  
  920.         ior
  921.  
  922.         Kodiak_
  923.  
  924.         Saeger
  925.  
  926.         anixter
  927.  
  928.         Hasty
  929.  
  930.  
  931.         and everyone else I forgot...
  932.  
  933.