home *** CD-ROM | disk | FTP | other *** search
/ The Party 1994: Try This At Home / disk_image.bin / source / 3d_math / 3dshade.doc < prev    next >
Text File  |  1994-01-04  |  12KB  |  312 lines

  1.  
  2.         ╓────────────────┤% VLA Proudly Presents %├────────────────╖
  3.         ║                                                          ║
  4.         ╙──────────────────────────────────────────────────────────╜
  5.  
  6. ──────────────────────────────────────────────────────────────────────────────
  7.      ────────────────────────────────────────────────────────────────────
  8.           ──────────────────────────────────────────────────────────
  9.                 Three Dimensional Shading In Computer Graphics
  10.           ──────────────────────────────────────────────────────────
  11.      ────────────────────────────────────────────────────────────────────
  12. ──────────────────────────────────────────────────────────────────────────────
  13.                               By Lithium /VLA
  14.  
  15.  
  16.  
  17.     Hopefully you have read the companion document 3DROTATE.DOC, as this one
  18. will build apon the concepts presented in my attempt to teach some of the
  19. math need to make 3D graphics a reality.  This file will cover such important
  20. topics as the Dot Product and how routines are best constructed for real-time 
  21. 3D rotations and planar shading.
  22.  
  23.  
  24.  
  25.  
  26.                         Our Friend, The Dot Product
  27.  
  28.     The Dot Product is a neat relation that will allow you to quickly find
  29. the angle between any two vectors.  It's easiest to explain graphicly, so
  30. I will exercise my extended-ASCII keys.
  31.  
  32.  
  33. Two Vectors A & B
  34.  
  35. A (Xa, Ya, Za)     │A│ = √( (Xa)² + (Ya)² + (Za)² )
  36.  
  37. B (Xb, Yb, Zb)     │B│ = √( (Xb)² + (Yb)² + (Zb)² )
  38.  
  39.  
  40. Where Xa, and the others coorispond to some value on their respective Axis's
  41.  
  42.  
  43.        ┐A
  44.       /
  45.      /
  46.     /
  47.    /  
  48.    \ Θ   <-- Angle Theta between vector A and B
  49.     \
  50.      \
  51.       \
  52.        ┘B
  53.  
  54.  
  55.  Cos(Θ) =  Xa * Xb + Ya * Yb + Za * Zb
  56.           ────────────────────────────
  57.                   │A│*│B│
  58.  
  59.  
  60.  
  61. Example:
  62.  
  63. A (1,2,3)         │A│ = √( 1² + 2² + 3²) = √(14) = 3.7417
  64.  
  65. B (4,5,6)         │b│ = √( 4² + 5² + 6²) = √(77) = 8.7750
  66.  
  67.  
  68.  Cos(Θ) =  1 * 4 + 2 * 5 + 3 * 6   =  4 + 10 + 18    =    32    =  0.9746
  69.            ─────────────────────     ───────────────    ─────
  70.              (3.7417)*(8.7750)           32.8334       32.8334
  71.  
  72.  
  73.  ArcCos (.9746) = 12.9° 
  74.  
  75.  
  76.     So, your wondering how this revolutionizes you code, huh?  Well, remember
  77. our other friend, the Normal vector?  You use Normal vectors that define
  78. the directions of everything in our 3D world.  Let's say that vector A was
  79. the Normal vector from my plane, and B is a vector that shows the direction
  80. that the light in my scene is pointing.  If I do the Dot Product of them,
  81. you will get the angle between them, if that angle is >= 90° and <= 270°
  82. then no light falls on the visible surface and it doesn't need to be 
  83. displayed.
  84.  
  85.  
  86. Also notice, the way the values of the Cosine orient themselves
  87.  
  88.             
  89.  
  90.            90°                  Cos 000° =  1
  91.                                 Cos 090° =  0
  92.             │                   Cos 180° = -1 
  93.   Negative  │  Positive         Cos 270° =  0
  94.             │
  95.             │
  96. 180° ───────┼───────  0°        An angle between a light and a plane that
  97.             │                   is less than 90° or greater than 270° will
  98.             │                   be visible, so you can check if the Cos(Θ)
  99.   Negative  │  Positive         is greater than 0 to see if it is visible.
  100.             │
  101.             │
  102.  
  103.            270°
  104.  
  105.                 
  106.                 How Do You Implement The Code?  Easy As π.
  107.  
  108. Examples in ASM structures
  109.  
  110. We will define our points like this
  111.  
  112.     STRUC XYZs
  113.         Xpos    dd  ?
  114.         Ypos    dd  ?
  115.         Zpos    dd  ?
  116.         Dist    dd  ?       
  117.     ENDS  XYZs              ;size is 16 bytes
  118.  
  119.  
  120. The X,Y,Zpos define a point in 3D space, Dist is the distance from the origin
  121.  
  122. Dist = √( X² + Y² + Z² )
  123.  
  124. Precalculate these values and have them handy in your data area
  125.  
  126.  
  127. Our planes should look something like this
  128.  
  129.     STRUC PlaneSt
  130.         NumPts      db      ?               ;3 or 4
  131.         NormIndex   dw      ?
  132.         PtsIndex    dw      ?
  133.                     dw      ?
  134.                     dw      ?
  135.                     dw      ?
  136.     ENDS  PlaneSt
  137.  
  138. The number of points that in the plane depends on the number your fill
  139. routines can handle you must have at least 3 and more than 6 is not suggested
  140.  
  141.  
  142. Then we set up our data like this
  143.  
  144. MaxPoints   =           100
  145. MaxPlanes   =           100
  146.  
  147. PointList   XYZs        MaxPoints DUP()
  148. PlaneList   PlaneSt     MaxPlanes DUP()
  149. NormalList  XYZs        <0,0,0, 10000h> , MaxPlanes DUP()
  150.  
  151.     Non-ASM User Note:   
  152.             
  153.             I set up points in a structure that had an X,Y,Z and Distance
  154.         value.  I set up a plane structure that had the number of points
  155.         the index number of the normal vector for that plane and the index
  156.         numbers for the points in the plane.
  157.  
  158.             The next lines set up arrays of these points in PointList, and
  159.         the number of points was defined as MaxPoints.  An array of planes
  160.         was created as PlaneList with MaxPlanes as the total number of 
  161.         plane structures in the array.  NormalList is an array of the vectors
  162.         that are normal to the planes, one is set up initally (I'll explain 
  163.         that next) and then one for each possible plane is allocated.
  164.  
  165.  
  166. You'll notice that I defined the first Normal and then created space for 
  167. the rest of the possible normals.  I'll call this first normal, the 
  168. Zero Normal.  It will have special properties for planes that don't shade 
  169. and are never hidden.
  170.  
  171.  
  172.  
  173.     Well, before I start telling all the tricks to the writting code, let me
  174. make sure a couple of points are clear.
  175.  
  176. -       In the 3DROTATE.DOC I said that you could set your view point on the 
  177.     Z-Axis and then figure out if planes were visible by the post-rotation
  178.     Normal vectors, if their Z was > 0 then display, if not, don't
  179.         That is an easy way to set up the data, and I didn't feel like going
  180.     into the Dot Product at the time, so I generalized.  So, what if you
  181.     don't view your plane from the Z-Axis, the answer is you use the...
  182.     
  183.     Dot Product!  
  184.     
  185.     that's right.  The angle will be used now to figure wheither or not to
  186.     display the plane.
  187.  
  188. -       I have been mentioning lights and view points as vectors that I can
  189.     use with the Normal vector from my plane.  To work correctly, these 
  190.     vectors for the lights and view should point in the direction that you
  191.     are looking or the direction that the light is pointing, *NOT* a vector 
  192.     drawn from the origin to the viewer position or light position.
  193.  
  194. -       True Normal vectors only state a direction, and should therefore have
  195.     a unit distance of 1.  This will have the advantage of simplifying the
  196.     math involved to figure you values.  Also, for God's sake, pre-compute
  197.     your normal, don't do this everytime.  Just rotate them when you do your
  198.     points and that will update their direction.
  199.  
  200.         If the Normal's have a length of 1 then │A│*│B│ = 1 * 1 = 1
  201.  
  202.     So:
  203.         Cos(Θ) = Xa * Xb + Ya * Yb + Za * Zb
  204.                  ────────────────────────────
  205.                           │A│*│B│
  206.  
  207.     Is Reduced To:    
  208.         
  209.         Cos(Θ) = Xa * Xb + Ya * Yb + Za * Zb
  210.      
  211.  
  212.     We eliminated a multiply and a divide!  Pat yourself on the back.
  213.  
  214. -       You ASM users might be wondering why I defined my Zero Normal as:
  215.     <0,0,0,10000h>  How does 10000h = a length of 1 ?
  216.  
  217.     Well, this is a trick you can do in ASM, instead of using floating point
  218.     values that will be slow on computers without math co-processors, we can
  219.     use a double word to hold our value.  The high word holds the integer
  220.     value, and the low word is our decimal.  You do all of your computations
  221.     with the whole register, but only pull the high word when you go to 
  222.     display the point.  So, with that under consideration, 10000h = 1.00000
  223.     Not bad for integers.
  224.  
  225.  
  226. -       How does the Zero Normal work?  Since the X,Y,and Z are all 0, the
  227.     Cos(Θ) = 0, so if you always display when Cos(Θ) = 0, then that plane
  228.     will always be seen.
  229.  
  230.  
  231.             So, Beyond The Babble...  How To Set Up Your Code    
  232.  
  233.  
  234. Define Data Points, Normals, and Planes
  235.     Pre-Calculate as many values as possible
  236.  
  237.  Rotate Points and Normals
  238.  
  239.  Determin Visible Planes With Dot Product
  240.     (Save this value if you want to shade)
  241.  
  242.     Sort Visible Planes Back to Front
  243.  
  244.          (Determin Shade From Dot Product)
  245.  
  246.          Clip Plane to fit scene
  247.  
  248.          Draw to the screen
  249.  
  250.  Change Angles
  251.  
  252.  Goto Rotation
  253.  
  254.  
  255.  
  256.         A quick way to figure out which color to shade your plane if you are
  257.     using the double word values like I described before is to take the
  258.     Dot Product result, it will lie between 10000h - 0h if you would like
  259.     say 16 shades over the angles, then take that value and shr ,12 that will
  260.     give you a value from 0h - 10h (0-16, or 17 colors)  if you make 10h into
  261.     0fh, add that offset to a gradient in your palette, then you will have
  262.     the color to fill your polygon with.
  263.  
  264.         Note also that the Cosine function is weighted toward the extremes.
  265.     If you want a smooth palette change as the angles change, your palette
  266.     should weight the gradient accordingly.
  267.  
  268.  
  269.         A useful little relation for depth sorting is to be able to find the
  270.     center of a triangle.
  271.  
  272.         E         The center C = (D + E + F)/3
  273.         ^
  274.        / \        Divide each cooridinate by (Xd + Xe + Xf)/3 = Xc
  275.       / C \         and do the same for the Y's and Z's if you 
  276.      /     \        choose to sort with this method.  Then rotate
  277.    D─────────F      that point and use it to depth sort the planes
  278.  
  279.  
  280. Phong and Goraud Shading
  281.  
  282.     Recently, someone asked me about the practiblity of real-time phong and
  283. goraud shading.  The technique is common to ray-tracers and requires a great
  284. deal of calculation when working with individual rays cast from each pixel,
  285. but when only using this for each plane, it is possible.  This type of shading
  286. involves taking into account the reduced luminousity of light as distance
  287. increases.  For each light, you define a falloff value.  This value should be
  288. the distance a which the light will be at full intensity.  Then at 2*FallOff 
  289. you will have 1/2 intensity, 3*FallOff will yeild 1/3 and so on.  To implement
  290. this type of shading, you will need to determin the distance from the light
  291. to the center of the plane.  If distance < FallOff, then use the normal
  292. intensity.  If it is greater, divide the FallOff value by the distance.  This
  293. will give you a scalar value that you can multiple by the shading color that
  294. the plane should have.  Use that offset and it will be darker since it is
  295. further away from the light source.
  296.     However, to determin the distance form the light to each plane, you must
  297. use a Square Root function, these are inherently slow unless you don't care
  298. about accuracy.  Also, it would be difficult to notice the use of this 
  299. technique unless you have a relatively small FallOff value and your objects
  300. move about in the low intesity boundries.
  301.  
  302.  
  303.  
  304.  
  305. Well, that's all that I feel like doing tonight, and besides, Star Trek is on!
  306. So, see VLA.NFO for information about contacting myself or any of the other 
  307. members of VLA.
  308.  
  309.                             Happy Coding!
  310.  
  311.  
  312.