📄 ddfade.htm
字号:
</FONT></PRE>
</BLOCKQUOTE>
<P>The first type of fade we'll implement is cross-fading, which is the basic fade directly from one image on screen to another.
What your basically trying to do is combine the two desired images through blending. Where during each iteration the initial
image becomes more transparent and the final image becomes more opaque (although, transparency_initial_img + transparency_final_img = 100%).
<P>What the next function presented does is perform a cross-fade (Alpha Transition) on the two given surfaces.
<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
/*
* AlphaTransition:
* Does an alpha transition from Src -> Des
*/
void AlphaTransition(LPDIRECTDRAWSURFACE Src, LPDIRECTDRAWSURFACE Des)
{
long i; // index into surfaces
int alpha; // Holds current alpha value
int dpitch, spitch, tpitch, ppitch; // surface pitch for destination, source, temp surfaces
WORD *AlphaPTR; // pointer to the current AlphaMap level (Source)
WORD *InvAlphaPTR; // the inverted pointer to the current AlphaMap level (Destination)
WORD *src, *des, *tmp, *prm;
WORD *fastsrc, *fastdes, *fasttmp; // Surface memory pointer for source, destination, and temporary surfaces
RECT SrcRect, DesRect; // Source and destination rectangles
// Set source and destination rectangles to the screen size
SetRect(&SrcRect, 0, 0, 640, 480);
SetRect(&DesRect, 0, 0, 640, 480);
// Create the three surface we are going to use
lpDDSTmp = DDCreateSurface(640, 480, DDSCAPS_SYSTEMMEMORY); // The temporary surface
lpDDSSrc = DDCreateSurface(640, 480, DDSCAPS_SYSTEMMEMORY); // The source surface
lpDDSDes = DDCreateSurface(640, 480, DDSCAPS_SYSTEMMEMORY); // The destination surface
// Blit the transition surfaces into out newly created source/destination surfaces
lpDDSSrc->Blt(&DesRect, Src, &SrcRect, DDBLT_WAIT, NULL); // Blit Src->lpDDSSrc
lpDDSDes->Blt(&DesRect, Des, &SrcRect, DDBLT_WAIT, NULL); // Blit Des->lpDDSDes
// lock all three surfaces temporary, source, and destination
des = DDLockSurface(lpDDSDes, &dpitch);
src = DDLockSurface(lpDDSSrc, &spitch);
tmp = DDLockSurface(lpDDSTmp, &tpitch);
prm = DDLockSurface(lpDDSPrimary, &ppitch);
// for each alpha level
for(alpha=31;alpha>=0;alpha--)
{
// set AlphaMap pointers to appropriate levels
AlphaPTR = PixelShade[alpha];
InvAlphaPTR = PixelShade[31-alpha];
// "reset" the *fast* pointers to the locked surfaces
fastsrc = src;
fastdes = des;
fasttmp = tmp;
// loop through every pixel
for(i=0;i<307200;i++,fasttmp++,fastsrc++,fastdes++)
{
// Set the new pixel value in temporary surface
*fasttmp = AlphaPTR[*fastsrc] + InvAlphaPTR[*fastdes];
}
// copy the temp surface to the primary surface
// (640*480) = 307200 (words) * 2 = 614400 (bytes)
memcpy(prm, tmp, 614400);
}
// Unlock our temporary, source, and destination surfaces
DDUnlockSurface(lpDDSPrimary);
DDUnlockSurface(lpDDSTmp);
DDUnlockSurface(lpDDSDes);
DDUnlockSurface(lpDDSSrc);
// Release our temporary, source, and destination surfaces
lpDDSTmp->Release();
lpDDSTmp = NULL;
lpDDSSrc->Release();
lpDDSSrc = NULL;
lpDDSDes->Release();
lpDDSDes = NULL;
}
</FONT></PRE>
</BLOCKQUOTE>
<P>Ok, the next fade we are going to want to perform is a fade from black to a surface. Since all three fading methods use
the same basic algorithm, and given the fact that <i>PixelShade[0]</i> would be black for any color, in each iteration we're
simply going to fill the screen with that level pixel color until we hit <i>PixelShade[31]</i> which will be the desired image
at full color.
<P>Here's the code:
<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
/*
* FadeToSurface:
* Fades into a surface from black
*/
void FadeToSurface(LPDIRECTDRAWSURFACE lpDDS)
{
int c; // counter variable
long i; // incrementing variable
WORD *tmp, *ref, *prm;
WORD *fasttmp, *fastref; // temporary and destination surface mem pointers
RECT SrcRect, DesRect; // Source and destination rectangles
int tpitch, rpitch, ppitch; // temporary and destination surface pitch
WORD *shade;
// Set the source and destination rectangles to the size of the screen
SetRect(&SrcRect, 0, 0, 640, 480);
SetRect(&DesRect, 0, 0, 640, 480);
// Create the surfaces
lpDDSTmp = DDCreateSurface(640, 480, DDSCAPS_SYSTEMMEMORY); // the temporary surface
lpDDSRef = DDCreateSurface(640, 480, DDSCAPS_SYSTEMMEMORY); // the temporary surface
lpDDSRef->Blt(&DesRect, lpDDS, &SrcRect, DDBLT_WAIT, NULL); // blit the desired surface into our destination surface
// Lock our surfaces temporary, and destination
tmp = DDLockSurface(lpDDSTmp, &tpitch);
prm = DDLockSurface(lpDDSPrimary, &ppitch);
ref = DDLockSurface(lpDDSRef, &rpitch);
// This can be changed, but it worx out nice to do 10 iterations
for(c=1;c<=30;c++)
{
// get pointer indexed to the start of the current shade level
shade = PixelShade[c];
// "reset" our *fast* surface pointers
fasttmp = tmp;
fastref = ref;
// for every pixel on the screen (640*480=307200)
for(i=0;i<307200;i++,fasttmp++,fastref++)
{
// new pixel please.....
*fasttmp = shade[*fastref];
}
// copy the temp surface to the primary surface
// (640*480) = 307200 (words) * 2 = 614400 (bytes)
systovid_memcpy(prm, tmp, 614400);
}
// unlock the temporary surface and destination surface
DDUnlockSurface(lpDDSTmp);
DDUnlockSurface(lpDDSPrimary);
DDUnlockSurface(lpDDSRef);
// blit the actual destination surface to the primary surface so we're sure
// the screen is where it should be
lpDDSPrimary->Blt(&DesRect, lpDDS, &SrcRect, DDBLT_WAIT, NULL);
// release the temporary and destination surfaces
lpDDSTmp->Release();
lpDDSTmp = NULL;
lpDDSRef->Release();
lpDDSRef = NULL;
}
</FONT></PRE>
</BLOCKQUOTE>
<P>And the final fade we're going to perform is the classic fade to black. What we want is to have a desired initial image
already on the screen and simply do the opposite of what we did with the <i>FadeToSurface()</i>, starting with <i>PixelShade[31]</i>
and ending with <i>PixelShade[0]</i>.
<p>Again, here's the implementation:
<BLOCKQUOTE>
<PRE><FONT SIZE=2 COLOR=RED>
/*
* FadeToBlack:
* Fades a screen to black
*/
void FadeToBlack(void)
{
RECT SrcRect, DesRect; // Source and Destination Rectangles
WORD *tmp; // temporary surface memory pointer
WORD *ref;
WORD *prm;
WORD *fastref, *fasttmp;
int c, tpitch, rpitch, ppitch; // incrementing variable, temporary surface pitch
long i; // another incrementing variable
WORD *shade;
// Set source and destination rectangles to size of screen
SetRect(&SrcRect, 0, 0, 640, 480);
SetRect(&DesRect, 0, 0, 640, 480);
// Create our temporary surface
lpDDSTmp = DDCreateSurface(640, 480, DDSCAPS_SYSTEMMEMORY);
lpDDSRef = DDCreateSurface(640, 480, DDSCAPS_SYSTEMMEMORY);
// Blit our primary surface into our temporary SYSTEM MEMORY surface
lpDDSRef->Blt(&DesRect, lpDDSPrimary, &SrcRect, DDBLT_WAIT, NULL);
// Lock our temporary surface
tmp = DDLockSurface(lpDDSTmp, &tpitch);
ref = DDLockSurface(lpDDSRef, &rpitch);
prm = DDLockSurface(lpDDSPrimary, &ppitch);
for(c=30;c>=1;c--)
{
// get a pointer indexed to the start of the current shade level
shade = PixelShade[c];
// "reset" our *fast* surface pointers
fastref = ref;
fasttmp = tmp;
// for every pixel on the screen (640*480=307200)
for(i=0;i<307200;i++,fasttmp++,fastref++)
{
// new pixel please....
*fasttmp = shade[*fastref];
}
// copy the temp surface to the primary surface
// (640*480) = 307200 (words) * 2 = 614400 (bytes)
systovid_memcpy(prm, tmp, 614400);
}
// unlock our temporary surface
DDUnlockSurface(lpDDSTmp);
DDUnlockSurface(lpDDSRef);
DDUnlockSurface(lpDDSPrimary);
// just to make sure the screen is black when this routine is over, fill it with 0
DDFillSurface(lpDDSPrimary,0);
// release our temporary surface
lpDDSTmp->Release();
lpDDSTmp = NULL;
lpDDSRef->Release();
lpDDSRef = NULL;
}
</FONT></PRE>
</BLOCKQUOTE>
<P>Before I offer the download to the demo application, just a couple things to keep in mind. It's obvious that you should
never attempt to do pixel manipulations directly on the primary (Video Memory) surface. That's the reason for the creation of
system memory surfaces and then the copying of the working surfaces into them in each of the three functions. After that, you
can do all the pixel manipulations you want and then blast it into the primary surface with a memcpy. The functions also attempt
to minimize surface locking, another potential slowdown. But, as always, nothing is every "optimized" as new ways to speed
things up can always be found...
<H4 ALIGN=CENTER>Download: <A HREF="ddfade.zip">ddfade.zip (Executable, Source C++)</A></H4>
<!--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 + -