Skip to main content
GameDev.net gamedev.net
🔒 Locked

Plotting pixels using DX9

Started by dstruktiv Jan 20, 2010 at 8:26 PM 16 replies 2.3k views
Original Post
dstruktiv
dstruktiv
I'm currently learning how to code emulators, I've started with a Chip 8 emu from scratch using the awesome documentation about them on the net. I'm at the point where my emu runs and I can see the debug output and see it executing all the opcodes. My screen info is stored in a char array which represents the 64x32 resolution of the Chip8 so:
unsigned char screen[2047]
Each char in the array is either 1 for on or 0 for off. Now what I need to do is loop through this array and draw it to the screen, so draw 64 chars at 1-64,0 then draw the next 64 chars at 1-64,1 then the next at 1-64,2 etc until I get to 64,31. Then I want to display that on the screen. I've been told I need to create a texture and an object to apply it to i.e. a rect, then each update I want to lock the texture, clear it out, plot my pixels depending on what's in the char array, unlock the texture and render the rect with the texture applied to it. I'd obviously increase each char to say take up 4 or 8 pixels so I can increase the screen size but I can handle that. What I've done so far is create my d3d device and implement a simple update and render loop which at the moment just clears the screen and redraws it. I'm really stuck when it comes to creating the texture and the object and plotting the pixels. I've been on Google that last few hours and come up with nothing. So if anyone has any experience with DX9 then I'd really appreciate some advice or a helping hand (This has to be done using dx9).
Nazdreg
Nazdreg
do you have to use Direct3D9? Could you not use DirectDraw9?
"REAL programmers use a magnetised needle and a steady hand"xkcd.com/378
dstruktiv
dstruktiv
It has to be Direct3D9 sorry.
Nazdreg
Nazdreg
Why is that?
"REAL programmers use a magnetised needle and a steady hand"xkcd.com/378
MJP
MJP
Quote:
Original post by Nazdreg
Could you not use DirectDraw9?


I'd imagine that would be kind of hard, since there is no DirectDraw9. :P

But I do agree that D3D9 is a very poor fit for this task. The API and the hardware it supports are designed for rasterizing triangles and writing pixels using shader programs executed on the GPU...drawing all of the pixels on the CPU isn't really an intended use case, and will take quite a bit of work for what is realyl a simple operation. I would instead recommend sparing yourself the hassle of working with D3D and instead just use something like GDI directly, or pixeltoaster.

If you really need to do this with D3D, the fastest way will probably be to create a texture with the dimensions of the device (64x32) and every frame fill it with your pixel info using LockRect. Then you can simply draw that texture to the backbuffer, which is very easy if you use ID3DXSprite.
Nazdreg
Nazdreg
Wait, so if you have DirectX9, you cant use DirectDraw? Or does it come with an older version of it?
"REAL programmers use a magnetised needle and a steady hand"xkcd.com/378
dstruktiv
dstruktiv
////////////////////////////IDirect3DTexture9* display;D3DLOCKED_RECT rect;/////main/////pDevice ->CreateTexture(64, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &display, 0);/////render/////display->LockRect(0,▭,NULL, NULL);	for(int i=0; i <2048; i++)	{		if (screen == 0)		{			*((DWORD*)(rect.pBits)+i) = 0x00000000;		} 		else		{			*((DWORD*)(rect.pBits)+i) = 0xFFFFFFFF;		}	}	display->UnlockRect(0);


It's probably quite obvious I have zero experience with what I'm doing, screen is my emu display buffer, 0 = black, 1 = white, so I loop through that setting each pixel in the display texture to either black or white depending on whats in screen. Is this right or completely wrong?
nobodynews
nobodynews
Quote:
Original post by Nazdreg
Wait, so if you have DirectX9, you cant use DirectDraw? Or does it come with an older version of it?
The newer DirectX SDKs dropped library support for DirectDraw. This just means that in order to use DirectDraw one must get an older version of the SDK that did have it. I think it also means that a number of newer graphics cards have poor DirectDraw support but that I'm less sure of.
C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) ,
Nazdreg
Nazdreg
Hm, ok thanks. Do you know what was the latest version of directx that had directdraw?
"REAL programmers use a magnetised needle and a steady hand"xkcd.com/378
Haytil
Haytil
Quote:
Original post by Nazdreg
Hm, ok thanks. Do you know what was the latest version of directx that had directdraw?


DirectX 7.
Ravyne
Ravyne
Why *DOES* it have to be Direct3D? Its not like you're going to get any hardware acceleration. All you're doing is creating an unnecessary dependency for no reason at all.

I would look into rendering Windows DIB sections (which is what I do for my software renderer), or look into TinyPTC/OpenPTC -- which are very, very simple, cross-platform framebuffers, and will take care of all the platform-dependant stuff for you.
throw table_exception("(? ???)? ? ???");
dstruktiv
dstruktiv
It *has* to be D3D because that's what I asked :)

I obviously have a reason for using d3d and I said it *has* to be d3d because I knew others would recommend doing it a different way.

I know it can be done with D3D so if anyone can help I would really appreciate it.
Codeka
Codeka
Quote:
Original post by dstruktiv
I know it can be done with D3D so if anyone can help I would really appreciate it.
You've been given a number of answers already that will help.

I noticed that you just edited your response to remove the bit where you said this is being done for the Xbox. Do you have an Xbox devkit? If not, there's not much point limiting yourself to DirectX.
Endurion
Endurion
Quote:
Original post by dstruktiv
////////////////////////////IDirect3DTexture9* display;D3DLOCKED_RECT rect;/////main/////pDevice ->CreateTexture(64, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &display, 0);/////render/////display->LockRect(0,▭,NULL, NULL);	for(int i=0; i <2048; i++)	{		if (screen == 0)		{			*((DWORD*)(rect.pBits)+i) = 0x00000000;		} 		else		{			*((DWORD*)(rect.pBits)+i) = 0xFFFFFFFF;		}	}	display->UnlockRect(0);




Almost correct, you're not taking account of the pitch. You have to process the pixel access line wise. The texture is very probably not a continuous area of memory.
Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>
ET3D
ET3D
First let me see if I understand. You have a 32 row 64 column array of one bit pixels (2048 in total, your screen[2047] is wrong), each represented by a char. You want to draw that as a black/white image.

One way is to create a dynamic 32x64 texture with one byte per pixel (A8 or L8 format). Copy the data to it by locking, copying, unlocking. Check the pitch. If it's 64 bytes, you can just copy everything together. If it's not, you can memcpy one row at a time. Then draw a quad, where the pixel shader draws white for the 'on' value and black for the 'off' (or vice versa). Or just clear to one value, draw the other value with alpha testing, using the texture for alpha.

To save the issue of having to checking the pitch you can create a 1x2048 texture copy to it using one memcpy, but then you have to do a little more address calculation in your shader.
MJP
MJP
Quote:
Original post by dstruktiv
It *has* to be D3D because that's what I asked :)

I obviously have a reason for using d3d and I said it *has* to be d3d because I knew others would recommend doing it a different way.



Many times programming is all about solving the right problem, instead of spending hours/days/weeks solving the wrong one. In this case we all seem to agree that making D3D work is the wrong problem, and the real problem is that there are plenty of better alternatives available. Personally I feel I would be doing you a great disservice by saying "okay here's some code that shows you how to do it" without bothering to bring up the fact that D3D is way more complex than you need.

I'm also not willing to accept your explanation of "I obviously have a reason for using D3D" since...

A. You haven't given us that reason

and

B. If you don't know how to do something as simple as locking a texture and drawing it, you're probably not familiar enough with the API to be making decisions regarding whether you *need* to use it.

I don't mean any offense by this...I'm just trying to help you out after all and so is everyone else in this thread. If you have some important reason for needing to use D3D, just say it.
dstruktiv
dstruktiv
The reason I was locked to D3D9 is because it was for the Xbox 360.

I had it working fine on the PC using SDL but that doesn't help me on the Xbox :p

Still got some issues to work out with some things disappearing and reappearing every alternating update call but I can handle that :)

m_pd3dDevice ->CreateTexture(64, 32, 1, 0, D3DFMT_LIN_A8R8G8B8, D3DPOOL_DEFAULT, &display, 0);		display->LockRect(0,▭,NULL, NULL);		BYTE* pByte =(BYTE*)rect.pBits;		for (DWORD y=0;y<32;++y)		{			for (DWORD x=0;x<64;++x)			{				DWORD index = (x*4)+(y*rect.Pitch);				pByte[index] 	= (BYTE)(screen[(y*64) + x] == 0 ? 0x00 : 0xFF);				pByte[index+1] 	= (BYTE)(screen[(y*64) + x] == 0 ? 0x00 : 0xFF);				pByte[index+2] 	= (BYTE)(screen[(y*64) + x] == 0 ? 0x00 : 0xFF);				pByte[index+3]	= (BYTE)(screen[(y*64) + x] == 0 ? 0x00 : 0xFF);			}		}	display->UnlockRect(0);


IMG_2060.jpg
clashie
clashie
What about treating a vertex / point as a pixel? I guess you could just amass a ton of them in a nice batch and draw that.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.