DirectX:DirectDraw:Tutorials:VB:DX7:Special Effects

From GPWiki
Jump to: navigation, search

Too lazy to write a C, C++, or ASM DLL to do your special effects dirty work? Put blitter Raster Operations (ROPs) to work for you! Maximal results with minimal effort, that's my motto!

There are a number of different ROP constants available to us in VB:

vbSrcPaint 
ORs the source and destination image data, giving a pseudo-alphablending effect.
vbSrcAnd 
ANDs the source and destination image data, giving a pseudo-gamma effect.
vbSrcInvert 
XORs the source and destination image data.
vbSrcErase 
Inverts the destination image data then ANDs with the source image data.
vbSrcCopy 
Copies the source image data directly onto the destination, replacing it completely.
vbDstInvert 
Inverts the destination image data, and ignores the source image data completely.
vbNotSrcCopy 
Inverts the source image data and copies directly onto the destination, replacing it completely.
vbNotSrcErase 
ORs the source and destination image data and inverts the result.

Now, we have two methods at our disposal for implementing these various ROPs. We can use the API BitBlt function, or we can use the DirectX BltFx function. BltFx will ONLY work if the user's video card supports the ROP in hardware. BltFx WILL fail otherwise! Where BltFx fails however, the BitBlt API call can take over; The BitBlt API call will never fail since all operations are carried out via software!

(Important Speed Consideration: When using BltFx, it is ideal to place surfaces in Video Memory as they can be accessed there most quickly by the video card's blitter. When using the BitBlt API call on the other hand, it is ideal to place surfaces in System Memory, otherwise the data must be fetched from video memory, modified, and then sent back to video memory. Inefficient!)

It would be nice to know for certain whether the user's video card can support a specific ROP in hardware or not, and I have written a simple function to do just that:

Private Function TestROP(ByRef surfBack As DirectDrawSurface7, lngROP As Long) As Boolean

Dim objBltFx As DDBLTFX Dim rectTemp As RECT Dim surfTemp As DirectDrawSurface7 Dim udtDDSD As DDSURFACEDESC2

   'Create a small temporary surface
   udtDDSD.lFlags = DDSD_HEIGHT Or DDSD_WIDTH
   udtDDSD.lHeight = 1
   udtDDSD.lWidth = 1
   Set surfTemp = mdd.CreateSurface(udtDDSD)
   
   'Set the BltFx ROP code
   objBltFx.lROP = lngROP
   
   'Our source and dest rectangle
   rectTemp.Right = 1
   rectTemp.Bottom = 1
   
   'Test the BltFx capability
   If surfBack.BltFx(rectTemp, surfTemp, rectTemp, DDBLT_ROP Or DDBLT_WAIT, objBltFx) <> 0 Then
       TestROP = False
   Else
       TestROP = True
   End If

End Function

Simply pass this function a reference to your current backbuffer and the ROP constant you're interested in and it will inform you of the user's hardware capabilities. It does this by performing a sample BltFx blit and examining the error code returned.

Now that we know if our desired ROP is supported, we can go ahead and perform our blit! If the ROP is supported, we can use BltFx, like so:

   objBltFx.lROP = lngROP
   msurfBack.BltFx rectDest, surfDisplay, rectSource, DDBLT_ROP Or DDBLT_WAIT, objBltFx

objBltFx is of the DDBLTFX type, and must be loaded with the ROP we wish to perform (here stored in lngROP). Once we have our DDBLTFX type filled, we can call the backbuffer's BltFx method, passing our source and dest rectangles, our desired surface, a few constants (DDBLT_ROP and DDBLT_WAIT) and our objBltFx. The constant DDBLT_ROP is required, informing BltFx that we wish to use the lROP member of the DDBLTFX structure.

If we're forced to use the BitBlt API call, it can be handled in this fashion:

   'Lock down the surface DCs
   lngDestDC = msurfBack.GetDC
   lngSrcDC = surfDisplay.GetDC
   'Do the fancy old-fashioned blit
   BitBlt lngDestDC, intX, intY, intWidth, intHeight, lngSrcDC, 0, 0, lngROP
   'Release our DCs
   surfDisplay.ReleaseDC lngSrcDC
   msurfBack.ReleaseDC lngDestDC

First we need to acquire the source (surface to be blitted) and destination (backbuffer) DCs. Once we have them, we feed this data into the BitBlt call, along with our sprite dimensions and the ROP we desire (lngROP). Afterward we MUST release the DCs, lest we freeze the computer

So there you have it! A few magic little functions and you can employ nifty raster operations in your games and programs. Download this sample source code to see all of the different ROPs in action.