Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


SDL multiple layer transparency issue


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 ZwodahS   Members   -  Reputation: 483

Like
1Likes
Like

Posted 11 April 2013 - 12:16 PM

Hi guys I have another issue with SDL recently. Here is the smallest segment possible.

Circle is a circle with a hole in the middle and square is just a square.

SDL_Surface* loadImage(std::string filename)
{
    SDL_Surface* img = IMG_Load(filename.c_str());
    if(img == NULL)
    {
        return NULL;
    }
    SDL_Surface* optimized = SDL_DisplayFormatAlpha(img);
    SDL_FreeSurface(img);
    return optimized;
}

int main(int args , char* argv[] )
{
    if(SDL_Init(SDL_INIT_EVERYTHING) == 1)
    {
        std::cout << "error" << std::endl ;
    }
    SDL_Surface* surface = SDL_SetVideoMode(100,100,32,SDL_SWSURFACE);
    SDL_Surface* circle = loadImage("circle.png");
    SDL_Surface* square = loadImage("square.png");
    SDL_PixelFormat* format = surface->format;    
    SDL_Rect rect = {0 ,0 , 100 , 100};

    // draw code
    
    SDL_Flip(surface);


 

so for the draw code , this works.

    SDL_BlitSurface(square,&rect,surface,&rect);
    SDL_BlitSurface(circle,&rect,surface,&rect);

However, I want to draw to a temporary surface first before drawing.

Then this don't work.

    SDL_PixelFormat* format = surface->format;
    SDL_Surface* temp1 = SDL_CreateRGBSurface(SDL_SWSURFACE,100,100,32,format->Rmask,format->Gmask,format->Bmask,format->Amask);
    SDL_Surface* temp2 = SDL_CreateRGBSurface(SDL_SWSURFACE,100,100,32,format->Rmask,format->Gmask,format->Bmask,format->Amask);

    SDL_BlitSurface(square,&rect,temp1,&rect);
    SDL_BlitSurface(circle,&rect,temp2,&rect);
    SDL_BlitSurface(temp1,&rect,surface,&rect);
    SDL_BlitSurface(temp2,&rect,surface,&rect);

 

When I do this, the temporary surface has a black background and the final output is only a circle.

 

I checked and I found out that surface->format->Amask is 0 , so the created surface do not have alpha enabled.

So instead of using surface-> format, i tried using circle->format instead. The result ? , nothing is drawn.

 

I tried other stuffs as well, like doing a SDL_FillRect onto temp1 and temp2 , but it still doesn't do what i want. =( 

I tried doing SDL_SetAlpha as well but still didn't work. What am i missing ? =/

 


Check out my blog at zwodahs.github.io and zwodahs.itch.io/


Sponsor:

#2 Kylotan   Moderators   -  Reputation: 3338

Like
0Likes
Like

Posted 12 April 2013 - 05:36 AM

When you blit, you don't normally copy across alpha information, because the alpha is used to decide what to blit. There are a couple of suggestions in this thread though: http://forums.libsdl.org/viewtopic.php?t=3943

#3 ZwodahS   Members   -  Reputation: 483

Like
1Likes
Like

Posted 14 April 2013 - 05:15 AM

Thanks a lot. 

 

Here is the code that works, in case other people face the same problem.

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <iostream>


SDL_Surface* loadImage(std::string filename)
{
    SDL_Surface* img = IMG_Load(filename.c_str());
    if(img == NULL)
    {
        return NULL;
    }
    SDL_Surface* optimized = SDL_DisplayFormatAlpha(img);
    SDL_FreeSurface(img);
    return optimized;
}

int main(int args , char* argv[] )
{
    if(SDL_Init(SDL_INIT_EVERYTHING) == 1)
    {
        std::cout << "error" << std::endl ;
    }
    SDL_Surface* surface = SDL_SetVideoMode(100,100,32,SDL_SWSURFACE);
    SDL_FillRect(surface,0,SDL_MapRGBA(surface->format,100,100,100,255));

    SDL_Surface* circle = loadImage("circle.png");
    SDL_Surface* square = loadImage("square.png");

    SDL_PixelFormat* format = surface->format;
    SDL_Surface* temp1 = SDL_CreateRGBSurface(SDL_SWSURFACE,100,100,32,format->Rmask,format->Gmask,format->Bmask,format->Amask);
    SDL_Surface* temp2 = SDL_CreateRGBSurface(SDL_SWSURFACE,100,100,32,format->Rmask,format->Gmask,format->Bmask,format->Amask);

    temp1 = SDL_DisplayFormatAlpha(temp1);
    temp2 = SDL_DisplayFormatAlpha(temp2);

    SDL_SetAlpha(square,0,square->format->alpha);
    SDL_SetAlpha(circle,0,circle->format->alpha);

    SDL_Rect rect = {0 ,0 , 100 , 100};

    SDL_BlitSurface(square,&rect,temp1,&rect);
    SDL_BlitSurface(circle,&rect,temp2,&rect);
    SDL_BlitSurface(temp1,&rect,surface,&rect);
    SDL_BlitSurface(temp2,&rect,surface,&rect);

    SDL_Flip(surface);


    SDL_Delay(2000); 

 

SDL_DisplayFormatAlpha is needed to set the mask for the surface, because the original surface do not have alpha mask.

 

There is a lot of memory leak here, and many surface is not freed to reduce the length of the code.

 

Once again, thanks :P


Check out my blog at zwodahs.github.io and zwodahs.itch.io/





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS