Advertisement

DirectDraw Transparency

Started by July 12, 2004 11:27 PM
10 comments, last by FenixRoA 20 years, 2 months ago
Ok... I have searched a found ALOT of posts on this subject and every single one has something wrong with it. Currently I'm not interested in making it work on all computers, right now i'll be happy to make it work on my computer. That said, if you need any specific specs of my computer PLZ ask. ATI Radeon 8500LE (newest drivers) Windows XP SP1 (+ all applicable updates) YES I am using VB .net, and I know how evil that is to some of you people, but I can really use some help. YES I already know that DirectDraw does NOT do Translucency in any conventional manner, but I do not want translucency. I want transparency. Here is what I have. Now I load a picture called "stand.bmp" which is basically a pink (thats R 255 G 0 B 255) box with a white (R 255 G 255 B 255) 'S' in it. The funny thing is for some reason it makes the 'S' transparent while leaving me with the pink. Aside from making a new fad in strangely-colored RPG maps, does anyone have ANY suggestions.


        Dim Point As Drawing.Point
        Dim Pict As DirectX.DirectDraw.Surface
        Public Sub New(ByVal x As Int32, ByVal y As Int32, ByVal nPict As Drawing.Bitmap, ByRef DDevice As DirectX.DirectDraw.Device)
            Dim Desc As New DirectX.DirectDraw.SurfaceDescription()
            Dim CK As New DirectX.DirectDraw.ColorKey()
            CK.ColorSpaceLowValue = RGB(·po·255·pc·, ·po·0·pc·, ·po·255·pc·)
            CK.ColorSpaceHighValue = RGB(·po·255·pc·, ·po·0·pc·, ·po·255·pc·)
            Desc.SurfaceCaps.VideoMemory = True
            Desc.SurfaceCaps.OffScreenPlain = True
            Desc.SourceDraw = CK
            Desc.Height = nPict.Height
            Desc.Width = nPict.Width
            Point = New Drawing.Point(x, y)
            Pict = New DirectX.DirectDraw.Surface(nPict, Desc, DDevice)
            '63519 '565
            'Pict.SetColorKey(DirectX.DirectDraw.ColorKeyFlags.SourceDraw, CK)
        End Sub

        Public Sub DrawScreen(ByVal ScrTop As Int32, ByVal ScrLeft As Int32, ByRef DXSight As DirectX.DirectDraw.Surface)
            Dim SrcRect As New Drawing.Rectangle()
            Dim DestRect As New Drawing.Rectangle()
            SrcRect.Width = Pict.SurfaceDescription.Width
            SrcRect.Height = Pict.SurfaceDescription.Height
            DestRect.Width = Pict.SurfaceDescription.Width
            DestRect.Height = Pict.SurfaceDescription.Height
            DXSight.DrawFast(DestRect.X, DestRect.Y, Pict, SrcRect, DirectX.DirectDraw.DrawFastFlags.SourceColorKey Or DirectX.DirectDraw.DrawFastFlags.Wait)
        End Sub



[Edited by - FenixRoA on July 13, 2004 9:30:23 PM]
I don't know much about the first question, but to find out more about tags, click on the faq link next to the search link above. You use brackets [] instead of the <> you used for source code. {open bracket}source{close bracket}

Chris
Chris ByersMicrosoft DirectX MVP - 2005
Advertisement
Please guys.. Anyone that can offer ANYTHING on this subject will be GREATLY appreciated. Thank you
I'm not sure what the true answer is, but I do know what works....I confronted the very same problem you have confronted, not two months ago...

The DDraw docs provide two methods to transparrent blitting. One works, and one does not. The one that doesn't it setting a universal transparent blit key...rather, it didn't EVER work for me (and I fought with it a lot). Setting a momentary key, however, always seemed to work. Try this out:

	DDCOLORKEY ddck;	memset(&ddstruct,0,sizeof(ddstruct));	ddck.dwColorSpaceLowValue = BLIT_TRANSPARENCY_COLOR;	ddck.dwColorSpaceHighValue= BLIT_TRANSPARENCY_COLOR;	DDBLTFX bltfx;	memset(&bltfx,0,sizeof(bltfx));	bltfx.dwSize = sizeof(bltfx);	bltfx.ddckSrcColorkey = ddck;	g_App.GetDDBackBuffer()->Blt(&rTargetOnBackBuffer, m_lpddsWhateverYouWantToBlitToTheBackBuffer, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &bltfx);


BLIT_TRANSPARENCY_KEY I #defined earlier as the hex value for whatever color was to be transparent (make it whatever you need). rTargetOnBackBuffer is just the rect struct that with destination coords on the backbuffer...but if you're familiar with ddraw I'm sure you'll recognize that. I'll watch this post for a bit to see if you have any further trouble or questions.
First of all, thanks for your help serratemplar.

From what I understood from your code, all I have to change is move the setcolorkey to just before I actually blt to the background layer.

It didnt work. I get the same thing. A black 'S' on a pink background as opposed to a white 'S' on a black background.

so if you or anyone else wants to give it another go, here is my modified code

        Dim Point As Drawing.Point        Dim Pict As DirectX.DirectDraw.Surface        Public Sub New(ByVal x As Int32, ByVal y As Int32, ByVal nPict As Drawing.Bitmap, ByRef DDevice As DirectX.DirectDraw.Device)            Dim Desc As New DirectX.DirectDraw.SurfaceDescription()            Desc.SurfaceCaps.VideoMemory = True            Desc.SurfaceCaps.OffScreenPlain = True            Desc.Height = nPict.Height            Desc.Width = nPict.Width            Point = New Drawing.Point(x, y)            Pict = New DirectX.DirectDraw.Surface(nPict, Desc, DDevice)            '63519 '565            'Pict.SetColorKey(DirectX.DirectDraw.ColorKeyFlags.SourceDraw, CK)        End Sub        Public Sub DrawScreen(ByVal ScrTop As Int32, ByVal ScrLeft As Int32, ByRef DXSight As DirectX.DirectDraw.Surface)            Dim SrcRect As New Drawing.Rectangle()            Dim DestRect As New Drawing.Rectangle()            Dim CK As New DirectX.DirectDraw.ColorKey()            CK.ColorSpaceLowValue = RGB(·po·255·pc·, ·po·0·pc·, ·po·255·pc·)            CK.ColorSpaceHighValue = RGB(·po·255·pc·, ·po·0·pc·, ·po·255·pc·)            SrcRect.Width = Pict.SurfaceDescription.Width            SrcRect.Height = Pict.SurfaceDescription.Height            DestRect.Width = Pict.SurfaceDescription.Width            DestRect.Height = Pict.SurfaceDescription.Height            Pict.SetColorKey(DirectX.DirectDraw.ColorKeyFlags.SourceDraw, CK)            DXSight.DrawFast(DestRect.X, DestRect.Y, Pict, SrcRect, DirectX.DirectDraw.DrawFastFlags.SourceColorKey Or DirectX.DirectDraw.DrawFastFlags.Wait)
This won't make you feel any better =) but...

"Holy crap! What language is that?!" I'm guessing it's VB, cause I've *never* seen it before, but it has a BASIC feel to it...though I haven't seen BASIC source since high school (seven...eight years?) Anyway, you may need someone else's help as my code example and experience are in C++...however, I believe the theory should still hold true across dev platforms.

That is, IDirectDraw7 has two methods of making a transparency. Use the DirectDraw Blitter's special FX structure/methods to do the transparency...don't set a universal key. In my example only the blit call has any transparency to it. DO NOT BIND THE TRANSPARENCY TO THE BACKBUFFER.

As I'm reading over that I fear it wont' help you at all, so I dug up a tut on msdn.com

<a href="http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/ddraw7/directdraw7/vbddtut_8s82.asp>Here it is.

I'm trying to skim thru it, but - like I said - my experience in VB is absolute zero, so I may as well be looking at COBOL.
Advertisement
Okay, this is making a little more sense to me.

IDirectDrawSurface7 in VB has a Blt method which you use for blitting....use the DDBLTFX struct (as I did in my example, only do it in your language =) and set the "source key" to the color you want NOT to blit with the rest of your sprite. Then pass it to the Blt method along with the flag DDBLT_SRCKEY or whatever the VB equivalent is (I'm looking).
Here's more on it.

The VB examples are below the C++ examples.
I'm spamming at this point, but I think this is the function you need. =)

DirectDrawSurface7.BltFx
WOW
you are a godsend.

I have looked through all your tuts, but then I tried a test.

Until now the color i've been using for transparency is pink (RGB (255,0,255))

However, When I tried a picture with a black background, change the transparency to black and turned the surface white, it does something weird. First of all nothing shows up except for a white screen (I changed the 's' to a pinkish color). I made a high-res timer to put a pause between page-flips and something completely strange happens.

At first when I started I made the timer time 17 milliseconds and then allow the draw loop to continue. however all I got is a white background (just before exiting tho a 'S' does appear).

Then I changed the timer to 300 milliseconds. this is the strange part.

First I see a white background (the whole screen) and the 'S' and the black is transparent (yay) BUT... after one or a few reiterations of the draw loop, the 's' changes from a pinkinsh color to a dark green....

any thoughts?

    Private Structure StaticX        Private Point As Drawing.Point        Private Pict As DirectX.DirectDraw.Surface        Public Sub New(ByVal x As Int32, ByVal y As Int32, ByVal nPict As Drawing.Bitmap, ByRef DDevice As DirectX.DirectDraw.Device)            Dim Desc As New DirectX.DirectDraw.SurfaceDescription()            Dim CK As New DirectX.DirectDraw.ColorKey()            CK.ColorSpaceLowValue = RGB(·po·0·pc·, ·po·0·pc·, ·po·0·pc·)            CK.ColorSpaceHighValue = RGB(·po·0·pc·, ·po·0·pc·, ·po·0·pc·)            Desc.SourceDraw = CK            Desc.SurfaceCaps.VideoMemory = True            Desc.SurfaceCaps.OffScreenPlain = True            Desc.Height = nPict.Height            Desc.Width = nPict.Width            Point = New Drawing.Point(x, y)            Pict = New DirectX.DirectDraw.Surface(nPict, Desc, DDevice)            '63519 '565            'Pict.SetColorKey(DirectX.DirectDraw.ColorKeyFlags.SourceDraw, CK)        End Sub        Public Sub DrawScreen(ByVal ScrTop As Int32, ByVal ScrLeft As Int32, ByRef DXSight As DirectX.DirectDraw.Surface)            Dim SrcRect As New Drawing.Rectangle()            Dim DestRect As New Drawing.Rectangle()            SrcRect.Width = Pict.SurfaceDescription.Width            SrcRect.Height = Pict.SurfaceDescription.Height            DestRect.Width = Pict.SurfaceDescription.Width            DestRect.Height = Pict.SurfaceDescription.Height            DXSight.DrawFast(DestRect.X, DestRect.Y, Pict, SrcRect, DirectX.DirectDraw.DrawFastFlags.SourceColorKey Or DirectX.DirectDraw.DrawFastFlags.Wait)        End Sub    End Structure    Public Sub GLoop()        Dim Test As New StaticX(·po·0·pc·, ·po·0·pc·, New Drawing.Bitmap(Windows.Forms.Application.StartupPath + "stand.bmp"), DDevice)        Dim TestTim As New OnTimer(·po·300·pc·)        TestTim.Active = True        BackSurf.FillColor = Drawing.Color.White        Do Until DInp.GetCurrentKeyboardState.Item(DirectX.DirectInput.Key.Escape)            If TestTim.Tick Then                Test.DrawScreen(·po·0·pc·, ·po·0·pc·, BackSurf)                ForeSurf.Flip(BackSurf, DirectX.DirectDraw.FlipFlags.Wait)                BackSurf.DrawBox(·po·0·pc·, ·po·0·pc·, ·po·800·pc·, ·po·600·pc·)            End If        Loop    End Sub


O and YES... i forgot to mention... This IS in VB .Net 2003. sry.

This topic is closed to new replies.

Advertisement