⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 engine07.shtml

📁 关于windows游戏编程的一些文章还有相关图形
💻 SHTML
📖 第 1 页 / 共 2 页
字号:
 */</font>
.
.
.
cPatch <font color="navy">*</font>pSrc<font color="navy">, *</font>pDest<font color="navy">, *</font>pNext<font color="navy">;</font>
<font color="blue">double</font> FF<font color="navy">,</font> deltaRad<font color="navy">;</font>

<font color="blue">while</font><font color="navy">( (</font> pSrc <font color="navy">=</font> FindBrightestPatch<font color="navy">() ) !=</font> NULL <font color="navy">) {</font>
  <font color="blue">for</font><font color="navy">(</font> pDest <font color="navy">=</font> pPatchList<font color="navy">;</font> pDest<font color="navy">;</font> pDest <font color="navy">=</font> pNext <font color="navy">) {</font>
    pNext <font color="navy">=</font> pDest<font color="navy">-&gt;</font>d_pNext<font color="navy">;</font>

    FF <font color="navy">=</font> FormFactor<font color="navy">(</font> pSrc<font color="navy">,</font> pDest <font color="navy">);</font>
    <font color="blue">if</font><font color="navy">( !</font>FF <font color="navy">)</font> <font color="blue">continue</font><font color="navy">;</font>

    deltaRad <font color="navy">=</font> pSrc<font color="navy">-&gt;</font>d_deltaRad <font color="navy">*</font> pDest<font color="navy">-&gt;</font>d_reflect
             <font color="navy">*</font> FF <font color="navy">*</font> H <font color="navy">*</font> pSrc<font color="navy">-&gt;</font>d_area <font color="navy">/</font> pDest<font color="navy">-></font>d_area<font color="navy">;</font>
    pDest<font color="navy">-&gt;</font>d_deltaRad <font color="navy">+=</font> deltaRad<font color="navy">;</font>
    pDest<font color="navy">-&gt;</font>d_rad <font color="navy">+=</font> deltaRad<font color="navy">;</font>
  <font color="navy">}</font>
<font color="navy">}</font>
.
.
.
<font color="green">
/* There's an extra multiply and divide that could
 * also be removed but I left it in because
 * src.area/dest.area is a ratio, it's easier to
 * understand what's going on.
 */</font>
<font color="blue">double</font> FormFactor<font color="navy">(</font> cPatch <font color="navy">*</font>pSrc<font color="navy">,</font> cPatch <font color="navy">*</font>pDest <font color="navy">) {</font>
  <font color="blue">double</font>   H<font color="navy">,</font> angle1<font color="navy">,</font> angle2<font color="navy">,</font> dist<font color="navy">,</font> factor<font color="navy">;</font>
  cVector3 vec<font color="navy">;</font>

  H <font color="navy">=</font> LineOfSight<font color="navy">(</font> pSrc<font color="navy">,</font> pDest <font color="navy">);</font>
  <font color="blue">if</font><font color="navy">( !</font>H <font color="navy">)</font> <font color="blue">return</font> <font color="red">0.0</font><font color="navy">;</font>

  vec <font color="navy">=</font> pDest<font color="navy">-&gt;</font>d_center <font color="navy">-</font> pSrc<font color="navy">-&gt;</font>d_center<font color="navy">;</font>
  dist <font color="navy">=</font> vec<font color="navy">.</font>Length<font color="navy">()</font><font color="navy">;</font>
  vec <font color="navy">/=</font> dist<font color="navy">;</font>

  angle1 <font color="navy">=</font> vec <font color="navy">|</font> pSrc<font color="navy">-&gt;</font>d_pPoly<font color="navy">-&gt;</font>GetNormal<font color="navy">()</font><font color="navy">;</font>
  angle2 <font color="navy">=</font> <font color="navy">-(</font> vec <font color="navy">|</font> pDest<font color="navy">-&gt;</font>d_pPoly<font color="navy">-&gt;</font>GetNormal<font color="navy">() )</font><font color="navy">;</font>

  factor <font color="navy">=</font> angle1 <font color="navy">*</font> angle2 <font color="navy">*</font> pDest<font color="navy">-&gt;</font>d_area <font color="navy">*</font> H<font color="navy">;</font>
  factor <font color="navy">/=</font> PI <font color="navy">*</font> dist <font color="navy">*</font> dist<font color="navy">;</font>

  <font color="blue">return</font> factor<font color="navy">;</font>
<font color="navy">}</font>
</pre>
<font face="arial" size="-1">
Often when rendering large models it's a good idea to see the work in progress so that you can stop if it
 isn't going quite as planned.  Rendering patches to the screen shouldn't prove to be a big challenge for
 you battle hardened 3D veterans but there will be little problem: at the start of the program the light
 level for most polygons will be zero!  The solution is to compensate by adding the <i>global ambient</i>
 term to each patch as it is being rendered.  Note that the global ambient term is <b>ONLY</b> for rendering
 while calculating because it will approach zero as the calculation nears completion.  The global ambient
 term is calculated thusly:<br>
</font>
<pre>
<font color="green">/* Ambient term calculation.  Reflective term can be
 * used later to speed up ambient term updates
 * and prevent infinite looping.
 */</font>
cPatch *</font>pPatch<font color="navy">, *</font>pNext<font color="navy">;</font>
<font color="blue">double</font> ambient<font color="navy">,</font> reflect<font color="navy">,</font> area<font color="navy">;</font>

ambient <font color="navy">=</font> <font color="red">0.0</font><font color="navy">;</font>
reflect <font color="navy">=</font> <font color="red">0.0</font><font color="navy">;</font>
area <font color="navy">=</font> <font color="red">0.0</font><font color="navy">;</font>
<font color="blue">for</font><font color="navy">(</font> pPatch <font color="navy">=</font> pPatchList<font color="navy">;</font> pPatch<font color="navy">;</font> pPatch <font color="navy">=</font> pPatch <font color="navy">) {</font>
  pNext <font color="navy">=</font> pPatch<font color="navy">-&gt;</font>d_pNext<font color="navy">;</font>
  ambient <font color="navy">+=</font> pPatch<font color="navy">-&gt;</font>d_deltaRad <font color="navy">*</font> pPatch<font color="navy">-&gt;</font>d_area<font color="navy">;</font>
  reflect <font color="navy">+=</font> pPatch<font color="navy">-&gt;</font>d_reflect <font color="navy">*</font> pPatch<font color="navy">-&gt;</font>d_area<font color="navy">;</font>
  area <font color="navy">+=</font> pPatch<font color="navy">-&gt;</font>d_area<font color="navy">;</font>
<font color="navy">}</font>

reflect <font color="navy">/=</font> area<font color="navy">;</font>
<font color="green">// &lt;= 0 - almost all walls black
// &gt;= 1 - all walls white, infinite loop.</font>
<font color="blue">if</font><font color="navy">(</font> reflect <font color="navy">&lt;=</font> <font color="red">0.0</font> <font color="navy">||</font> reflect <font color="navy">&gt;=</font> <font color="red">1.0</font> <font color="navy">)</font> return<font color="navy">;</font>

reflect <font color="navy">=</font> <font color="red">1.0</font> <font color="navy">/ (</font> <font color="red">1.0</font> <font color="navy">-</font> reflect <font color="navy">);</font>

ambient <font color="navy">*=</font> reflect <font color="navy">/</font> area<font color="navy">;</font>
</pre>
<font face="arial" size="-1">
Now that you know everything you need for your first radiosity processor, let's take a look at some ways to speed
 things up and avoid pitfalls.<br>
<br>
<hr>
 &nbsp; <b>Patches: Triangles or Rectangles?</b><br>
<br>
 There are two basic options for splitting polygons into patches: triangles and rectangles.  I tried
 triangles first because<br>
<ul>
<li>Their area is easy to calculate.
<li>Their corners are (relatively) easy to calculate.
<li>The triangle patches stay exactly within the boundaries of the region of the light map of the polygon
 they're associated to.  Go ahead, say it six times fast, I dare you. P:
<li>When <i>subdividing</i> a patch into smaller pieces I could use the middle of each edge as the points
 for the new vertexes, giving me four new patches exactly 1/4 the size.  The added advantage here was that
 if the original patch was very tall and very narrow (not good) then each of the sub patches would be 1/2
 the size and 1/2 the width, bringing them gradually closer to right angled (better).
</ul>
They were great for a brief time but I quickly realized why they weren't used in games like quake and
 half-life:  <i>They look like crap</i>.  So I switched to square patches and discovered many advantages.
<ul>
<li>Square patches are even easier to subdivide.
<li>They don't require information on where the corners are, just the width and height so they save time
 and ram.  Schwinnng!  <i>Party on Wayne.  Party on Garth.</i>
<li>Converting square patches back into light maps is a lot simpler - you don't have to rasterize triangles
 or worry about floating point imprecision.
<li>Squares are much better area to approximate over than irregular triangles, so results would be more
 accurate.
<li>They don't look like crap.
</ul>
<hr>
 &nbsp; <b>Pitfalls</b><br>
<br>
Radiosity really had me stumped at first and I kept screwing with just about every piece of code I could
 until I stumbled upon the solution and, of course, it wasn't where I expected at all.  So here are a few
 of the setbacks I encountered and what to do about them:<br>
<br>
<ul>
<li><b>I have no idea what the hell is going on...</b>  Try starting with a simpler model.  The first
 radiosity images were of a cube with a lit ceiling (think of the cheap halogen light panels at school).
 Always remember to start simple.  After all, you did and look!  You're almost nearly perfect! (:
<li><b>Everything is way too dark, except the light source!</b> This could be one of two problems:
<ol>
<li>Your patch reflect value is way too low.  I find a value of around 0.55 to 0.75 in the models I've
 tested so far.
<li>Your patches are too big.  The smaller the patches, the more accurate the image.  A good way to gauge
 the amount of inaccuracy is to sum the total light that actually reaches the destination patches and
 compare that to the amount of light that left the source patch.  You'll see that the number starts
 frighteningly large and drops in a k/n<sup>2</sup> fashion if your patches are too big.
</ol>
<li><b>Things are so SLOOOW!</b>  The greater the detail, the slower the calculation.  Et la vie, elle pu
 de temps en temps.  Squeeze every possible ounce out of your optimizations as you possibly can.
<li><b>There's a tiny patch in front of a big patch and the big patch is completely black!</b> (or)
<li><b>There's a tiny patch in front of a big patch, why doesn't the tiny patch cast a shadow?</b>  Your
 line of sight test isn't catching this situation correctly.  Or perhaps it is, but not returning the
 correct fraction.  It's this visibility problem that keeps scientists employed.
</ul>
<hr>
 &nbsp; <b>Faster, faster!  OH, YES!  YES!</b> *ahem*<br>
<br>
How to go faster can be summed into three categories.<br>
<br>
<b>Adaptive Subdivision</b> is a really neat trick.  Instead of cutting your initial polygons into teeny
 tiny itsy bitsy eeny weeny (yellow polka dot bikini...) patches try starting with somewhat larger patches.
 When you're sending light to the patch, check to see if the radiosity gradient is too high across the
 surface (if the change in light is too high).  If it is, split
 the patch into smaller pieces.<br>
<br>
<center><img src="0708.jpg" width="428" height="128" border="0" alt="Adaptive subdivision"></center>
<br>
<b>Elements</b> are another good idea for your calculator.  Each element contains a certain number of adjacent
 patches.  Only <b>send</b> from the elements but <b>catch</b> the light with the patches, which then report
 the change in delta radiosity to their element.  I made one element for every four patches, thus saving myself
 1/4 the work.  Granted, it will widen the margin of error but by so little that it shouldn't matter.  Also be
 careful that when you design your elements that they won't cause problems with adaptive subdivision, I had
 trouble getting them to play nice together.<br>
<br>
<b>Hemicubes</b> offer a distinct speed improvement and are by far the most touted, though why this is I don't
 really know, they seem way too prone to error for my taste.  I'll write more about them after I get a chance
 to try them.<br>
<br>
<hr>
<br>
Wasn't that fun?  I didn't think so either.  I finished my first radiosity calculator in nine days
 without eating, sleeping or taking care of personal hygiene 'cause I had a deadline to meet.  Can you tell
 it's 0400 where I live?<br>
<br>
...Since we've been talking about reflective surfaces, it seems only appropriate that we delve into mirrors
 next!
<br>
<br>
<a href="#top">Back to the top</a>
<hr>
<b>PREV: <a href="Engine06.shtml">Possible Visible Set</a></b><br>
<b>NEXT: <!--a href="Engine08.shtml"-->Mirrors</a></b><br>
<br></font>
</td></tr></table>
</td>
</tr>

</TABLE>

<HR ALIGN="CENTER" SIZE="1" WIDTH="700" NOSHADE>
<FONT FACE="arial" SIZE="-2">All photos copyright of their respective owners.  All other content of this website is &copy; 1997-1999 Dan Royer.<BR>
Designed for IE 5.0+, 800x600x16 or greater.  Some pages use style sheets.<br>
<A HREF="http://members.home.com/droyer/index.html"
   TITLE="Dan's Homepage">http://members.home.com/droyer/index.html</A><br>
</FONT>

</CENTER>
<BR>
<BR>

</BODY>
</HTML>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -