Sign in to follow this  

How can I examine pixels in D3D?

This topic is 4327 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm using Direct3D with textured quads to make a 2D platformer. I want the ground to be defined by tiles of image files, where each tile is white with a 1-pixel-wide black line drawn across it. Is there a way in D3D that I can examine each pixel of an image file?

Share this post


Link to post
Share on other sites
Yes, it is possible - but we need a lot more details before we can suggest something [smile]

  1. What language are you using? C++/C#/VB
  2. What version of D3D - 7,8,9?
  3. Are you wanting to load the texture then read it, or do you want to read the pixels as they are in the file?
  4. Do you want to read the pixels from the texture (as stored in memory) or from the screen (after you've rendered everything)?


The general idea is to use "locking" - you lock the contents of the texture and receive a pointer to the memory. You can then read/write to this memory and unlock the texture again.

hth
Jack

Share this post


Link to post
Share on other sites
Ah, sorry.

C++, DirextX9, and I want to read the pixels from memory.
Not sure what you mean about reading the pixels as they are in the file, vs loadng it first, but I don't want to be accessing the HDD tile by tile if that's the point.

And thanks, I'll look into locking.

Share this post


Link to post
Share on other sites
Quote:
Original post by Defend
C++, DirextX9, and I want to read the pixels from memory.

Okay, well it'll either be IDirect3DSurface9::LockRect() or IDirect3DTexture9::LockRect() that you need to investigate. Given that you're wanting to render the tiles, I'd recommend loading into and using textures rather than surfaces.

Quote:
Original post by Defend
Not sure what you mean about reading the pixels as they are in the file, vs loadng it first, but I don't want to be accessing the HDD tile by tile if that's the point.

It's a fairly minor point really, but if you have your image stored as an 888/24bit bitmap and you were to load it into a different format (say 565/16bit) in your program then the values you read from memory won't be the same as the ones you might have been expecting.

It's usually more of an issue when dealing with more 'exotic' formats that the hardware might not support (thus you have to choose a different format to store it in memory).

hth
Jack

Share this post


Link to post
Share on other sites
Thanks.

One more question.. is there a way I can load and make use of the pixel data in an image file with only a 1 or 2-bit depth? As in, I only need a black and white image, or something similar, so even an 8-bit depth seems unnecessary. Or does DirectX's compression save the memory space for such textures anyway?
Basically, how do I save memory when I only need black and white image files?

Share this post


Link to post
Share on other sites
Quote:
Original post by Defend
Bump for that last question. How can I create, and use, a 1 or 2-bit image file?
Unless there is a corresponding D3DFMT_** tag, then i'm pretty sure it's not possible.

An alternative might be to find a way of "packing" multiple 1 or 2 bit textures into a larger quantity. It gets a little tricky, but you should be able to put 4 2-bit textures inside an _L8 or A8 format and unpack them in a shader.

hth
Jack

Share this post


Link to post
Share on other sites
Quote:
Original post by jollyjeffers
Okay, well it'll either be IDirect3DSurface9::LockRect() or IDirect3DTexture9::LockRect() that you need to investigate. Given that you're wanting to render the tiles, I'd recommend loading into and using textures rather than surfaces.


Why is that; concerning the surfaces and textures?

Share this post


Link to post
Share on other sites
Quote:
Original post by arithma
Quote:
Original post by jollyjeffers
Okay, well it'll either be IDirect3DSurface9::LockRect() or IDirect3DTexture9::LockRect() that you need to investigate. Given that you're wanting to render the tiles, I'd recommend loading into and using textures rather than surfaces.


Why is that; concerning the surfaces and textures?

Surfaces cannot be used for rendering. They can only be rendertargets or simple image storage (e.g. they don't have to have power-of-two dimensions and they don't support MIPMAPs).
Hence, to render a surface, you would have to copy it (or a part of it) to a texture object first. This is both inefficient and cumbersome, unless you have to do that to support very large images (on-the-fly, that is - if you know your image resources are too big, breaking them up into smaller textures would be subject to pre-processing).

HTH,
Pat.

Share this post


Link to post
Share on other sites
Is he even talking about rendering these 1-bit images, or just using them for collision detection? You might want to consider using some sort of duplicate (low quality, 1 bit, low mem usage) images that you could load into system memory for calculations and load separate but corresponding high quality 32-bit textures to use as your actual graphics. You gain the advantage of not needed collision information inside your rendered graphics. Thus you can have things like blades of grass, etc. that appear in the graphic but don't influence the player. Plus, obviously, locking/examining resources on the video card is SLOW, so you're going to need some sort of system memory duplicate anyways...

Share this post


Link to post
Share on other sites
Yes, that is exactly what I'm trying to do, which is why I'm wondering if its possible to create and use 1 bit textures. I only need to read from the texture.

Secondly, I'm getting some memory access errors while trying to learn how to use LockRect(). Does the following look correct? And if so, what would I do to output each byte (in hex or oct) of my texture?


D3DLOCKED_RECT pLockedRect;
BYTE* aByte;
INT thePitch, cell;

ERRCONT(m_VLoadedTextures[whichTexture].filename);
m_VLoadedTextures[whichTexture].rawTexture->LockRect(0, &pLockedRect, NULL, D3DLOCK_DISCARD);

thePitch = pLockedRect.Pitch;
aByte = (BYTE*)(&pLockedRect.pBits);

Share this post


Link to post
Share on other sites
I'm pretty sure it should be reinterpret_cast< BYTE* >( pLockedRect.pBits ). pBits is defined as void*, so your & will actually be casting a void** to a BYTE*.

If it's just for a collision mask, I wouldn't bother storing it in a D3D format. Load it in as a binary object and store it in your own format - not only is is more flexible, but it'll probably be faster (or, offer more room for optimization).

Jack

Share this post


Link to post
Share on other sites

This topic is 4327 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this