GDI With DirectX - Fastest Alternative

Started by
8 comments, last by remigius 15 years, 2 months ago
Hi I'm trying to find the fastest alternative to solve a GDI problem with DirectX. We have methods that work but I'm trying to find the fastest alternative. So I will start with the method that works for us right now. 1) We're using an OLE object so we are rendering to a Bitmap using OLEDraw 2) We then copy this bitmap to a DirectX Managed surface and render a quad to the D3D screen. 3) The application we're using(Flash) has the following issues though that we need to be aware of to handle transparency. Transparency is done using a color key with this object so when we copy to our DX surface we need to do the color key check. So that is what we're doing which is OK speed what I want to do is this: I want to find a way we can just use OLEDraw to a DX9 Managed Texture and then find a way to Render using a Color Key. I believe this will be the fastest method if I can find a way to use Multipass texture stages to do this. I have been unable to think of a method so far, where I could get the Alpha Channel to handle transparency. The biggest issue I'm running into is the fact that you must use a X8R8G8B8 format if you want to call GetDC on a Dx9 surface. So I'm trying to think of a way I could use a Color Key Texture as 1 texture stage and the OLE Texture as my other texture stage to come up with a way to render transparency correctly. Does anyone have any ideas on a method to do this. Thanks, Keith
Advertisement
Are shaders an option? If they are this would be a piece of cake. I don't think there's a way to do with texture stages, but the fixed-function stuff is before my time so I'm not too familiar with it.
So you question basically boils down to, "How do I configure the D3D9 texture stages of the fixed-function pipeline to render a specified color as transparent?"

If that's the case, I think I can help you, but before I spend time testing my theory, I need to know if this is truly what you're trying to do.

Shaders are not an option. And Yes the question boils down to "How do I configure the D3D9 texture stages of the fixed-function pipeline to render a specified color as transparent"

Thanks for any help you can provide. I'm still stumped on this one.

Keith
> We then copy this bitmap to a DirectX Managed surface and render a quad to the D3D screen.

when you're doing this copy, check for the color key and if it matches current texel, set that texel alpha to zero.

You may also want to set the color of that texel to zero (configured as a "premultiplied alpha") to prevent weird color bleeding when rendering.

LeGreg
I can think of a parial solution:

The only texture stage op mentioned in the docs which can convert colour to alpha in some way is D3DTOP_DOTPRODUCT3.

A solution would therefore look something like this:

Stage 0:
Colour op: Subtract colour key in texture factor from colour of surface
Alpha op: Doesn't matter

Stage 1:
Colour op: I think this needs to be DP3 because of the alpha op (if not, can move stage 2 colour op here and drop stage 2)
Alpha op: DP3(current, current).

Stage 2:
Colour op: Surface colour (using D3DTSS_TEXCOORDINDEX 0)
Alpha op: Current (prev stage)

Enable alpha testing to draw all pixels with alpha != 0.

This isn't perfect because the subtraction might clap to 0, in which case you'd need to subtract in both directions, add the results, and then do the DP3. This will only work on cards that support pixel shaders, which might or might not be a problem for you, depending on why you can't use them. (If it's the limitation of the hardware, then that won't be good, if it's just an API issue, but the hardware is advanced, then it should work).

I don't know if the above solution will work exactly as described, but it should be close enough that playing with it will get you a working solution.

I'm not familiar with the limitations of OLEDraw, but it might be worth investigating if you can render the Flash control while preserving alpha (kinda like a windowless Flash control on a webpage). If you can get the control to render to a 32bpp bitmap and get that onto the surface with a usable alpha channel, you could use standard alpha blending to render it to the screen.

A quick google turned up this C++ sample which at first glance seems to succeed at creating a transparent Flash control at least. Good luck with it at any rate!
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
What I came up with was similar to ET3D's solution. Use DOTPRODUCT3 to set the alpha channel to zero, based on the color values. You'd need to shift each texel by an offset based on the color key prior to performing the dot product operation, so that the dot product of the texel with itself is zero. I used ADDSIGNED for this, but there are probably other ways to do it.

I have code that does all of this and it does work, the problem is a lack of precision which causes colors that are close to the color key to also become transparent. As an example, if I used 0x00f800 (97% green) as the color key, any color from 0x00f100 to 0x00ff00 ended up with an alpha value of zero. This is because the dot product of that range produces values that are less than 1/255, and are assigned a value of zero once the colors have been scaled back to the range [0,255]. Another problem is that there are probably combinations of color components that will result in a dot product (and a resulting alpha value) of zero, even though they are nowhere near the colorkey's color.

BTW, if you use DOTPRODUCT3 as a color op, it will copy the result to all color channels as well as the alpha channel. The alpha op in the stage will be ignored. There's also an offset involved so that negative values can be expressed. I had to look at the source of the reference rasterizer in order to find out how this texture op actually works.

If you're not going to do this with shaders, then you may want to spend your time making that texture load routine as fast as possible and just search for the color key and set the alpha accordingly. There's a D3DX routine that does this, but you might be able to do something using SSE that would be faster. If you have to do this every frame, double-buffering the texture might provide a speed-up since you aren't trying to write to the texture while it's in use by the GPU.
Hi You mentioned using a bitmap to render to using the Alpha. The problem with that is Text. This is what we've been doing but the issue is with Text. For some reason Flash Text always has 0x00 for the Alpha channel in the bitmap. So we currently need to convert that value's Alpha if the color is not the color key when we copy over to our DirectX surface.

Keith

Quote:Original post by glavian999
... The problem with that is Text. This is what we've been doing but the issue is with Text. For some reason Flash Text always has 0x00 for the Alpha channel in the bitmap...


It might be wildly optimistic, but is it pointless to investigate this Flash bug (sounds like a Flash bug at any rate)? In the topic I linked to above, I saw some notes that Flash Player 8 regularly corrupts its alpha channel, so it just might work out to try another Flash player version and/or check out some Flash/Adobe resources on this issue.

Obviously I don't know if it can be fixed in the first place or if it'd be worth investigating, but I'd imagine a proper alpha channel beats color-key transparency and it'd even be easier & faster to render to boot.
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

This topic is closed to new replies.

Advertisement