I hate myself sometimes (SDL, Transparency)

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

I hate myself sometimes (SDL, Transparency)

Postby DistortedLance on Sun Dec 09, 2012 9:18 pm

I was easily able to quickly come up with something that would give me an entirely transparent SDL_Surface* that would theoretically just be something used to combine other surfaces while maintaining their transparencies. I also wanted to generalize my drawing so that every surface would act as if I were laying overhead sheets on top of each other - that is, you can see through all the way to the bottom sheet where there isn't something solid/non-transparent.

//To create a blank texture of the given size
uint32_t BlankTexture(int width, int height)
SDL_Surface* surface = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height, 32,
0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
SDL_FillRect(surface, 0, SDL_MapRGBA(surface->format, 0, 0, 0, 0);
SDL_SetAlpha(surface, SDL_SRCALPHA, 0);

And, of course, I needed to create something that would let me actually clip a texture, otherwise there would be no real use for obtaining a new blank surface. It automatically generates a new blank surface, so I should probably change things around so I can just directly merge portions of textures with others without the middle step. Oh well.

//To clip a texture
uint32_t ClipTexture(uint32_t textureid, int x, int y, int w, int h)
Rect clip = {x, y, w, h};

SDL_Surface* source = textures[textureid].surface;
SDL_SetAlpha(source, 0, 0);

SDL_Surface* clipped = SDL_CreateRGBSurface(SDL_HWSURFACE, w, h, 32,
0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
SDL_FillRect(clipped, 0, SDL_MapRGBA(clipped->format, 0, 0, 0, 0));
SDL_SetAlpha(clipped, SDL_SRCALPHA, 0);

SDL_BlitSurface(source, &clip, clipped, 0);
SDL_SetAlpha(source, SDL_SRCALPHA, 0);

Things all went downhill when I tried to re-implement what I thought would simply be the same functionality in my generic DrawTexture() function - I would just need to copy the same SDL_SetAlpha() calls, ignoring the stuff in the middle that automatically generated a new SDL_Surface*, right?

Weeeeell, I'm really terrible at this alpha blending stuff, so I didn't actually do it right for the longest time. It turns out I don't want to be setting the source to be opaque if I'm drawing it to the screen - only if I'm drawing to another surface.

//Draws a texture onto either a texture or the screen
void DrawTexture(uint32_t textureid, int x, int y, Rect* srcclip, uint32_t desttexture = 0)
SDL_Surface* destsurface = 0;
if(!dest) destsurface = screen->GetSurface();
destsurface = textures[desttexture].surface;
SDL_SetAlpha(textures[textureid].surface, 0, 0); //Only SetAlpha if drawing to another texture
} //^This call used to be outside the conditional right before the SDL_BlitSurface() call

Rect offset = {x, y, 1337, 9001};

SDL_SetAlpha(destsurface, SDL_SRCALPHA, 0);
SDL_BlitSurface(textures[textureid].surface, clip, destsurface, &offset);
SDL_SetAlpha(textures[textureid].surface, SDL_SRCALPHA, 0); //Aaaaaand reset when you're done

I'd been staring at my code wondering why I was just getting white boxes every time I tried drawing things onto other textures; I was especially confused because ClipTexture() worked perfectly fine, and I thought I was doing the same exact thing. Then I tried this, and it worked. At least, I'm pretty sure it works. I haven't tested every scenario, but it certainly does what it wasn't doing before. If you see anything screwed up, I would really appreciate it being fixed ^_^

Lesson learned? Read documentation.
User avatar
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 26
Joined: Fri Jul 22, 2011 1:36 pm

Return to Programming Discussion

Who is online

Users browsing this forum: No registered users and 1 guest