Archived

This topic is now archived and is closed to further replies.

Fast pixel plotting?

This topic is 5126 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

Can anybody tell me how to draw pixels much faster than using SetPixel? I know you can use either assembler or direct memory access, but I don''t know how to implement it! I tried some assembler functions from one book, but compiler isn''t able to make the file. I don''t understand errors because I don''t understand Assembler Can anybody tell me where to find such functions (under C++ DirectX) or send me one? Thanks!

Share this post


Link to post
Share on other sites
Well, why would you want to plot pixels? What are you trying to do? There isn't ayn example where plotting pixels the only way to do it.

Plus, you write in "Assembly" and the code is parsed by the "assembler" (I think).

[edited by - PlayGGY on November 28, 2003 12:20:46 PM]

Share this post


Link to post
Share on other sites
quote:
Well, why would you want to plot pixels?

Because not everyone is doing 3D stuff. If he''s doing 2D effects, then he''ll want to plot pixels. Or, maybe he''s interested in making his own graphics library.

Writing in assembly won''t make a difference, really, unless we''re talking about using string instructions as a substutite for, say, memcpy—and even that is a moot point when you enable intrinsic functions in your compiler. So, the fastest starting point is to lock your buffer. This gives you a pointer to its memory. You''ll need to take note of its stride, because you''ll use that in your x/y --> offset calculation. Once you''ve done that, dereference the pointer or access it as an array. Or, use it with memcpy and memset to fill or copy entire blocks. After locking the surface, you could always access that memory using assembly functions. No matter what, don''t forget to unlock your buffer when you''re done.

Share this post


Link to post
Share on other sites
Even if he is doing 2D stuff, he could use texture quads. Maybe he for some reason he wanted to render 1 pixel all alone, but even then rendering Direct3D points would be faster.

[edited by - PlayGGY on November 28, 2003 8:27:13 PM]

[edited by - PlayGGY on November 28, 2003 8:27:46 PM]

Share this post


Link to post
Share on other sites
If you''re using DirectDraw, here''s a decent one I used a long time ago:

Here''s the class definition so you know what it''s using:

class S3DDDSURFACE
{
protected:
LPDIRECTDRAWSURFACE7 m_Surface;
S3Dlong m_VideoPitch;
LPVOID m_VideoStart;
S3Dboolean m_IsColorKeyed;
S3Dint m_SurfaceLocked;
DDSURFACEDESC2 m_SurfaceDescription;
//--

public:
S3DDDSURFACE();
~S3DDDSURFACE();
//--

LPDIRECTDRAWSURFACE7 GetSurface(S3Dvoid);
S3Dboolean GetIsColorKeyed(S3Dvoid);
//--

S3DERROR CreateSurface(LPDIRECTDRAWSURFACE7 Surface);
S3DERROR CreateSurface(LPDIRECTDRAW7 DDraw, DDSURFACEDESC2* SurfaceDescriptin);
S3Dvoid CleanupSurface(S3Dvoid);
//--

S3DERROR DrawBitmap(S3Dcrptr Filename, S3Dulong Width, S3Dulong Height);
S3DERROR DrawBitmap(HBITMAP BMPHandle, S3Dulong X, S3Dulong Y, S3Dulong Width, S3Dulong Height);
S3DERROR DrawText(HFONT FontHandle, S3Dcrptr Text, S3Dulong X, S3Dulong Y, COLORREF Color);
//--

S3Dint LockSurface(S3Dvoid);
S3Dvoid UnlockSurface(S3Dvoid);
S3Dulong AutoGrabColorKey(S3Dvoid);
S3Dvoid GrayScaleSurface(S3Dvoid);
S3DERROR SetColorKey(S3Dulong ColorKey);
S3Dulong ConvertGDIColor(COLORREF Color);
S3DERROR GetBitMaskInfo(S3Dulong Mask, S3Dulong* retShift, S3Dulong* retBits);
//--

S3Dvoid GetPixelXL(S3Dint X, S3Dint Y, S3Duchar &retRed, S3Duchar &retGreen, S3Duchar &retBlue);
S3Dvoid SetPixelXL(S3Dint X, S3Dint Y, S3Duchar Red, S3Duchar Green, S3Duchar Blue);
S3Dvoid GetPixelXL_LITE(S3Dint X, S3Dint Y, S3Duchar &retRed, S3Duchar &retGreen, S3Duchar &retBlue);
S3Dvoid SetPixelXL_LITE(S3Dint X, S3Dint Y, S3Duchar Red, S3Duchar Green, S3Duchar Blue);
S3Dvoid DrawRectangleXL(S3Dint X, S3Dint Y, S3Dint Width, S3Dint Height, COLORREF Color);
S3Dvoid DrawRectangleXL_LITE(S3Dint X, S3Dint Y, S3Dint Width, S3Dint Height, COLORREF Color);
};


Here''s the Lock/Unlock surface functions:

S3Dint S3DDDSURFACE::LockSurface(S3Dvoid)
{
if(this->m_Surface == NULL)
{
return 0;
}
//--

if(this->m_Surface->Lock(NULL, &this->m_SurfaceDescription, DDLOCK_WAIT, NULL) != DD_OK)
{
return 0;
}
//--

this->m_VideoPitch = this->m_SurfaceDescription.lPitch;
this->m_VideoStart = this->m_SurfaceDescription.lpSurface;
this->m_SurfaceLocked = 1;
return 1;
}

S3Dvoid S3DDDSURFACE::UnlockSurface(S3Dvoid)
{
if(this->m_Surface == NULL || !this->m_SurfaceLocked)
{
return;
}
//--

this->m_Surface->Unlock(NULL);
this->m_VideoPitch = 0;
this->m_VideoStart = 0;
this->m_SurfaceLocked = 0;
}


And here''s the Set/Get Pixel functions:

S3Dvoid S3DDDSURFACE::GetPixelXL_LITE(S3Dint X, S3Dint Y, S3Duchar &retRed, S3Duchar &retGreen, S3Duchar &retBlue)
{
if((this->m_Surface == NULL) | (!this->m_SurfaceLocked))
{
return;
}
S3Duchar Red;
S3Duchar Green;
S3Duchar Blue;
//--

S3Dlong Pitch = this->m_VideoPitch;
LPVOID Start = this->m_VideoStart;
S3Dint BPP = this->m_SurfaceDescription.ddpfPixelFormat.dwRGBBitCount;
//--

if((BPP == 16) | (BPP == 24))
{
_asm
{
PUSH ESI
PUSHF
MOV EAX, Y
MUL Pitch
MOV EBX, EAX
MOV EAX, X
MOV CX, 3
MUL CX
ADD EAX, EBX
MOV ESI, Start
ADD ESI, EAX
MOV AL, [ESI]
INC ESI
MOV DH, [ESI]
INC ESI
MOV DL, [ESI]
MOV Blue, AL
MOV Green, DH
MOV Red, DL
POPF
POP ESI
}
}
else
{
if(BPP == 32)
{
_asm
{
PUSH ESI
PUSHF
MOV EAX, Y
MUL Pitch
MOV EBX, EAX
MOV EAX, X
MOV CX, 4
MUL CX
ADD EAX, EBX
MOV ESI, Start
ADD ESI, EAX
MOV AL, [ESI]
INC ESI
MOV DH, [ESI]
INC ESI
MOV DL, [ESI]
MOV Blue, AL
MOV Green, DH
MOV Red, DL
POPF
POP ESI
}
}
}
retRed = Red;
retGreen = Green;
retBlue = Blue;
}
//--

S3Dvoid S3DDDSURFACE::SetPixelXL_LITE(S3Dint X, S3Dint Y, S3Duchar Red, S3Duchar Green, S3Duchar Blue)
{
if((this->m_Surface == NULL) | (!this->m_SurfaceLocked))
{
return;
}
//--

S3Dlong Pitch = this->m_VideoPitch;
LPVOID Start = this->m_VideoStart;
S3Dint BPP = this->m_SurfaceDescription.ddpfPixelFormat.dwRGBBitCount;
//--

if((BPP == 16) | (BPP == 24))
{
_asm
{
PUSH ESI
PUSHF
MOV EAX, Y
MUL Pitch
MOV EBX, EAX
MOV EAX, X
MOV CX, 3
MUL CX
ADD EAX, EBX
MOV ESI, Start
ADD ESI, EAX
MOV AL, Blue
MOV DH, Green
MOV DL, Red
MOV [ESI], AL
INC ESI
MOV [ESI], DH
INC ESI
MOV [ESI], DL
POPF
POP ESI
}
}
else
{
if(BPP == 32)
{
_asm
{
PUSH ESI
PUSHF
MOV EAX, Y
MUL Pitch
MOV EBX, EAX
MOV EAX, X
MOV CX, 4
MUL CX
ADD EAX, EBX
MOV ESI, Start
ADD ESI, EAX
MOV AL, Blue
MOV DH, Green
MOV DL, Red
MOV [ESI], AL
INC ESI
MOV [ESI], DH
INC ESI
MOV [ESI], DL
POPF
POP ESI
}
}
}
}


Now just call the this:
LockSurface();
SetPixelXL_LITE(50, 50, 255, 0, 0);
UnlockSurface();

Remember I said this was old, so there might be a faster way. That should give you some ideas though.

Best of luck,

-UltimaX-

"You wished for a white christmas... Now go shovel your wishes!"

Share this post


Link to post
Share on other sites
Some of the formatting got messed up O_°
Oh well, if you have any problems let me know. One of use should be able to help you

-UltimaX-

"You wished for a white christmas... Now go shovel your wishes!"

Share this post


Link to post
Share on other sites
For me, being able to plot single pixels is very important. The absence of a drawPixel function in the standard Java API was the result of a terrible design choice. I use single pixels for graphics programming such as fractals and particle physics and other things.

[edited by - pUnkInner on November 29, 2003 3:38:37 AM]

Share this post


Link to post
Share on other sites
It always drives me insane when I see people say "There is no reason for you to do x" when someone asks how they should do x. There is no way you can know that, it''s not your project. I can thnk of about a billion reasons why you''d want to plot pixels without resorting to texture quads.

There''s an article in the articles section I wrote some years ago on this subject, called "Bit Depth Independant Pixel Plotting in DirectDraw" or something like that. It was written for DirectDraw, but the concepts should apply to a D3D texture surface in an equivalent manner.

Share this post


Link to post
Share on other sites
quote:
Original post by RonHiler
It always drives me insane when I see people say "There is no reason for you to do x" when someone asks how they should do x. There is no way you can know that, it''s not your project. I can thnk of about a billion reasons why you''d want to plot pixels without resorting to texture quads.

There''s an article in the articles section I wrote some years ago on this subject, called "Bit Depth Independant Pixel Plotting in DirectDraw" or something like that. It was written for DirectDraw, but the concepts should apply to a D3D texture surface in an equivalent manner.


Actually, I gree with the first thing you said. I figured he was probably trying to do sprites, and texture quads would be faster. I was just trying to help him, thats all.

And, by the way, you could still use a point list to render single pixels, if you want.

But, if he wants to render pixels a fast way just because he thinks it would be a cool thing to try (I have done that), then I am sorry that I tried giving him a faster method.

Share this post


Link to post
Share on other sites
quote:
Original post by RonHiler
It always drives me insane when I see people say "There is no reason for you to do x" when someone asks how they should do x. There is no way you can know that, it''s not your project. I can thnk of about a billion reasons why you''d want to plot pixels without resorting to texture quads.

There''s an article in the articles section I wrote some years ago on this subject, called "Bit Depth Independant Pixel Plotting in DirectDraw" or something like that. It was written for DirectDraw, but the concepts should apply to a D3D texture surface in an equivalent manner.


While I agree with you that there may be some use for ploting a single pixel at a time in memory without any sort of order (enumerated in my reply), you must understand that there are 90% chances that the poor guy is trying to draw a full scene or sprite using a PlotPixel() function which is inneficient for this task (search for Batching on this site for an explanation). PlayGGY simply asked WHY he wanted to draw a pixel, in a way to direct him in a more efficient way.

Then, people started answering for Bartiss, who didn''t reply yet BTW. The fact is, we still don''t know on what library he wants to draw the pixel (DD or D3D), and most importantly, on what purpose.

Share this post


Link to post
Share on other sites
maybe he just wanted to do it for the sake of doing it, I know there are itmes were I just like doing things in a bass acwards way just becase it''s fun to do things the wrong way.
for example I once made a graphics system that used a char array and cout as a bassis for drawing things, it was slow and ugly and flickered to the point of uselessness, but it was fun to make.

Bobboau, bringing you products that work... in theory

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
simple...

//call an interrupt in screen x
pokeb(0xA000,(width*y)+x,color);
//return to text mode calling interrupt 0x10 back to text mode


to get the color value...

peekb(0xA000,(width*y)+x);

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
simple...

//call an interrupt in screen x
pokeb(0xA000,(width*y)+x,color);
//return to text mode calling interrupt 0x10 back to text mode


to get the color value...

peekb(0xA000,(width*y)+x);


That looks like code from some BASIC language... he is using C++.

Share this post


Link to post
Share on other sites
quote:
Original post by pUnkInner
It looks more like calls to some assembly functions to me.


Yes, but I remember in QBasic they had Poke/Peek. You would have to deal with the VRAM stride if you were really going to deal with the VRAM up close and personal. Plus, what is "screen x"? In Qbasic they had screen modes too (oh boy, set up all of the video stuff with a simple "screen 7"...), so I figured it was probably some other BASIC language.



[edited by - PlayGGY on November 30, 2003 1:08:04 AM]

[edited by - PlayGGY on November 30, 2003 1:08:20 AM]

Share this post


Link to post
Share on other sites
Uh, adding polygons with textured quads is probably not the best way to go abotu things since that would take more processing power than just plotting pizels (though i dont know if textured quads would allow for acceleration or somethin cool like that)

Share this post


Link to post
Share on other sites
quote:
Original post by Ademan555
Uh, adding polygons with textured quads is probably not the best way to go abotu things since that would take more processing power than just plotting pizels (though i dont know if textured quads would allow for acceleration or somethin cool like that)


Actually Direct3D can draw a POINT-type primitive. HW-accelerated and all.

Speaking of which, I have a question. For plotting up to a thousand points per frame, would it be faster to use the point primitives, or to lock the frame buffer?

Share this post


Link to post
Share on other sites
Thanks for all the answers!

All I wanted to do is to create some 2D effects such as lighting,fire,flares,morphing etc.

I know enough about arithmetics but I lacked technical experience!

Share this post


Link to post
Share on other sites
Well, I''d recommend figuring out exactly what to do and then write a good algoritm that does it.

DON''T USE A SETPIXEL FUNCTION !!!

You need to lock the surface once and then run the algorthm that does the effekt. By using a setpixel function you will loose alot of speed, well, you could just make the funktion ''inline'' and gain some speed but it will still multiply y with the pitch and such things drain speed if you do them alot. Better to do it all at once. And then ofcourse read from smem, write to vmem.

/MindWipe

Share this post


Link to post
Share on other sites
quote:
Original post by Pipo DeClown
D3D: Point List?

--
You''re Welcome,
Rick Wong

- sitting in his chair doing the most time-consuming thing..


Yeah that''s what I was on about.

So anyone have any figures on which is faster for < 1000 px? Locking the buffer or drawing a point list primitive?

Share this post


Link to post
Share on other sites