Managed DirectX and Alpha Textures

Started by
8 comments, last by Promit 15 years ago
Hi! I'm using csharp with Managed DirectX: Bitmap bitmap = new Bitmap(500, 200); Texture texture = Texture.FromBitmap(device, bitmap, 0, Pool.Managed); Graphics g = texture.GetSurfaceLevel(0).GetGraphics(); g.DrawString("Hello", font, brush, rect, StringFormat.GenericTypographic); When doing it like above, I get a texture without transparent background. But ofcourse Texture.FromBitmap is slow (with or without debugger). When I do it like this: Texture texture = new Texture(device, 500, 200, 0, 0, Format.X8R8G8B8, Pool.Managed); Now it is very quick, but the texture has a black background, how can I remove this background, or get a texture like the one made by Texture.FromBitmap.
Advertisement
Good found the difference...


Texture texture = new Texture(device, 500, 200, 0, 0, Format.X8R8G8B8, Pool.Managed);


vs


Texture texture = new Texture(device, 500, 200, 0, 0, Format.A8R8G8B8, Pool.Managed);


The only problem is that Format.A8R8G8B8 gives an InvalidCallException when I request a GetSurfaceLevel(0).GetGraphics() on it (at least sometimes...).

How can I get a texture on which I can draw with alpha-colors?

The GetGraphics method invokes the IDirect3DSurface9::GetDC() function. The documentation of this function says:
Quote:IDirect3DSurface9::GetDC is valid on the following formats only: D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, D3DFMT_R8G8B8, and D3DFMT_X8R8G8B8. Formats that contain Alpha are not supported because the GDI implementations don't have a well-defined behavior on the alpha channel.


Personally I would question why you're attempting to do this, as it's pretty silly when you have stuff like Font and render to texture and all.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
P.S. MDX is dead. Look into XNA or SlimDX.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Quote:Original post by Promit
The GetGraphics method invokes the IDirect3DSurface9::GetDC() function. The documentation of this function says:
Quote:IDirect3DSurface9::GetDC is valid on the following formats only: D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, D3DFMT_R8G8B8, and D3DFMT_X8R8G8B8. Formats that contain Alpha are not supported because the GDI implementations don't have a well-defined behavior on the alpha channel.


Personally I would question why you're attempting to do this, as it's pretty silly when you have stuff like Font and render to texture and all.


Well the interesting thing is, that I can create a Bitmap in csharp gdi+, have it use alpha color (eg. Color.FromArgb(128, 255, 0, 0) ). Draw my picture like I want too, and have it converted to a texture. This is nice, but also slow.

Doing it the other way, creating a texture, and using a graphics object to draw on it, is very easy and very fast. Only it doesn't really work they same way.

Interesting is that Texture.FromBitmap creates a texture with A8R8G8B8, which like you say doesn't work 100% with GetDC.

But when creating a X8R8G8B8 Format Texture, works with GetDC, but you can't use alpha colors any more...

What do you mean with font -> Direct3DX.Font ? Because the GDI font is much more powerfull and easier to use. What do you mean by render to texture?
Quote:Original post by Promit
P.S. MDX is dead. Look into XNA or SlimDX.


My options are a little more limited than that. I'm using DirectShow for displaying FullHD videos with animations in front of it.

XNA uses just like WPF something new, which doesn't work in Windows XP. Playing FullHD videos in XP or in Vista with WPF looks terrible also (it doesn't use the vsync). They told me Windows 7 was better, but can't use that in real life yet...

Writing it in C# is a lot more fun than writing it in C++, because you can concentrate better on the logic of your program first...

SlimDX is a possibility, but does it solve my problem? Probably not...

If I had to hazard a guess, I would say that the C# version uses GDI+, which is able to handle alpha in a sane way, but Direct3D is not GDI+ aware and GDI does not handle alpha in a sane way. At least that's what it sounds like from skimming the various docs involved.

I'm curious what functionality GDI fonts have that you don't get with D3DX's Font?
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Quote:Original post by Promit
If I had to hazard a guess, I would say that the C# version uses GDI+, which is able to handle alpha in a sane way, but Direct3D is not GDI+ aware and GDI does not handle alpha in a sane way. At least that's what it sounds like from skimming the various docs involved.

I'm curious what functionality GDI fonts have that you don't get with D3DX's Font?


Interesting didn't think about GDI+ and alpha in that way...

I tried to use D3DX's Font on a texture, it was a little more complex didn't work directly. I could write them directly to the screen, but don't wish to do that 60x a second for the same text. Somehow the fonts looked bigger too.

And with GDI fonts I have a little more freedom, don't need to know the font in advance, the text looks a little better (anti-aliasing anyone?) I also have shapes with borders around them, which are easier done in gdi+ than with DrawPrimitive... (as far as I know...)


Quote:Original post by Promit
If I had to hazard a guess, I would say that the C# version uses GDI+, which is able to handle alpha in a sane way, but Direct3D is not GDI+ aware and GDI does not handle alpha in a sane way. At least that's what it sounds like from skimming the various docs involved.


I found some solution around the GetDC problem:

https://forums.microsoft.com/msdn/ShowPost.aspx?PostID=1086855&SiteID=1&pageid=0

It goes like this:

- first create texture with Format.A8R8G8B8
- second get GraphicsStream and put it in a bitmap:


Texture texture = new Texture(device, s.Width, s.Height, 0, 0, Format.A8R8G8B8, Pool.Managed);
GraphicsStream gs = texture.LockRectangle(0, LockFlags.None);
Bitmap bmp = new Bitmap(s.Width, s.Height, s.Width * 4, PixelFormat.Format32bppPArgb, gs.InternalData);
Graphics g = Graphics.FromImage(bmp);

g.Clear(Color.FromArgb(128,255,0,0));

g.Dispose();
g = null;

texture.UnlockRectangle(0);
bmp.Dispose();
bmp = null;


It works the sameway as first creating a Bitmap in .NET and filling it with an alpha color, and doing a Texture.FromBitmap. But it is much faster...

The only problem is when using DirectX Debug Libraries, you get the message of not support those not RGB modes, which further seem to work fine...
Clever trick. Good thing I remembered to expose the internal pointer of a locked stream in SlimDX. I imagine it's still fairly slow, being software rendered and all, but probably not bad if you're just drawing a few things to a single overlay texture.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

This topic is closed to new replies.

Advertisement