Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


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.

  • You cannot reply to this topic
9 replies to this topic

#1 The Melody Maker   Members   -  Reputation: 126

Like
0Likes
Like

Posted 10 February 2013 - 11:41 PM

Hello. smile.png  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. smile.png



Sponsor:

#2 Nik02   Crossbones+   -  Reputation: 2870

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


#3 Nik02   Crossbones+   -  Reputation: 2870

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


#4 The Melody Maker   Members   -  Reputation: 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! ^__^



#5 lomateron   Members   -  Reputation: 363

Like
0Likes
Like

Posted 11 February 2013 - 09:22 AM

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



#6 Nik02   Crossbones+   -  Reputation: 2870

Like
0Likes
Like

Posted 12 February 2013 - 02:20 AM

For win98 compatibility? :D


Niko Suni


#7 lomateron   Members   -  Reputation: 363

Like
0Likes
Like

Posted 12 February 2013 - 04:53 AM

why windows 98?



#8 Nik02   Crossbones+   -  Reputation: 2870

Like
0Likes
Like

Posted 12 February 2013 - 06:14 AM

I don't know, just guessing smile.png

 

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


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

Niko Suni


#9 Nik02   Crossbones+   -  Reputation: 2870

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


#10 The Melody Maker   Members   -  Reputation: 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. smile.png

 

* 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. happy.png  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.



PARTNERS