Sign in to follow this  

[SDL] Setting a colorkey on a primitive function?

This topic is 2337 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

A problem I'm running into right now;
I have a SDL_Surface* overlay, at the beginning of my code, as such:
[code]

if(overlay == NULL){overlay = SDL_CreateRGBSurface(screen->flags, screen->w,

screen->h, screen->format->BitsPerPixel, screen->format

->Rmask, screen->format->Gmask, screen->format->Bmask,

screen->format->Amask);

overlay = SDL_DisplayFormat(overlay);

boxRGBA(overlay, 0, 0, overlay->w, overlay->h, 255, 255,

255, 0);

SDL_SetAlpha(overlay, SDL_SRCALPHA, 0);

}

[/code]

It's first set to NULL, and is then made to fit the screen surface, and go completely transparent, while optimizing the surface... everything's fine so far, right?

Ok, so now my problem, somewhere along the code, I have a function call to
[code]filledEllipseRGBA(overlay, bx, by, ch.lightRadius,

ch.lightRadius, ch.lightColor.r, ch.

lightColor.g, ch.lightColor.b, ch.lightAlpha);

[/code]

Which is set to magenta at that point, drawing a circle of color magenta on the screen,
Now, I want to use the SDL_SetColorKey function to set the transparent color of the overlay surface to Magenta, so that the magenta circle on the surface won't show up.

This brings up a couple of problems, it'll cause a MAJOR slow down of the game, and it wouldn't even work.
I tried positioning it first right next to the drawing function, to discover these effects, but then, even when I put it along in the initializer code at the beginning of the post, it'll still actually cause slowdown, even though it's only called once, at the beginning of the code, and not repeating...

I'm kind of at a loss here, since the surface is constantly to be changed, it isn't like using it on a static surface loaded from a file, so I'm not really sure if I'm even using the right method...


Any input would be most appreciated =)

Share this post


Link to post
Share on other sites
[code]SDL_SetAlpha(overlay, SDL_SRCALPHA, 0);[/code]
If I understand correctly this makes the whole surface transparent. Is this what you want? Using SDL_SRCALPHA will normally be slower than not using it. Using a color key will also make it somewhat slower. I don't know if using both SDL_SRCALPHA and SDL_SRCCOLORKEY will be terrible slow.

Share this post


Link to post
Share on other sites
Yea, I need the whole surface to be semi transparent, and then a part of it wholy transparent, is this even possible?
Ok, so say that SRCCOLORKEY does slow it down this much, how come it only does it for shapes, and not surfaces loaded from images?

Also, why doesn't boxRGBA make the shape transparent on its' own? If I DON'T use SDL_SetAlpha after calling boxRGBA, it'll treat the shape as 100% opaque regardless of the alpha level I feed to the function)

Share this post


Link to post
Share on other sites
[quote name='KazenoZ' timestamp='1311602154' post='4839985']Yea, I need the whole surface to be semi transparent, and then a part of it wholy transparent, is this even possible?[/quote]
Yes, made a test and this works.
[code]#include "SDL.h"
#include "SDL_gfxPrimitives.h"
#include <stdio.h>

int main()
{
SDL_Init(SDL_INIT_VIDEO);

SDL_Surface* screen = SDL_SetVideoMode(200, 200, 0, SDL_SWSURFACE);
SDL_Surface* overlay = SDL_CreateRGBSurface(screen->flags, screen->w, screen->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
overlay = SDL_DisplayFormat(overlay); // is this really needed?

boxRGBA(overlay, 0, 0, overlay->w, overlay->h, 255, 255, 255, 255); // Here I changed the alpha value to fully opaque
SDL_SetAlpha(overlay, SDL_SRCALPHA, 128); // Here change the alpha value to semi transparent

filledEllipseRGBA(overlay, 100, 100, 60, 60, 255, 0, 255, 255); // Here I also have to change the alpha value, otherwise this had no effect

SDL_SetColorKey(overlay, SDL_SRCCOLORKEY, SDL_MapRGB(overlay->format, 255, 0, 255)); // magenta colorkey

SDL_Rect rect = {0, 0, 0, 0};
SDL_BlitSurface(overlay, 0, screen, &rect);

SDL_Flip(screen);

SDL_Delay(4000); // get some time to see the result
SDL_Quit();
}[/code]

[quote name='KazenoZ' timestamp='1311602154' post='4839985']Ok, so say that SRCCOLORKEY does slow it down this much, how come it only does it for shapes, and not surfaces loaded from images?[/quote]
If the surfaces are the same, have the same format etc. it should not make a difference how you load the surface. Using the functions provided by SDL_gfx is probably slower than blitting from a surface.

[quote name='KazenoZ' timestamp='1311602154' post='4839985']Also, why doesn't boxRGBA make the shape transparent on its' own?[/quote]
boxRGBA don't affect the alpha value of the surface. The alpha value you pass to boxRGBA only affect how much of the old surface colors will be visible. Note that there is a difference between per surface alpha and per pixel alpha. SDL_SetAlpha changes the per surface alpha.

Share this post


Link to post
Share on other sites
Your example is great, but what I need is a semi transparent surface(The grey you used) with a fully transparent shape on it(Like you did with the circle), I need to be able to see the surfaces beneath it, under the effect of the tainted screen from the semi transparent color, with a bit that's completely visible of the surface below.

I only learned after posting that SDL_SRCALPHA and SDL_SRCCOLORKEY can't be used at the same time, so, atleast by the looks of it, unless there's another way to bypass this, you can't have a semitransparent shape which is per surface, and a completely transparent shape, which is per pixel with the alpha color key, used on the same surface , which explains why they kept cancelling eachother out... but that's the exactly what I needed to use, is there any way around that maybe?...

Maybe there's a function to delete a part of a drawn shape? Instead of using filledElipseRGBA to paint it to magenta and then make it transparent, a way to use a similiar function that tears away the filledElipse from the current surface, leaving it transparent?

Share this post


Link to post
Share on other sites
The grey is because the overlay surface is white and is blitted on top of the black background. The alpha value of 128 makes a mix of black and white, which is grey. The black in the middle is because of the colorkey and it is the black background you see.

If you first blit another background you will see better. Here is an example. To the left is without the overlay, to the right you see with the overlay.
[img]http://img51.imageshack.us/img51/2002/overlayf.png[/img]

Share this post


Link to post
Share on other sites
Gah, I feel so stupid, I didn't even look at the values in the code after I saw the grey D:

Wow... so basicly... the big big secret behind this is just to set the initial value of the shape to completely opaque? I did it and it works like a charm now.

But there's still something wrong here, it still causes a huge slowdown when I use the SetColorKey in there. How do games that use this technique do that without dropping the frame rate?


I really appreciate your help so far, you've been very very informative and I thank you for your time =)

Share this post


Link to post
Share on other sites
I don't know how you are doing but constructing surfaces is slow so it is always good if you don't have to create new surfaces every frame. Instead try to create them all at the start and have them ready to be used when you need them.

Try pass SDL_RLEACCEL when setting the colorkey.[code]SDL_SetColorKey(overlay, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(overlay->format, 255, 0, 255));[/code]This will probably be faster in this case (close to the speed without colorkey), but note that if you are blitting to the overlay surface after this it will be slower.

Share this post


Link to post
Share on other sites
I thought that RLE was automatically set when you use DisplayFormat()?
Also SetColorKey doesn't work if you only set it at the beginning, you need to set it each time you're using the color, but even though that is only done once, still it causes the slowdown....

Share this post


Link to post
Share on other sites
[quote name='KazenoZ' timestamp='1311719492' post='4840847']I thought that RLE was automatically set when you use DisplayFormat()?[/quote]
It's not. DisplayFormat only converts the surface to the same format as the screen surface so it don't have to make the conversion every time you call SDL_BlitSurface.

[quote name='KazenoZ' timestamp='1311719492' post='4840847']Also SetColorKey doesn't work if you only set it at the beginning, you need to set it each time you're using the color, but even though that is only done once, still it causes the slowdown....[/quote]You should only have to set the colorkey once for each surface you use it on and you probably want to set it when you have finished blitting to it. So in the example code I posted I think it is in a good place.

Are you you creating the overlay surface every frame? How do you notice the slowdown? Do SDL_RLEACCEL make any difference at all?

Share this post


Link to post
Share on other sites
That did all the difference, put it on every instance of SetColorKey and now there's no drop at all, going as fast as it should, thanks alot =)

Share this post


Link to post
Share on other sites

This topic is 2337 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this