Notes on plotting pixels

Started by
7 comments, last by slayemin 19 years, 4 months ago
Here is a problem I was banging my head on all night and I just figured out the reasons for everything. I'm going to attempt to share this so that I'm the only one who had to make the hard mistakes on your behalf. First, I was running in a 24 bit resolution. This means I have 24 bits for a color, thus, 8 for each RGB value. Originally I was using the USHORT to contain my RGB value, however I was getting some very strange color results: RGB(255,255,255) = white RGB(0,255,255) = white RGB(0,0,255) = teal (I think) It looks like the red values weren't being used, so: 00000000 11111111 11111111 = WHITE!!! now, why would that be? because the USHORT variable is only 2 BYTES in size, thus it could only contain the 2 right bytes: 11111111 11111111, which indeed does equal white! I fixed that problem by using a larger variable: DWORD (4 bytes) this should easily contain the info for both 24bit and 32bit color resolutions. Hope this helps someone! :)
Advertisement
Quote:RGB(0,0,255) = teal (I think)

Actually, that's cyan.

EDIT: nope, I'm wrong

Cyan (00FFFF)
Blue (0000FF)
Quote:Original post by slayemin
Here is a problem I was banging my head on all night and I just figured out the reasons for everything. I'm going to attempt to share this so that I'm the only one who had to make the hard mistakes on your behalf.

First, I was running in a 24 bit resolution. This means I have 24 bits for a color, thus, 8 for each RGB value.

Originally I was using the USHORT to contain my RGB value, however I was getting some very strange color results:
RGB(255,255,255) = white
RGB(0,255,255) = white
RGB(0,0,255) = teal (I think)

It looks like the red values weren't being used, so:
00000000 11111111 11111111 = WHITE!!!
now, why would that be? because the USHORT variable is only 2 BYTES in size, thus it could only contain the 2 right bytes:
11111111 11111111, which indeed does equal white!


@Mushu: He seems to mean that the red bits were being cut off of his data (because of the USHORT only holding 16 bits), and the rest was interpreted as a 565 RGB colour or something.

Thus cyan = (0,255,255) in -> 1111111111111111 -> 11111 111111 11111 -> white out

blue = (0, 0, 255) in -> 0000000011111111 -> 00000 000111 11111 -> blue slightly green-twinged out.

Or something? :s
My favorite kind of programming mistake! I recently did something very similar in assembly (one instruction) that broke everything.
:P I'm happy to know that I'm not alone.
I finally got my pixel plotting to work, though it doesn't seem to be very fast or efficient.
I'm using DirectDraw with page flipping, so the fastest frames per second possible is equal to the monitor refresh rate (me: 72)
When I start plotting lots of pixels every frame (like 100 pixels) my frame rate starts to drop. Especially when I create a 100x100 or greater FOR loop. :P

Is this common with everyones pixel plotting routines or is it just me expecting too much?
Quote:Original post by slayemin
:P I'm happy to know that I'm not alone.
I finally got my pixel plotting to work, though it doesn't seem to be very fast or efficient.
I'm using DirectDraw with page flipping, so the fastest frames per second possible is equal to the monitor refresh rate (me: 72)
When I start plotting lots of pixels every frame (like 100 pixels) my frame rate starts to drop. Especially when I create a 100x100 or greater FOR loop. :P

Is this common with everyones pixel plotting routines or is it just me expecting too much?
Well, how are you doing the for loop? Are you calling a draw pixel function? It would make more sense to use a memcopy for each row or such, if that is a viable option for you, rather than draw 100 pixels in a row, then move down and so one.
HAHAHA, its the simplest method I could think of:

for(int x=0;x<100;x++){    for(int y=0;y<100;y++)   {        //params: X location, Y location, Red, Green, Blue, Surface        Plot_Pixel(x+300,y+300,255,255,255,lpddsback);   }}


This would create a 100x100 white block starting at (300,300) and ending at (400,400). ;P I can make some cool gradient effects if I set the colors initially at 0 and increase with the X & Y values until 255, but other then something pretty, theres no real practical use for it. heh, that makes my framerate drop to about 3-5 FPS.
Here are some things to watch out for:

(1) You're probably locking and unlocking the back buffer every time you draw a pixel -- this is EXTREMELY slow. Make sure you lock it before your double-for loop and then unlock it after drawing all of the pixels. That is, you lock it ONCE and unlock it ONCE per frame.

(2) Note that you have to compute the pixel location for EVERY pixel, which is a few multiplies. Note also that each row pixel is contiguous to the last one, so it is located at exactly 4 bytes after the current pixel's address in memory. To take advantage of this, you might want to make a draw-rectangle function that calculates the buffer address for the upper-left hand rectangle pixel. Now your inner for-loop is just *(bufferPointer++) = color, given DWORD *bufferPointer (note this is for 32-bit color, 24-bit is slightly different). The outer for-loop would then increment the bufferPointer by how many pixels are in a row (HOWEVER, in DirectDraw sometimes there are "invisible" pixels in a row that you need to skip over due to how video cards support different resolutions).

(3) You can inline the SetPixel function so that the expensive function calls are not made (eg it's more like a macro).

Of these three, #1 will give you a HUGE speed boost, and you probably won't really notice #2 and #3. If you want any more sugestions, post your latest code!
h20, member of WFG 0 A.D.
OMG! wow!!! you're right! when I Lock/Unlock the surface only once per frame instead of 255*255=65025 times per frame, my computer definately speeds up!!!! Wow, that was super helpful! I got the maximum frames per second when I do it your way! mucho gracias!

This topic is closed to new replies.

Advertisement