Skip to main content
gamedev.net
🔒 Locked

Draw Pixels?

Started by McDusty 7 replies 650+ views
Original Post
McDusty
McDusty
Hi Im trying to do the equivalent of glDrawPixels in Directx, but find myself a little stuck. Basically I have a 2d array of RGB values (my own framebuffer) and I want to draw these in a directx window. Cheers for your help.
"I have taken more out of alcohol than alcohol has taken out of me."- Sir Winston Churchill
johnnyBravo
johnnyBravo
maybe the dx sprite class, you can set the rect size to 0,0,1,1
and maybe have no texture, i think u can do that, or just have a white single pixel texture, then u just set the rect to null instead, but then you set the rgb colour value,

or you can use vertices, but 2d ones i think u have to keep saving the to the vb, which is bad, maybe you can use matrices somehow on them to make them move, but im yet to do so
fractoid
fractoid
I dunno about DX9 (have been using OpenGL since I discovered it's immensely superior non-suckyness, maybe should revisit DX) but in Direct3D 8 I did this:

1) Create an IDirect3DTexture8 of appropriate size (powers of 2, whatever, blah blah. Ask it not to be automagically mipmapped)
2) Lock the top level of it (lr = D3DLOCKED_RECT)
3) Write to lr.pBits, making sure that you respect lr.Pitch otherwise your code won't work properly on non-nVidia cards
4) Unlock the surface

Stolen directly from an app. that uses dynamic textures:
(pCurrentSource->GetBits() gives you a DWORD pointer to a packed 32-bit bitmap)

//stretch the software effect output to our source texture

D3DLOCKED_RECT lr;
if (FAILED(pDestSurface->LockRect(0, &lr, 0, 0))) return;
DWORD *pTex = static_cast<DWORD*>(lr.pBits);
int pitchTex = lr.Pitch / 4;
DWORD *pSrc = pCurrentSource->GetBits();
int srcWidth = pCurrentInput->GetWidth(), srcHeight = pCurrentInput->GetHeight();
int wdiff = (srcWidth << 16) / TEX_WIDTH;
int hdiff = (srcHeight << 16) / TEX_HEIGHT;
for (int y=0, srcY=0; y<TEX_HEIGHT; y++, srcY+=hdiff)
{
DWORD *src = pSrc + srcWidth * (srcY>>16);
DWORD *dst = pTex + pitchTex * y;
for (int x=0, srcX=0; x<TEX_WIDTH; x++, srcX+=wdiff)
dst[x] = src[srcX>>16];
}
pDestSurface->UnlockRect(0);


[edit: oh, and this rescales the input image to the size of the texture, using my standard fixed-point resizerer. neat, hey? ]
[edit edit: this should work for the backbuffer too, as Endurion says. In which case you can probably not use the fixed-point stuff if your framebuffer is the same size as the screen. In fact you don't need to double-buffer on the video card at all since you're handling double-buffering manually.]
[edit^3: dammit. confusing phraseology. Read "you can probably not use the fixed-point stuff" as "you shouldn't need the fixed-point stuff", not as "you can't use the fixed-point stuff". D'oh.]

[edited by - fractoid on March 3, 2004 9:49:33 AM]

[edited by - fractoid on March 3, 2004 9:51:59 AM]

[edited by - fractoid on March 3, 2004 9:53:40 AM]
Endurion
Endurion
You can always lock the backbuffer and copy your pixeldata inside. If you do, take the pitch and pixel format in account.

[edit- exactly as fractoid shows]

[edited by - Endurion on March 3, 2004 9:49:42 AM]
Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>
J_Vitel
J_Vitel
How about using the D3DPT_POINTLIST primitive??

MyCustomVertex Points[n] = {
// Points
};
.
.
.
IDirect3DVertexBuffer8* pVBPoints;
pD3DDevice->CreateVertexBuffer(n*sizeof(MyCustomVertex),
D3DUSAGE_WRITEONLY,
D3DFVF_MYCUSTOMVERTEX,
D3DPOOL_MANAGED, &pVBPoints);
.
.
.
MyCustomVertex *pVertexes;
pVBPoints->Lock(0,0,&pVertexes,0);
memcpy(pVertexes, Points, sizeof(Points) );
pVBPoints->Unlock();
.
.
.
pD3DDevice->SetVertexShader(D3DFVF_MYCUSTOMVERTEX);
pD3DDevice->SetStreamSource(0,pVBPoints,sizeof(MyCustomVertex));
pD3DDevice->DrawPrimitive(D3DPT_POINTLIST,0,n);
.
.
.
pVBPoints->Release();
My site Jvitel.com
RuneLancer
RuneLancer
Just lock the backbuffer and write directly to it.

The DirectDraw docs (I''m not sure what it''s under if you''re using anything about DirectX7, though you''ll probably find a section on surfaces somewhere in there) lists the a number of useful members the surface structure can use to be drawn to. When you lock the surface, you''ll gain access to a number of properties, including the size of the surface, a pointer to the display region, as well as the pitch (the length of a row of pixels, which is not necessarily equal to the width of the surface! Take this into account!!).

Mind you, you''ll have to refresh your drawing every frame with this method, since the image is invalidated when you flip the surfaces. That is, it''s one-time use. There''s nothing to keep track of which pixels are "supposed" to be drawn or not in-between frames. You''ll have to worry about that yourself.
neneboricua19
neneboricua19
If you''re using D3D, locking the back buffer is *very* bad and should never be done unless there is an EXTREMELY good reason because it totally kills parallelism between the CPU and th GPU.

The best way to do this is to have a dynamic texture that you load with the data in your RGB array. Then you draw a sprite or a screen-aligned quad over the whole screen and apply your dynamic texture to it.

Filling the dynamic texture isn''t very difficult. It''s been discussed many times here in the forum. Do a search of the archives and you''ll get all the info you need.

If you don''t care about performance, you can go ahead and lock the backbuffer directly. Filling the backbuffer is done the same way as filling a dynamic texture.

neneboricua
McDusty
McDusty
Cheers for your help guys,

I''ll have a play with these ideas and get back to ya.
All I need to do is draw a ray traced image to the screen, so performance isn''t a big an issue.
"I have taken more out of alcohol than alcohol has taken out of me."- Sir Winston Churchill
RuneLancer
RuneLancer
Huh, didn''t know about dynamic textures. Guess you learn something new everyday.

You''d probably be able to do a lot more with a texture generated on the fly since it wouldn''t be as static as drawing directly to the screen (or surface, as the case would be). Plus, it would allow you to keep a hold on your image even when you refresh and need to redraw stuff (as in, no need to lock the surface, draw every pixel, unlock, etc.. over again).

Topic Locked

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

Sign in to reply to this topic.