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

📄 signzbuf.htm

📁 关于windows游戏编程的一些文章还有相关图形
💻 HTM
字号:
<!--Header-->
<HTML>
<HEAD>
<TITLE>GPMega - Advanced Section - Sign Based Z-Buffers</TITLE>
</HEAD>
<BODY BGCOLOR=#000000 TEXT=#FFFFFF LINK=#00FF00 VLINK=#00FF00 ALINK=#0000FF>
<!--End Header-->
<!--Advertiser-->
<CENTER>
<TABLE>
<TR>
<TD>
<A HREF="http://www.ugo.com/">
<IMG SRC="/GPMega/ugologo120.gif" BORDER=0 WIDTH=120 HEIGHT=60></A>
</TD>
<TD>
<IMG SRC="/GPMega/sponsored.gif" WIDTH=468 HEIGHT=10><br><br>
<SCRIPT LANGUAGE= "JavaScript">
<!--
var now = new Date();
var random_num = now.getSeconds();
document.write("<A HREF='http://www.ugo.net/RealMedia/ads/click_nx.cgi/www.perplexed.com/GPMega/advanced/signzbuf.htm/" + random_num + "/@Top'>");
document.write("<IMG SRC='http://www.ugo.net/RealMedia/ads/adstream_nx.cgi/www.perplexed.com/GPMega/advanced/signzbuf.htm/" + random_num + "/@Top' BORDER='0' WIDTH='468' HEIGHT='60'></A>");
//-->
</SCRIPT>
</TD>
</TR>
</TABLE>
</CENTER>
<!--End Advertiser-->
<!--Splitter-->
<BR>
<!--End Splitter-->
<!--Body-->
<FONT SIZE=2 FACE=Helvetica>
<STRONG>
<!--Top Navigation-->
<A NAME="top"></A>
<CENTER>
<TABLE WIDTH=75%>
   <TR VALIGN=MIDDLE>
   <TD ALIGN=LEFT>
      <IMG SRC="gradsplit2.jpg" WIDTH=100% HEIGHT=1><BR><BR>
      <A HREF="http://www.perplexed.com/GPMega/"><IMG SRC="logo.jpg" BORDER=0 ALT="Home" WIDTH=80 HEIGHT=47 ALIGN=CENTER></A>
      <FONT COLOR=#666666 FACE=HELVETICA SIZE=-1><I>
      This Article Is Taken From <A HREF="http://www.perplexed.com/GPMega/">The Game Programming MegaSite</A>, A Definitive Resource For Game Developers!
      </I></FONT><BR>
      <IMG SRC="gradsplit2.jpg" WIDTH=100% HEIGHT=1>
   </TD>
   </TR>
</TABLE>
</CENTER>
<BR><!--End Top Navigation-->
<!--Title-->
<H3 ALIGN=CENTER><font color="#FFF300">S</font><font color="#FFE700">i</font><font color="#FFDB00">g</font><font color="#FFCF00">n</font><font color="#FFC300"> </font><font color="#FFB700">B</font><font color="#FFAB00">a</font><font color="#FF9F00">s</font><font color="#FF9300">e</font><font color="#FF8700">d</font><font color="#FF7B00"> </font><font color="#FF6F00">Z</font><font color="#FF6300">-</font><font color="#FF5700">B</font><font color="#FF4B00">u</font><font color="#FF3F00">f</font><font color="#FF3300">f</font><font color="#FF2700">e</font><font color="#FF1B00">r</font><font color="#FF0F00">s</font><BR><FONT SIZE=-2>By: Jeff Weeks</FONT></H3>
<!--End Title-->
<P>Hidden surface removal is a key component
of any 3D engine.  Unfortunately, it is often difficult to achieve a
decent speed with the most popular method; the z-buffer.  Personally,
I fell in love with the z-buffer's ease of use.  Compared to most
systems in use it is not only easier to understand, but also easier
to implement.  The problem?  It's slow.  The reason?  It needs to be
cleared once per frame.  If the need to clear the z-buffer could be
eliminated then the algorithm would be next to perfect.

<P>I intend to show you how the above can
actually be achieved.  Through a simple programming trick you can
render an infinite number of frames without clearing the z-buffer. 
There is only one restriction, which I will explain as well. 
However, in my own opinion, the restriction is minor and in most
cases not even an issue.

<H3><FONT COLOR=YELLOW><I>The Theory of the Z-Buffer</I></FONT></H3>

<P>I'm sure most of you know the theory behind
the z-buffer algorithm, but I'll provide a brief introduction to
those who aren't as familiar.  Basically a z-buffer is just that, a
buffer filled with z co-ordinates.  When rendering polygons you are
required to interpolate every pixel's z value and compare it to the
z-buffer.  If your z is closer to the viewer that the current z value
in the z-buffer, you plot your pixel and readjust the z-buffer value,
otherwise the pixel is ignored.

<P>In other words, the z-buffer has the same
dimensions as your rendering surface, except instead of holding
colour values, in holds z values.  As you can see, the algorithm is
extremely simple to explain and implement.  Another advantage is that
it has no ordering requirement.  Polygons can be rendered in any
order, unlike other systems which require them to be sorted.

<P>The disadvantage here is that after every
frame you must clear the z-buffer back to zero.  You don't want to be
comparing the new polygon's z values with old ones in the z-buffer
from the previous frame.  This is what we will be eliminating.

<H3><FONT COLOR=YELLOW><I>Getting Rid of the Z-Buffer Clear</I></FONT></H3>

<P>In the tradition of the
z-buffer, this addition to the algorithm is also extremely easy to
understand and implement.  In fact, any existing z-buffer
implementation should require very little change to fit this system. 
There are but two alterations.  I will explain them each briefly then
describe how the two work together to create this new z-buffer
system.

<P>The secret is in what you put
into the z-buffer.  Instead of putting in the actual z value, we will
alternate between positive and negative versions of the actual z
value.  Perhaps you can see what is about to happen already.  There
will be no need to clear the z-buffer to zero, because by the time
you're inserting the positive numbers into the z-buffer, it will be
filled with negative numbers which, of course, are less than zero. 
By contrast, when you're inserting negative numbers, the z-buffer
will be filled with positive ones.

<P>The last change is in your
testing code.  When you're inserting positive numbers nothing
changes, you continue to test and plot the pixel if its z is greater
than the value in the z-buffer.  However, when inserting negative
numbers you plot the pixel if its negative z is less than what is in
the z-buffer.

<P>The concept is simple.  There
is no need to clear the z-buffer back to zero because all existing
numbers in the z-buffer will be of the opposite sign of what you are
testing.  Essentially they already are zero, or rather non existent. 
With the alternating testing code they will always be farther away
then the pixel you are testing.

<P>In other words, by switching
the sign and test code you essentially perform your z-buffer
calculations on one side of zero, and then the other side of zero in
the next frame.  Each frame clears the opposite side of zero simply
by plotting pixels (sense the z-buffer will be of opposite sign, and
therefore non-existent, the first round of pixels will <I>always</I>
pass the z-buffer test, and will be plotted, erasing previous
opposite sign values for the next frame).

<P>Perhaps some code will help
explain this.  It is a simple concept, but perhaps a little difficult
to explain in print without code.</P>

<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
	// odd frame number
	if(view->frame_num & 1)
	{
		if(view->zbuf[z_offset] > -z)
		{
			view->zbuf[z_offset] = -z;
			fputpixel(address, c);
		}
	}
	else
	{
		if(view->zbuf[z_offset] < z)
		{
			view->zbuf[z_offset] = z;
			fputpixel(address, c);
		}
	}
</FONT></PRE>
</BLOCKQUOTE>

<P>As you can see, it's really
very simple to incorporate this into your current code.  This code
simply checks the frame number to see if it's divisible by 2 to
determine wether this frame is even or odd.  My code uses negative
z's on odd frames, and positive z's on even frames, but it really
doesn't matter which you choose.

<H3><FONT COLOR=YELLOW><I>The Restriction</I></FONT></H3>

<P>As I mentioned previously,
this method does have one restriction.  Perhaps some of you have
discovered this already;  with this method you must use the entire
z-buffer each frame.  If you don't, then the other size of zero will
not be cleared.  In other words, there will be z values left over in
the z-buffer that shouldn't be.  While it can produce an interesting
effect it probably isn't what you'd want in a professional product.

<P>The solution?  I'd like to
suggest you don't particularly have to worry about it.  If you are
developing a game then you will certainly be using the whole z-buffer
at all times.  In fact, many 3D programs will use the entire
z-buffer, and for these programs the restriction is not an issue.

<P>For those products that do not
use the entire z-buffer there is a solution.  You could simply put a
large polygon in the background that covers the entire z-buffer. 
Texture map it and make it your background image, if you wish. 
However, if you aren't using the entire z-buffer you are, no doubt,
simply displaying a single 3D object on a black background, in which
case perhaps a regular z-buffer would suffice.  It all depends on how
fast your polygon routines are for large polygons versus how fast you
can clear the z-buffer.  Obviously, you simply use the fastest
method.

<P>All and all, though, if you're
using the entire z-buffer you'd be hard pressed to find a faster
solution than the sign based z-buffer.</P>
<!--Bottom Navigation-->
<A NAME="bottom"></A>
<!--End Bottom Navigation-->
</STRONG>
</FONT>
<!--End Body-->
<!--Bottom-->
<BR>
<IMG SRC="gradbar.jpg">
<BR>
<FONT SIZE=2 COLOR=#8B8B8B FACE=Helvetica>
<I><font color="#FBFBFB">T</font><font color="#F7F7F7">h</font><font color="#F3F3F3">e</font><font color="#EFEFEF"> </font><font color="#EBEBEB">G</font><font color="#E7E7E7">a</font><font color="#E3E3E3">m</font><font color="#DFDFDF">e</font><font color="#DBDBDB"> </font><font color="#D7D7D7">P</font><font color="#D3D3D3">r</font><font color="#CFCFCF">o</font><font color="#CBCBCB">g</font><font color="#C7C7C7">r</font><font color="#C3C3C3">a</font><font color="#BFBFBF">m</font><font color="#BBBBBB">m</font><font color="#B7B7B7">i</font><font color="#B3B3B3">n</font><font color="#AFAFAF">g</font><font color="#ABABAB"> </font><font color="#A7A7A7">M</font><font color="#A3A3A3">e</font><font color="#9F9F9F">g</font><font color="#9B9B9B">a</font><font color="#979797">S</font><font color="#939393">i</font><font color="#8F8F8F">t</font><font color="#8B8B8B">e</font> - 

⌨️ 快捷键说明

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