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

📄 ddfade.htm

📁 关于windows游戏编程的一些文章还有相关图形
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<!--Header-->
<HTML>
<HEAD>
<TITLE>GPMega - DirectX Section - DirectDraw Fading Mania</TITLE>
<META NAME="DESCRIPTION" CONTENT="The only tutorial you'll need to have awesome 16-bit fades with DirectDraw.  Covers crossfading, fade to a surface, and fading to black.  Covers theory, technique and gives implementation code.  Includes complete demo with source code in C++.">
</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/directx/ddfade.htm/" + random_num + "/@Top'>");
document.write("<IMG SRC='http://www.ugo.net/RealMedia/ads/adstream_nx.cgi/www.perplexed.com/GPMega/directx/ddfade.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="#FFF400">D</font><font color="#FFE900">i</font><font color="#FFDE00">r</font><font color="#FFD300">e</font><font color="#FFC800">c</font><font color="#FFBD00">t</font><font color="#FFB200">D</font><font color="#FFA700">r</font><font color="#FF9C00">a</font><font color="#FF9100">w</font><font color="#FF8600"> </font><font color="#FF7B00">F</font><font color="#FF7000">a</font><font color="#FF6500">d</font><font color="#FF5A00">i</font><font color="#FF4F00">n</font><font color="#FF4400">g</font><font color="#FF3900"> </font><font color="#FF2E00">M</font><font color="#FF2300">a</font><font color="#FF1800">n</font><font color="#FF0D00">i</font><font color="#FF0200">a</font><BR><FONT SIZE=-2>By: Matt Reiferson</FONT></H3>
<!--End Title-->

<P>Fades are an excellent way to cut to and from sections of your game.  Fade into your intro screen, fade out after the player dies, 
and cross-fade from screen-to-screen.  Well, how do you do it?  I'm going to cover fades in DirectDraw 16-bit modes, this seems 
to be the most commonly used mode, and in subsequently is the most commonly asked mode to do fades in.

<P>NOTE:  This article assumes you have a decent knowledge of DirectDraw, such as setting modes, creating surfaces, locking/unlocking, etc.

<H3><FONT COLOR=YELLOW><I>16-bit Pixel Formats</I></FONT></H3>

<P>Answer me this quick question, can you evenly divide 3 into 16?  I hope you said no.  My point is that in order to describe 
a single pixel, you need three components, <i>red</i>, <i>green</i>, and <i>blue</i>.  In other words if your in a 16-bit 
mode each pixel is given 16 bits for it's RGB combo and since you can't evenly divide 3 (R,G,B) into 16 bits, your video card 
determines how it's going to split things up.  Video cards put in 16-bit modes come in two flavors, the 5,6,5 format or the 
5,5,5 format (# of bits for r,g,b respectively).  How does this affect fading?  Well we're going to need the red, green, and 
blue components of the pixels were going to be manipulating.

<P>After that background info on these two 16-bit pixel formats, the next obvious step is to throw some code at you that 
demonstrates one technique of determining what the users video card format is in.  The function is called <i>DDGetRGB16()</i> 
and i'll throw that in below but first, the function fills up a structure called <i>RGB16</i> which holds information about 
pixel masks and bit positions.

<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
	// the structure which holds pixel RGB masks
	typedef struct _RGBMASK
	{
		unsigned long rgbRed; // red component
		unsigned long rgbGreen; // green component
		unsigned long rgbBlue; // blue component
	} RGBMASK;

	// the structure which holds screen format info (5,6,5 or 5,5,5 and masking)
	typedef struct _RGB16
	{
		RGBQUAD depth;
		RGBQUAD amount;
		RGBQUAD position;
		RGBMASK mask;
	} RGB16;
</FONT></PRE>
</BLOCKQUOTE>

<P>Then of course, we're also going to need a couple globals.  One being the RGB16 structure, and the integers being a couple 
of convienence variables so we don't constantly type out the entire structure.  In case your wondering, the <i>'m'</i> 
or <i>'p'</i> preceding the variables below stand for <i>mask</i> and <i>position</i> variables respectively.

<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
	RGB16	rgb16;			// Video Card RGB Information Structure
	int	mRed, mGreen,		// Faster values of above structure
		mBlue, pRed,		// Faster values of above structure
		pGreen, pBlue;		// Faster values of above structure
</FONT></PRE>
</BLOCKQUOTE>

<P>Ok, now we're ready to go ahead and see that <i>DDGetRGB16()</i> function.  What it does is simply manipulate information 
returned from a query to <i>->GetSurfaceDesc()</i> on the primary surface.

<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
	/*
	 * DDGetRGB16:
	 *    Must run this function to fill the RGB16 struct with the information needed to plot a pixel
	 *		To call this, you must have rgb16 defined as a global (unless you want to modify this) variable
	 *		RGB16 rgb16;
	 */
	void DDGetRGB16(void)
	{
		DDSURFACEDESC   ddsd;       // DirectDraw Surface Description
		BYTE            shiftcount; // Shift Counter
	
		// get a surface despriction
		ddsd.dwSize = sizeof(ddsd);
		ddsd.dwFlags = DDSD_PIXELFORMAT;
		lpDDSPrimary->GetSurfaceDesc(&ddsd);

		// Fill in the masking values for extracting colors
		rgb16.mask.rgbRed = ddsd.ddpfPixelFormat.dwRBitMask;
		rgb16.mask.rgbGreen = ddsd.ddpfPixelFormat.dwGBitMask;
		rgb16.mask.rgbBlue = ddsd.ddpfPixelFormat.dwBBitMask;
		
		// get red surface information
		shiftcount = 0;    
		while(!(ddsd.ddpfPixelFormat.dwRBitMask & 1))
		{
			ddsd.ddpfPixelFormat.dwRBitMask >>= 1;
			shiftcount++;
		}
		rgb16.depth.rgbRed = (BYTE)ddsd.ddpfPixelFormat.dwRBitMask;
		rgb16.position.rgbRed = shiftcount;
		rgb16.amount.rgbRed = (ddsd.ddpfPixelFormat.dwRBitMask == 0x1f) ? 3 : 2;
	
		// get green surface information
		shiftcount = 0;
		while(!(ddsd.ddpfPixelFormat.dwGBitMask & 1))
		{
			ddsd.ddpfPixelFormat.dwGBitMask >>= 1;
			shiftcount++;
		}
		rgb16.depth.rgbGreen =(BYTE)ddsd.ddpfPixelFormat.dwGBitMask;
		rgb16.position.rgbGreen = shiftcount;
		rgb16.amount.rgbGreen = (ddsd.ddpfPixelFormat.dwGBitMask == 0x1f) ? 3 : 2;
	
		// get Blue surface information
		shiftcount = 0;
		while(!(ddsd.ddpfPixelFormat.dwBBitMask & 1)) 
		{
		ddsd.ddpfPixelFormat.dwBBitMask >>= 1;
		shiftcount++; 
		}
		rgb16.depth.rgbBlue =(BYTE)ddsd.ddpfPixelFormat.dwBBitMask;
		rgb16.position.rgbBlue = shiftcount;
		rgb16.amount.rgbBlue = (ddsd.ddpfPixelFormat.dwBBitMask == 0x1f) ? 3 : 2;

		// fill in variables so we dont' have to access the structure anymore
		mRed = rgb16.mask.rgbRed;         // Red Mask
		mGreen = rgb16.mask.rgbGreen;     // Green Mask
		mBlue = rgb16.mask.rgbBlue;       // Blue Mask
		pRed = rgb16.position.rgbRed;     // Red Position
		pGreen = rgb16.position.rgbGreen; // Green Position
		pBlue = rgb16.position.rgbBlue;   // Blue Position
	}
</FONT></PRE>
</BLOCKQUOTE>

<H3><FONT COLOR=YELLOW><I>Fading Technique</I></FONT></H3>

<P>Since the implementation of fading that we use at the end involves manipulating each pixel, how do we go about blending one 
pixel into another?  Well, let first establish an equation which will allow us to blend two pixel's color values for one of their RGB 
components.

<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
	// get pixels red,green,blue values
	red_final		= (red1 * transparency1) + (red2 * transparency2);
	blue_final	= (blue1 * transparency1) + (blue2 * transparency2);
	green_final	= (green1 * transparency1) + (green2 * transparency2);
	// recombine red,green,blue to pixel value
</FONT></PRE>
</BLOCKQUOTE>

<P>Great, so Matt, how do we get the pixels red,green,blue values and then how to we create a pixel value from those new red,green,blue 
values we've calculated?  Glad you asked, here's where we put into use that information we've obtained from our <i>DDGetRGB16()</i> 
function.

<P>What follows are four macros which do exactly what they say, find out that information we need...

<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
	#define RED(p)		(p >> pRed)			// Extracts Red Component
	#define GREEN(p)		((p & mGreen) >> pGreen)		// Extracts Green Component
	#define BLUE(p)		(p & mBlue)			// Extracts Blue Component
	#define RGB16(r, g, b)	((r &lt;&lt; pRed) | (g &lt;&lt; pGreen) | b)	// Creates RGB Pixel Value
</FONT></PRE>
</BLOCKQUOTE>

<P>If you didn't know already, we also want this cross-fade to occur fast, so I took the liberty of making an important 
but commonly used optimization, a lookup table.  I made the decision that for any given fade, 32 steps would be enough to 
create a smooth enough effect.  So the lookup table is simply a huge array of all the shades of any given color in 32 steps.

<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
	WORD PixelShade[32][65536];
</FONT></PRE>
</BLOCKQUOTE>

<P>In our <i>PixelShade</i> initialization function, we're going to precompute the values for a given pixel in the given shade 
level, 0-31.  The function should be self explanatory, the only interesting note is the use of our above macros, and the use 
of a constant array of the decimal percentage values for each shade level.

<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
	/*
	 * InitPixelShade:
	 *    Fills the PixelShade array with precomputed shades of every possible pixel (32 shades)
	 */
	void InitPixelShade(void)
	{
		int i, j;
		int r,g,b;
		int dr,dg,db;
		const double alpha[32] = { 0.0, 0.03, 0.06, 0.09,
					0.13, 0.17, 0.21, 0.24,
					0.27, 0.31, 0.34, 0.37,
					0.41, 0.44, 0.47, 0.49,
					0.51, 0.53, 0.56, 0.59,
					0.63, 0.66, 0.69, 0.73,
					0.76, 0.79, 0.83, 0.87,
					0.91, 0.94, 0.97, 1.0 };

		for(i=0;i&lt;32;i++)
		{
			for(j=0;j&lt;65536;j++)
			{
				r = RED(j);
				g = GREEN(j);
				b = BLUE(j);
				dr = (int)(r*alpha[i]);
				dg = (int)(g*alpha[i]);
				db = (int)(b*alpha[i]);
				PixelShade[i][j] = RGB16(dr,dg,db);
			}
		}
	}

⌨️ 快捷键说明

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