Pink Edges / Alpha Channels

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Pink Edges / Alpha Channels

      Hello again!

      I've created some BMP images with the ugly pink colour used for transparency. Some of the images with effects like drop shadows don't blend well into the game, leaving bits of pink in them around the edges. I understand what's going on here and have been reading up using an alpha channel to fix this (p. 174). I like the idea of storing it as a separate image.

      My question is what does an alpha channel look like? I understand it's kind of like a mask that fits over the drawable regions of your image, right?

      Does anyone have an example they could post, preferably one that could be adapted to resolve my drop shadow effect problem?

      Thanks in advance,
      -Carse.
    • Wow, it looks like things are really coming along for you!

      Just know that alpha blitting is really slow in DirectDraw and there is no hardware support of ralpha blitting... so you will want to do this as little as possible if performance is a priority.

      In code, you really only need R,G, or B of that alpha image to obtain the correct level of alpha for the real image, so it might be easiest to just have the alpha image look like a grayscale image, even though you really only need about one third of the color values the grayscale image will give you. In other words, I would use the B value of the alpha image as the A value to apply to the real image versus the background.

      Example: say you want your image to be a solid circle with edges that become more translucent as you get farther from the center until the circle is inivisble at the outermost edges.

      The alpha image for that circle, depending on how you code your custom mask blitting function, can look solid black in the center with the edges getting lighter and lighter until the outermost edges are pure white.... or you can go for a solid white in the center with the edges getting darker and darker until the outermost edges are pure black.

      I'm not quite sure how artists create these alpha images, but there might be some tool in photoshop or something that allows artists to save out the alpha channel as a grayscale image. I wish I knew how they did this.
    • Originally posted by Kain
      I'm not quite sure how artists create these alpha images, but there might be some tool in photoshop or something that allows artists to save out the alpha channel as a grayscale image. I wish I knew how they did this.


      There is and it's piss easy to do. Just hold down Ctrl while you click on the layer that contains the image with the alpha blend. Under the "Windows" menu you should find an option to make the Channels window visible. In the Channels window you will find a buttons at the bottom. If you hover over each of them you will find one that says use selection or something like that, clicking on that will create your black and white alfa channel for you. Make the rest of the channels invisible and then save the channel as a gif or whatever format you are using.

      There are many ways to accomplish this sort of thing but it's been so long since I have used Photoshop for anything complex so I forget. Also this sort of thing also exists in other imaging packages, so you don't need Photoshop. If your looking for a free alternative you should check out The Gimp, which btw has a Windows port.
    • Nice, thanks, that's pretty easy. Now if I understand correctly, all I have to do is rewrite the Sprite class to work with an Alpha surface by loading my 8-bit greyscale alpha channel BMP into it and making a call to CopyAlpha instead of Copy. Right?

      Thanks, as always, for the incredible help!
      -Carse.
    • If performance becomes an issue for you, then you should keep your original Sprite Copy around just in case. It is nice and fast. CopyAlpha has no hardware acceleration, and so it will be a slow and expensive process... best suited for sprites that do not have to be rendered every frame, like static sprites that blend with the background.

      But for your sprites that move around a lot or sprites that stand still and have other sprites moving around under them, you'll want to just do the fastblt.

      This really only applies to you if you care about the people that don't have the latest and greatest machines.

      Go ahead and try the CopyAlpha method on all sprites if you don't care about lower end machines, but keep your original method around as you may end up needing to use that, still.

      The post was edited 1 time, last by Kain ().

    • Hmm.. I'll definitely need to do some optimization. I've been loading everything from BMPs into BMPSprites to make it easier on me. I knew this would come back to haunt me, as static things like Buttons are objects that don't need to be rendered every frame. I suppose I could just make an m_NeedsUpdate flag and check it in the VDraw method to determine if it gets redrawn.

      In terms of CopyAlpha, I added an m_AlphaSurface to the Sprite class and check it in Sprite::VDraw like so:

      Source Code

      1. if (m_pAlphaSurface)
      2. hr = CopyAlpha(...)
      3. else
      4. hr = Copy(...)
      5. ...


      That way, the Sprite will only use the alpha surface if it needs one.

      The post was edited 1 time, last by Carse ().

    • That code looks really familiar! You've got the hang of it. That is exactly what I did when I was faced with the same problem. If I could write that code again, though... I would have done things differently.

      I would have made two separate sprite classes, one class would do the alpha mask thing and the other class would do the fastblt thing.

      That way, you don't need to have that extra if-else evaluation on 'm_pAlphaSurface' every time the sprite's virtual draw function gets called... also, memory usage would be slightly more efficient because the regular sprite class would not have a wasted m_pAlphaSurface member taking up 32 bits of memory per instantiated sprite.

      But you could go on forever coming up with ways to just make your code better and better to the point where you never get anything done, so you should probably ignore this post. I am beginning to babble.
    • Babbling? No way! "This is gold, Jerry, gold!!" (seinfeld) lol

      I do understand your point though and that has been a problem for me, stressing so much about the design that I actually end up changing it so much I never get any coding done. On the other hand though, you need to select a good design, because as I'm now finding, adding existing functionality after-the-fact to an architecture complicates it immensely. For example, the consequences of modifying the Sprite class also affect all of it's derived classes, and these can be many since Sprite is higher up in the food-chain. Anyway, now I'm babbling!

      Man, when I'm done this will be the most robust and elegantly designed Tic-Tac-Toe game ever done, hehe. And better yet, I'll be able to use that work as a launchpad for my next project, which is 75% through the design phase.
    • Tic Tac Toe Extreme!!!!!!!!!!

      Matthew Lamari (ex-Retro Studios and the person who instilled the seeds of thought for smart pointers and beyond, even though I was kicking and screaming at first) once told me that a class heirarchy should be broad and flat as opposed to thin and long.

      He was very much in favor of not wasting member variables in a base class that do not get used in all of the derived classes.

      INITIATE BABBLING SEQUENCE 01093728428...

      This made me question him about what to do when you end up having duplicate code all over the place as a result since a lot of Sprites draw the same way and if the sprites are not sharing a common base class, then how can I avoid copying and pasting draw duplicate draw code in different places? It was there that he pointed out the bridge pattern. Lamari was also the person who introduced "Design Patterns" to me. My head almost asploded; I was still very much a raw pointer, do what works kind of coder at the time. The bridge pattern is when you encapsulate an action into an object instead of making that action a function of the class that performs the action.

      For example, your sprites have a Draw function, but some use CopyAlpha, some might render a 3D model onto a 2D surface, and some just do good ole simple fastblt. I think this might be a bad example because if you only have one of each type of Sprite class (3 total), then you're good as it is. But let's just say that you're crazy and you've got 10 Sprite classes that use fastblt and 20 that use CopyAlpha and 30 that use 3DRender. And your class heirarchy is flat so that you have 10+20+30 = 60 total sprite classes that inherit from a common base class (ISprite).

      In this class, you create a new class called IDrawer. IDrawer will have three classes deriving from it. BltDrawer, AlphaDrawer, and 3DDrawer. Each drawer has a unique draw function (it doesn't have to be virtual, and it can even be a static function) that takes the right number of parameters and knows how to do its thing. Your 10 fastblt sprite classes will use BltDrawer:: Draw to do its thing; your 20 CopyAlpha sprite classes will use AlphaDrawer:: Draw to do its thing, and your 30 3D sprite classes will use 3DDrawer:: Draw to render.

      Looking back, I guess you don't even need a base IDrawer class in this case as I don't see a need for members in your Drawers.

      This is the bridge pattern, and it is really hard to wrap my head around this. You basically use this design pattern when you find yourself copying and pasting duplicate code in various places.

      ... END BABBLING SEQUENCE 01093728428

      The post was edited 1 time, last by Kain ().

    • Frick'n whoa! If that is food for thought then I'm at an all you can eat buffet! Good thing I brought my bib and a mean appetite!

      It would seem that by the time I actually finish Tic-Tac-Toe (after all 378126132 design revisions), I'll be an expert developer! :)

      Don't get me wrong, I'm not complaining at the least. This has already been a tremendous learning experience for me and I cannot thank you enough for your valuable advice.

      I have some questions of course, but I'm going to read up on the Bridge pattern first, stew on it and then probably post into a new thread - we seem to moving off the "pink edges" topic!
    • Duplicate code? Why not just wrap them into a function that happens to be outside of a class? You could use friend functions and be done with it, from the sound of it. I don't see why everything needs to be inside a class (unless you are writing in Java). Perhaps I am wrong (or just Linux-ized)
      -Larrik Jaerico

      www.LarrikJ.com
    • I think maybe you were just catering to me! I was taught that friends were bad, should be avoided and that they violate encapsulation. Hence, I never spent any time on them and know very little about them. Having said that, I'd like to learn of them, and if you'd love to show a short code sample of how they could be used in the aforementioned context, by all means...! That would be super!
    • I, too, was taught to use the "friends" keyword sparingly.

      Source Code

      1. class A
      2. {
      3. friend class B;
      4. private:
      5. void SecretFunction();
      6. }
      7. class B
      8. {
      9. friend void AlterB( B* pB );
      10. private:
      11. int m_b;
      12. public:
      13. void DoSomething()
      14. {
      15. A a;
      16. a.SecretFunction(); //This is only possible because A considers B a friend
      17. }
      18. }
      19. void AlterB( B* pB )
      20. {
      21. ++pB->m_b; //This is only possible because B considers this function a friend
      22. }
      Display All


      friends do violate encapsulation... or more specifically, they violate the reasons for there being a private/protected keyword in the first place. I try not to use them for that reason just like I try not to use gotos.

      But sometimes I do end up using "friend" because I don't have time to do things the right way at that time.

      Note that I do not ever claim to be an expert on what the right thing to do is. Whether you use the friends keyword or not, due to principle, borders on the religious... as do most coding standards that fall beyond the realm of syntax. I just like to talk about these things in the hopes of checking my sanity with other programmers and maybe even being corrected. Sorry for morphing this thread so much, but I like this thread :)
    • Friends ARE a concern, yes, but that doesn't mean you shouldn't use them. Just use them properly. If you are talking about a group of classes that all share a common function, then you aren't really violating encapsulation, the friend class is merely a part of the package, if you look at it that way.

      Oh, and screw encapsulation ;)
      -Larrik Jaerico

      www.LarrikJ.com