Drawing realtime graphics using wxDC

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
RP__
Earned some good credits
Earned some good credits
Posts: 124
Joined: Tue Jan 20, 2015 5:53 pm

Drawing realtime graphics using wxDC

Post by RP__ »

Hi guys,

This topic starts off more as an inquiry topic.
If it turns out that what I want is not doable using wxDC, it'll be a short topic.
If I can do what I want with wxDC, I think this will become quite a large topic.

So, for quite some time now I have been working on a map editor for a 2D game called "Command and Conquer: Tiberian Sun" or "Command and Conquer: Red Alert 2".
Now I have come to the part where I need rendering on screen.
I'm curious how far I will get using wxWidgets for blitting all graphicsto the screen.
Will I be able to get something like this on the screen using wxWidgets? I know that for voxels I will have to use OpenGL, but eventually all will be bitmaps.

Image
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Drawing realtime graphics using wxDC

Post by doublemax »

Drawing bitmaps to the screen should be pretty fast, there is not much overhead created by wxWidgets. If it will be fast enough for you is hard to tell, just write a small benchmark that draws a few thousand bitmaps on screen.

In any case, you should also try wxGraphicsContext instead of wxDC, it's possible that on some platforms wxGCDC is faster. At least under Windows using wxDirect2dGraphicsContext should be fast as it uses DirectX internally, unfortunately it's still a little unstable.

If we're lucky, we'll find a student for this GSoC idea:
http://wxwidgets.org/gsoc/projects/#ope ... cs-context

This would solve all speed-problems related to 2D drawing on all platforms.

Then again, if you only need to draw bitmaps, it should be easy to do it in OpenGL anyway.
Use the source, Luke!
RP__
Earned some good credits
Earned some good credits
Posts: 124
Joined: Tue Jan 20, 2015 5:53 pm

Re: Drawing realtime graphics using wxDC

Post by RP__ »

In the end, everything is a bitmap that gets blitted to the screen.

In due time I will not only have to work with bitmaps, but also voxels.
Though it would be possible to map it to a bitmap as they are 8 static facings.

The reason I'm inquiring about wxWidgets drawing functionalities is because I don't want to make it overcomplex.

Weren't there rendering components in wxWidgets for OpenGL already?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Drawing realtime graphics using wxDC

Post by doublemax »

In due time I will not only have to work with bitmaps, but also voxels.
If that means you'll be blitting thousands of small bitmaps on screen, i have a feeling that won't be fast enough. I'd go for OpenGL right away.
Use the source, Luke!
RP__
Earned some good credits
Earned some good credits
Posts: 124
Joined: Tue Jan 20, 2015 5:53 pm

Re: Drawing realtime graphics using wxDC

Post by RP__ »

For voxels I will have to use OpenGL to render them and what I intend to do then is to sort of take pictures from certain facings of the rendered voxel and create a bitmap out of those.
So lets say a tank existing of voxels will become a 2D representation. Only 8 facings are used.
Basically I convert the voxel unit to a bitmap as there is no need for 3D stuff to happen.
The map editor is a static representation.

Notice the green car in the screenshot? That's a voxel. And it has the facing to the north.
What I intend is to create some sort of a picture of when it is facing north, that will be stored as a bitmap. The entire car will become 1 bitmap.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Drawing realtime graphics using wxDC

Post by doublemax »

I made a little benchmark with standard wxDC functions under Windows.

frame, client size 1024x768
in a paint event with static buffer bitmap i first drew a 1024x768 background bitmap and then 3072x a 16x16 bitmap with transparency.

That took around 22ms per iteration on my system (i5 3.5Ghz, GTX 1060), almost 50 fps.

That should give you a general idea about what to expect.
Use the source, Luke!
RP__
Earned some good credits
Earned some good credits
Posts: 124
Joined: Tue Jan 20, 2015 5:53 pm

Re: Drawing realtime graphics using wxDC

Post by RP__ »

That sound quite alright.
Could you share that code with me?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Drawing realtime graphics using wxDC

Post by doublemax »

Here you go. Based on the "minimal" sample. You need to replace the two hard-coded image paths with fitting images.
Attachments
minimal.cpp
simple wxdc bitmap benchmark
(8.52 KiB) Downloaded 330 times
Use the source, Luke!
RP__
Earned some good credits
Earned some good credits
Posts: 124
Joined: Tue Jan 20, 2015 5:53 pm

Re: Drawing realtime graphics using wxDC

Post by RP__ »

Great!
I read that I could also use a timer to let it draw on screen in intervals.
I capped it at 25fps.

Am I to assume that creating bitmaps from raw rgb(a) bytes, like a big array of 3 or 4 bytes consisting of the color data is through wxImage?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Drawing realtime graphics using wxDC

Post by doublemax »

I read that I could also use a timer to let it draw on screen in intervals. I capped it at 25fps.
Yes, you can do that if you are 100% sure that your drawing will be fast enough. Because if it isn't, timer events will stack up and your program will become unresponsive.
Am I to assume that creating bitmaps from raw rgb(a) bytes, like a big array of 3 or 4 bytes consisting of the color data is through wxImage?
That's the easiest way to do it. Another option is to use raw bitmap access:
http://docs.wxwidgets.org/trunk/classwx_pixel_data.html
Use the source, Luke!
RP__
Earned some good credits
Earned some good credits
Posts: 124
Joined: Tue Jan 20, 2015 5:53 pm

Re: Drawing realtime graphics using wxDC

Post by RP__ »

Okay, I have implemented the raw pixel access and want to use Alpha to show pixels or not.
It seems that the Alpha setting is not working as intended for me. It does not matter what Alpha value I use, the pixel never gets hidden.

Code: Select all

	wxBitmap bmp(width, height, 32);
	wxAlphaPixelData data(bmp, wxRect(wxSize(width, height)));
	wxAlphaPixelData::Iterator p(data);
	unsigned int index = 0;
	p.Offset(data, 0, 0);
	for (int y = 0; y < height; ++y)
	{
		wxAlphaPixelData::Iterator rowStart = p;
		for (int x = 0; x < width; ++x, ++p)
		{
			auto& entry = pal->colors[paletteIndices[index]];
			p.Red() = entry.red;
			p.Green() = entry.green;
			p.Blue() = entry.blue;
			if (paletteIndices[index] == 0)
				p.Alpha() = 0;
			else
				p.Alpha() = 255;
			index++;
		}
		p = rowStart;
		p.OffsetY(data, 1);
	}
		
This is what the tile looks like without any hiding of pixels:
Image

All blue pixels (paletteIndices[index] == 0 has these RGB values) should not be visible on screen.
That's how the tiles connect.

I have also tested using what is in the sample (samples/image):

Code: Select all

	auto& entry = pal->colors[paletteIndices[index]];
	unsigned char alpha = paletteIndices[index] == 0 ? wxALPHA_TRANSPARENT : wxALPHA_OPAQUE;
	p.Red() = entry.red * alpha / 256;
	p.Green() = entry.green * alpha / 256;
	p.Blue() = entry.blue * alpha / 256;
	p.Alpha() = alpha;
This also does not work as what should be gone, is rendered black.

I'll check how everything performs, I can always switch to event based rendering instead of timers.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Drawing realtime graphics using wxDC

Post by doublemax »

The second version is the correct one, RGB values must be pre-multiplied with alpha.

BTW: Which platform and wxWidgets version are you using? Over the last few months there have been several fixes regarding the handling of bitmaps with alpha under Windows.

Can you test with the "toucan.png" from the "image" sample? That should draw correctly with alpha.
Use the source, Luke!
RP__
Earned some good credits
Earned some good credits
Posts: 124
Joined: Tue Jan 20, 2015 5:53 pm

Re: Drawing realtime graphics using wxDC

Post by RP__ »

I am running on Windows 10 using wxWidgets 3.1.0.

It's very odd. I took the PNG from the sample you pointed me to, renamed it to sprite16.png.
When I do this, it works, but still renders the actual tile (but does work with alpha):

Code: Select all

wxBitmap bmp(width, height, 32);
bmp.LoadFile("d:\\sprite16.png", wxBITMAP_TYPE_PNG);

bmp.SetWidth(width);
bmp.SetHeight(height);

wxAlphaPixelData data(bmp);
wxAlphaPixelData::Iterator p(data);
unsigned int index = 0;
p.Offset(data, 0, 0);
for (int y = 0; y < height; ++y)
{
	wxAlphaPixelData::Iterator rowStart = p;
	for (int x = 0; x < width; ++x, ++p)
	{
		auto& entry = pal->colors[paletteIndices[index]];
		unsigned char alpha = paletteIndices[index] == 0 ? wxALPHA_TRANSPARENT : wxALPHA_OPAQUE;
		p.Red() = entry.red * alpha / 256;
		p.Green() = entry.green * alpha / 256;
		p.Blue() = entry.blue * alpha / 256;
		p.Alpha() = alpha;
		index++;
	}
	p = rowStart;
	p.OffsetY(data, 1);
}
But when I remove the line to load the PNG, it shows full square of the tile, including what I don't want to get rendered.
It seems that some part of the PNG loading activates something inside which makes it work with alpha?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Drawing realtime graphics using wxDC

Post by doublemax »

I am running on Windows 10 using wxWidgets 3.1.0
Can you try again with the latest version from GIT?
It seems that some part of the PNG loading activates something inside which makes it work with alpha?
It's probably related to whether the bitmap is a DIB or DDB internally. (Device dependent/independent bitmap).

Check the value of m_bitmap->IsDIB() for both cases.
Use the source, Luke!
RP__
Earned some good credits
Earned some good credits
Posts: 124
Joined: Tue Jan 20, 2015 5:53 pm

Re: Drawing realtime graphics using wxDC

Post by RP__ »

Calling IsDIB for both the PNG and non-PNG bitmap result in true.

I have used the wxWidgets version from GitHub: results are the same as my local wxWidgets version.
Post Reply