Jump to content
  • Advertisement


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


Optimizing a Pixel Plot for Variable Bit Rates

This topic is 5479 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 writing a software rasterizer for fun and curious if anybody knows of a better way to implement a function DrawPixel( int x, int y, float r, float g, float b ) to draw a pixel to a surface of any bit depth. Right now this is my exact code: redBits = bits of red in a pixel greenBits = ... blueBits = ...

void GraphicsEngine::DrawPoint( int x, int y, float red, float green, float blue)
	if( red   >= 1.0 )
		red   = 0.9999999;

	if( blue  >= 1.0 )
		blue  = 0.9999999;
	if( green >= 1.0 )
		green = 0.9999999;

	unsigned char r;
	unsigned char b;
	unsigned char g;

	r = (1<<redBits  ) * red;
	g = (1<<greenBits) * green;
	b = (1<<blueBits ) * blue;
	unsigned long final = b + (g << blueBits) + (r << (blueBits + greenBits));

	if( !bufferOpen )
	switch( totalBits )
		case 32:
		case 24:
				unsigned long* temp = reinterpret_cast< unsigned long*   >(backBufferData);
				temp[ y * (pitch+width) + x  ] = final;

		case 16:
				unsigned short* temp = reinterpret_cast< unsigned short* >(backBufferData);
				temp[ y * (pitch+width) + x  ] = (unsigned short)final;
			PostError("DrawPoint does not support your current video bitrate.\n");

I''m positive I''m making some silly mistakes. I''m not completely concerned about optimization since I would not use this function extensively, but there has got to be a way to get some major speed ups..

Share this post

Link to post
Share on other sites
First of all, here''s what you are doing wrong:

- clamping RGB values per pixel. This should not be done in the pixel plotter if you can at all avoid it.
- locking backbuffer per pixel. OUCH, this is very painful. Lock it per frame instead, and batch-write your pixels.
- reinterpret casting. This isn''t evil or terribly slow per se (Afaik) but it isn''t needed at all. Work with char pointers whenever dealing with memory, it will save you lots of casting.
- switch statement. Conditional jumps ain''t fast, especially when doing them a million times per frame just to plot pixels. Go for function pointers, or write an abstract Render class with different implementations for each bitdepth, and select the proper implementation at run-time. See the excellent book Design Patterns for more info on how to pull that off smoothly.

In my engine I use a set of functions called Plot32, Plot24, Plot16, and Plot15. I then have a generic Plot function pointer which points to the correct function when the video bit depth is found from DirectX. In my engine loop I just call the correct plot function. Here''s relevant code from Plot32:

*(Ptr_Char+offset++)=(unsigned char)(color_b*255);
*(Ptr_Char+offset++)=(unsigned char)(color_g*255);
*(Ptr_Char+offset)=(unsigned char)(color_r*255);

Essentially Ptr_Char and offset are evil global variables, which are used because I''m lazy, and nobody playing the game will ever know, so I don''t care Ptr_Char is the address of a system-memory backbuffer. I allocate it via Ptr_Char = new unsigned char[size of video buffer]; and per-frame copy it onto a directdraw surface using memcpy. There''s probably much better ways of doing this, but it works for what I need and is fairly fast.

Plot24 is just like Plot32 except you increase offset by 1 at the end rather than by 2. If you want you can modify Plot32 for using alpha channels. Plot16 is also simple:

*(Ptr_Word+offset)=(unsigned short)(color.r*31);
*(Ptr_Word+offset)+=(unsigned short)(color.g*63);
*(Ptr_Word+offset)+=(unsigned short)(color.b*31);

And 15 is identical, but replace the 63 with 31.

offset is calculated as (width * y + x) * bytes per pixel. However, in my engine, I render pixels in a continuous rectangle (left to right, top to bottom) so I don''t need to calculate offset per pixel. However, if your pixels aren''t coherent like that, you''ll have to do the calculation per pixel.

Hope that helps.

Share this post

Link to post
Share on other sites
I don''t think a pixel plotter for a software renderer is a good idea...
you should code your pixel plotting inside the fnctions that use it, like inside a textured scanline tracer, that way you can avoid lots of unecessary multiplications.
and floating point for RGB values isn''t really good in a per-pixel point of view...
if you plan to use the FPU pipelines to your advantage, try using them to compute the pixel offsets for a perspective correct scanline texture tracer rather than to compute your RGB values.

also, if your texture is 32 bits and your color depth is also 32 bits, you don''t need to split anything, and you can use an unsigned int * pointer to access the texture and your buffer, rather than an unsigned char *, the same thing goes with 16 bpp and unsigned shorts.

and if you want to optimise your code, use a profiler, it will be *very* helpful

Share this post

Link to post
Share on other sites
Thanks alot for the useful feedback. As far as optimizations, it was mostly academic. I would not use the function (or any function) for real time per pixel effects.

Apoch: I don''t lock the backbuffer every time I draw a pixel, just if its not already locked. I''m designing my graphics system to be sort of a FSM so the update loop takes care of everything like unlocking the buffer, etc.. The functions just have to make sure its locked before doing anything. I really like the idea of writing a Render interface and implementing it with each bit depth, and using the correct implementation at run time. Great idea!!

sBiBi: I like the flexibility floating point offers for plotting in variable bit depths. It helps me make sure my colors look similiar in 16, 32 or even 256 bit color. Also not really trying to optimize all my code right now. I just found designing a random bitrate pixel plotting function fun, so wanted to learn some of the better ways to do it!

Share this post

Link to post
Share on other sites

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!