• Create Account

## Reading single pixel color - Direct3D8 in Visual Basic 6

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

9 replies to this topic

### #1The Melody Maker  Members

126
Like
0Likes
Like

Posted 10 February 2013 - 11:41 PM

Hello.   I did a search for a similar topic and couldn't find one, so I apologize in advance if one does indeed exist elsewhere.

I've been programming a game in Visual Basic 6 using the DirectX 8 Graphics interface, but I've run into a bit of trouble in my attempts to correctly read the color value from a single pixel from the front buffer that I've already locked with LockRect.  Just so I'm not misunderstood, though, I'm not having trouble with the functionality.  I've already successfully locked the front buffer, read from it, and unlocked it.  My problem is figuring out the correct math for reading the appropriate color data from the pixels.  (That being said, I hope I've started this thread in the right place and I apologize if I haven't.)

This is the helper function that I have going to make the job easier...

Function GrabPixel(XPos As Long, YPos As Long) As Long

Dim TempColor As Long

' LockedRect is the front buffer surface (D3DLOCKED_RECT) I've locked with Direct3DSurface.LockRect, and according to the docs it ought to be 32-bit automatically.
' X_RES& is the width of the game's current screen mode.
' Y_RES& is the height of the game's current screen mode.

With LockedRect
TempColor = (.pBits + ((Y_RES& - 1 - YPos) * .Pitch) + (XPos * 4))
End With

' Anything else I need to do here to manipulate the color value I get before it's usable?

GrabPixel = TempColor

End Function



If anyone can figure out where I'm going wrong with my math, I'd greatly appreciate it.  Thank you in advance to anyone who posts with help and advice.

### #2Nik02  Members

4075
Like
1Likes
Like

Posted 11 February 2013 - 02:04 AM

This is difficult in VB6 (and VB in general) because the language doesn't have pointer dereferencing.

As a workaround, you can import the CopyMemory function from kernel32, and copy the data from the locked_rect to your own array of pixels.

The pBits field of the locked_rect structure represents the pointer (or local memory address) of the first pixel of the first scanline of the area you locked. The scanlines of the locked area are guaranteed to be adjacent in memory, but they may have padding in addition to the actual pixel data; this is why you have to consider the "pitch" to navigate between scanlines, not just width * numbytesperpixel.

The address of a given pixel on the locked area is given by the following formula:

address(x, y) = pBits + y * pitch + x * bytesPerPixel

The bytesPerPixel varies with the texture format, of course.

If you know that your pixels are 32-bit (byte per channel rgba), you can use CopyMemory once you have the address on the locked rectangle:

type rgbapixel

r as byte

g as byte

b as byte

a as byte

end type

dim destination as rgbapixel

CopyMemory(byval varptr(destination), byval address, 4) ' where 4 is the number of bytes to copy, and "address" is the address of the source pixel as described above

Niko Suni

### #3Nik02  Members

4075
Like
1Likes
Like

Posted 11 February 2013 - 02:09 AM

Also, if you need many pixels, it is very much faster to copy them by scanline instead of one by one. In case you do scanline copies, your destination would be an array of the pixel structures and the correct first parameter (destination pointer) of the CopyMemory would be the first element of said array.

Note that CopyMemory has a nasty habit of crashing your VB6 app if the last parameter (number of bytes) is zero; be sure to safeguard your logic against that

Niko Suni

### #4The Melody Maker  Members

126
Like
0Likes
Like

Posted 11 February 2013 - 07:50 AM

Thanks for replying, Nik02.   I see now what I was doing wrong -- I was both reading the bitmap in memory upside-down and the resultant color backwards (assuming ABGR). XD

I tried the method you gave me (including using the CopyMemory sub from the Windows API) and now it's working perfectly; thank you so much for your help! ^__^

### #5lomateron  Members

491
Like
0Likes
Like

Posted 11 February 2013 - 09:22 AM

I would like to know why are you using directx 8 and VS 6

### #6Nik02  Members

4075
Like
0Likes
Like

Posted 12 February 2013 - 02:20 AM

For win98 compatibility?

Niko Suni

### #7lomateron  Members

491
Like
0Likes
Like

Posted 12 February 2013 - 04:53 AM

why windows 98?

### #8Nik02  Members

4075
Like
0Likes
Like

Posted 12 February 2013 - 06:14 AM

I don't know, just guessing

Sometimes it is fun toughening yourself by doing something the hard way instead of using these new fancy IDEs, OS and DirectX versions

Edited by Nik02, 12 February 2013 - 06:17 AM.

Niko Suni

### #9Nik02  Members

4075
Like
0Likes
Like

Posted 12 February 2013 - 06:20 AM

A fun, (distantly related) excercise is writing a Gouraud + multiple texture rasterizer in QBasic, and actually render some non-trivial mesh on that

Niko Suni

### #10The Melody Maker  Members

126
Like
0Likes
Like

Posted 12 February 2013 - 08:06 AM

Backwards compatibility with earlier versions of Windows is only one my reasons I still use those legacy interfaces instead of upgrading to the newer ones.  The Visual Basic 6 runtime, as well as the DirectX 7 and 8 interfaces which I've been using, do work with all the mainstream versions of Windows from 95 onward up to 8*.  But I do have other reasons.  I also use them because I still have them at my disposal, I've become comfortable with them after using them for 10+ years, and it's sufficient for what I need.  That's enough reason for me to keep using them.  At least at this time, I have no interest or need to upgrade.

* The two 2D-only games I've been making, both many years in the making and still under development, have been using DirectDraw 7 for graphical output but since finding out that Windows 8 handles DirectDraw operations very slowly, I've been making alternate Direct3D 8 versions of both which I'm happy to say so far actually do run at the right speed in Windows 8 upon testing.   In the one game I'm currently working on upgrading, I had a routine set up to read the colors from the screen's middle column of pixels in DirectDraw, but Direct3D handles that so differently from DirectDraw that I had to come on here to ask for help. XD

Edited by The Melody Maker, 12 February 2013 - 08:08 AM.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.