Skip to main content
GameDev.net gamedev.net
🔒 Locked

DirectDraw Transparency

Started by FenixRoA Jul 12, 2004 at 11:27 PM 10 replies 2.5k views
Original Post
FenixRoA
FenixRoA
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]
Supernat02
Supernat02
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
FenixRoA
FenixRoA
Please guys.. Anyone that can offer ANYTHING on this subject will be GREATLY appreciated. Thank you
serratemplar
serratemplar
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.
FenixRoA
FenixRoA
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)
serratemplar
serratemplar
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.
serratemplar
serratemplar
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).
FenixRoA
FenixRoA
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.
serratemplar
serratemplar
Again, I don't know VB but, I'll hazard a few guesses.

In what appears to be your primary rendering loop, when the timer goes off you do this...

            If TestTim.Tick Then                Test.DrawScreen(0, 0, BackSurf)                ForeSurf.Flip(BackSurf, DirectX.DirectDraw.FlipFlags.Wait)                BackSurf.DrawBox(0, 0, 800, 600)            End If


To be honest, I'm not entirely sure what "Test.DrawScreen" could be doing, but the last two lines give me the impression that you're flipping pages and then drawing to the back page. If that's the case, I recommend that the page flip is the very last thing you do, and that you always render to the backpage, never to the front page.

That the colors are botching up could mean a number of things, sadly, and that I don't know VB nor what the rest of your graphics calls look like, I fear I could guess and guess and never get it right. I'm sorry for this, because I really do understand how frustrating this problem with transparencies and DDraw can be.

Anyway, it sounds like you're on the right track, since you can see that the sprite is blitting correctly at least at first. My recommendation to you would be to keep up with the sort of debugging that you're doing. Instead of a timer, maybe require a keypress at each stage. I recommend putting a log file into play (open a textfile when your program starts and write to it whatever it's doing so you can maybe catch where it's botching up...this method saves me time and time again).

In any event, you are close and I bet you can feel it. =) Maybe someone else will pick up where I can't answer, but if not, I have a feeling you'll get this one. Good luck to you.

(Sorry about the long delay...had to watch some Cowboy Bebop.)
FenixRoA
FenixRoA
Still stuck
Any ideas at all would be useful

Again Serratemplar, thank you for helping me this far.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.