Please support our sponsor:
Welcome To DirectX 4 VB! Multimedia Visual Basic at its best...




DirectDraw: Accessing Surface Memory
By: Jack Hoxley
Written: June 2000

Download: DD_Ripple.Zip (49kb) and DD_pixPlot.zip (49kb)


There comes a point when writing a game (or program) in directdraw and you reach the end of it's usefullness - you need it to do more, but it cant. Or, you want it to do something that cant be done using the built in commands. This is when it starts getting fun/complicated....

Directdraw allows you two methods of accessing surface memory, and both of them can be really annoying to use, and very complicated. However, in return for your hard work you can create amazing special effects and features for your program. Go along to Unlimited Realities homepage for some incredible examples; although not all of them are in directX, the idea is the same. With some simple (or complicated) maths algorithms you can create custom effects.

Method 1: Set/GetLockedPixel
The first method is relatively easy, and fairly safe to use, but unfortunately much slower. You may have noticed that when setting the colour for various things it requires a long value? These methods allow you to retrieve the long value of a certain pixel, and set it again.

Sub ProcessMemory
Dim Colour as Long
Dim rArea as RECT
Dim ddsd as DDSURFACEDESC2

rArea.Bottom=480:rArea.Right=640

MainSurf.Lock rArea,ddsd, DDLOCK_WAIT,0
'We now have access to the memory. From now until the Unlock you are treading
'on thin ice......

'These are our two commands.

Colour=Mainsurf.GetLockedPixel(100,120)
Mainsurf.SetLockedPixel(100,120,Colour+10)

MainSurf.Unlock rArea

End Sub

Method 2: GetLockedArray
This is the complicated, difficult, dangerous and faster method to use. I have lost count of the number of times I locked up my computer playing around with this method. Basically, it passes back an array which points to the surface memory itself. You can then read/write to this array and the effects will be mirrored on the surface. Sounds simple. Two points of warning though:

  1. If you write an invalid value to the array you will not get an error; and you will be very lucky if you get back into windows without restarting your computer. Values must be whole numbers and between 0 and 255.
  2. If you write to a value outside the array you will not get an error, and you will probably have to restart your computer. This is basically a memory leak.

Then there is another problem - the debugger will not work whilst you are processing memory. Between the Surface.Lock and Surface.Unlock methods windows ceases execution, this is because directdraw takes the win16mutex which basically suspends windows. Because windows is effectively shut down you must do NOTHING complicated or invloved with other components. ie. No DLL calls, no file access and no running of other applications. Also, dont try anything clever inside directx, you can't blit from or to a locked surface, and some other clever operations may well fail. This leads onto another point - the code must be flawless, if there is an error in the compiled version you can say goodbye to windows.

You may have had enough of the problems already, but the final problem is probably the most annoying. The data. The array will basically show you the raw data from a bitmap, so it's fine if you understand that, otherwise (like me) it's extremely difficult. Each entry in the array is a byte which means 0-255 (every colour is 0-255 you may have noticed). Each entry in the array represents one channel of the colour, NOT one pixel. using the RGB(x,x,x) statement will be fatal. This is fine if you aren't interested in the colour of the pixel directly, but it is if you try setting the colour to be specific. If you only want to deform the current image, you can do that without paying much attention to the current value - you just run a formula through it.

Getting the Red/Green/Blue colour components can be extremely difficult. 16bit is a nightmare; 8, 24 and 32bit isn't too difficult. Hopefully you understand how computers store data; there are 8bits to a byte, 1024 bytes to a kilobyte etc... Therefore; if our array is a collection of bytes, we need to get the correct bits out of it. For 8bit it is easy - each byte (8 bits to a byte) represents the colour; because 8 bit mode is palettised this value refers to the palette entry for that pixel. 16 bit can either be in 555 or 565 mode - where they are all 5 bits (less than a byte) and there is one bit spare; or they are all 5 bits and Green is 6 bits, with no bytes to spare. 24 bits are 3 bytes, so each set of three bytes in the array are the channels for the pixel. It tends to be organised in BGR format rather than RGB... 32 bits are 4 bytes (getting the hang of this yet?), this is because 32bit colour can have an alpha channel. The bytes are organised in the format ARGB - so unless you are interested in the alpha channel you can skip every 4th byte.

Here's the code for accessing the surface memory using arrays:

Sub ProcessMemory
'Note: This is almost identical to the previous method...
Dim Colour as Long
Dim rArea as RECT
Dim ddsd as DDSURFACEDESC2
dim Pict() as Byte 'Note, there is NO boundaries specified

rArea.Bottom=480:rArea.Right=640

MainSurf.Lock rArea,ddsd, DDLOCK_WAIT,0
'We now have access to the memory. From now until the Unlock you are treading
'on thin ice......

MainSurf.GetLockedArray Pict

'You can now manipulate the array into whatever form you wish
'But remember the rules/warnings
'The array will still point to the memory until the Unlock command. After
'this point it becomes a normal VB array...


'It all goes in the form of Pict(x,y) = ??
'Even though two dimensions aren't specified, they can be referenced like that.

'If you're really clever you can access it as one linear block of memory...

MainSurf.Unlock rArea

End Sub

There are two example projects to go with this tutorial, one is a directX conversion of an unlimited realities example, the other just a simple example. They can be downloaded from the top of this page, or from the downloads page.

DirectX 4 VB © 2000 Jack Hoxley. All rights reserved.
Reproduction of this site and it's contents, in whole or in part, is prohibited,
except where explicitly stated otherwise.
Design by Mateo
Contact Webmaster
This site is hosted by Exhedra Solutions, Inc., the parent company of RentACoder.com and PlanetSourceCode.com