• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
OmarShehata

SDL openGL PNG transparency?

11 posts in this topic

Ok so I've been fiddling with this for a while, and while I came across some cool effects, I still haven't managed to achieve what I'm trying to do.

Basically, I just want to have my PNG's transparency enabled.

This is what I have set in an attempt to make it work:

[code]SDL_SetAlpha(surface,0,0);
glEnable (GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);[/code]

But this just makes the images overlap like this: (Where anything black is considered transparent)

[img]http://4urentertainment.org/storage/JoeTest.png[/img]

The rectangle doesn't have any transparent parts in its original PNG, while the blue character has transparency around the sides.

I also tried:

[code]glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);[/code]

Which was suggested here: http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml

But that just gives black in transparent areas:

[img]http://4urentertainment.org/storage/JoeTest2.png[/img]

Any help on getting them to be transparent without overlapping like in the top image would be appreciated, thanks!
0

Share this post


Link to post
Share on other sites
Shouldn't it be [i][font=courier new,courier,monospace]SDL_SetAlpha(surface, [color=#ff0000]SDL_SRCALPHA[/color], 0)[/font][/i]? (Note: I have never used SDL with OpenGL)
Otherwise, you're saying you [u]want[/u] to ignore the SDL_Surface's alpha, and use a per-surface alpha (the third perimeter) instead of the per-pixel alpha.

[color=#333333]Use that with (I think?), [/color][i][font=courier new,courier,monospace]glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).[/font][/i]
1

Share this post


Link to post
Share on other sites
Hmm, that does make sense actually, thanks for the tip!

Unfortunately I still get the same effect as the second one.
0

Share this post


Link to post
Share on other sites
Looks like depth testing. First sprite is drawn and fills the depth buffer; the second sprite is drawn at the same Z and thus fails the depth test in parts where the sprites overlap.

This is the classical problem with transparency; your objects have to be drawn in back-to-front order, because that blending function is drawing order dependent and the back-to-front order is the only way to achieve the correct transparency effect. Of course, if you draw the two sprites a the same Z, then both effectively overlap the other, and none of the drawing orders are sufficient.

Disable the depth test to eliminate the overlap problem though, but you have to ensure that layers are drawn in the correct order (for example; background, sprites, and finally the foreground) to achieve correct transparency though.
1

Share this post


Link to post
Share on other sites
Thanks for that note Brother Bob!

Ok, so I've disabled depth test first using glDepthFunc(GL_NEVER); then tried glDisable(GL_DEPTH_TEST);

Are these function equivalent or do they do different things?

Now my sprites get drawn in the order I draw them, with the first one drawn appearing at the back. Ok, seems good.

Still doesn't work. I try using alpha test, which is supposed to simply not draw the transparent pixels:

[CODE]
glEnable(GL_ALPHA_TEST) ;
glAlphaFunc(GL_GREATER, 0.1f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//After loading image:
SDL_SetAlpha(surface,SDL_SRCALPHA,0);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
//I bind the texture
glColor4f(1,1,1,1);
//I start drawing the square
[/CODE]

And again, no alpha, in fact, the image is rendered very strangely.

[img]http://4urentertainment.org/storage/Pic4.png[/img]

Original image on the right, how it's rendered on the left (and you can see there's still no transparency)

Now if I set the blendFunc to GL_ONE,GL_ONE the red parts of the image become translucent while the white is solid.

I feel pretty lost here. I'd like to do some in depth debugging, but I'm not sure how to go about that.

Is there any chance that the image I'm loading is getting loaded without transparency? Can I ensure that there are transparent pixels? Why doesn't the ALPHA_TEST work? Whether I add it or remove it, it doesn't seem to have any effect.

I really appreciate the help so far, and thank you for your time!
0

Share this post


Link to post
Share on other sites
[quote name='OmarShehata' timestamp='1330576256' post='4918080']
Ok, so I've disabled depth test first using glDepthFunc(GL_NEVER); then tried glDisable(GL_DEPTH_TEST);
[/quote]
The two are not the same. The first is only a comparison function that determines what to draw and what is occluded. The latter disables the depth buffer mechanism entirely. The main difference is that, if you only set depth function, then the depth buffer is still filled with the Z-values of whatever you draw.

Do you really need the depth buffer at all? Drawing the layers in a back-to-front order seems to be more than enough, and there appears to be no need for a depth buffer in the first place.

[quote name='OmarShehata' timestamp='1330576256' post='4918080']
Is there any chance that the image I'm loading is getting loaded without transparency? Can I ensure that there are transparent pixels? Why doesn't the ALPHA_TEST work? Whether I add it or remove it, it doesn't seem to have any effect.
[/quote]
Looks like your image is loaded either without an alpha channel or as a fully opaque image. Are you sure that the image is [i]saved[/i] with a proper alpha channel in the first place?
1

Share this post


Link to post
Share on other sites
[quote name='Brother Bob' timestamp='1330602633' post='4918139']
Do you really need the depth buffer at all? Drawing the layers in a back-to-front order seems to be more than enough, and there appears to be no need for a depth buffer in the first place.
[/quote]

Yeah, I was trying to disable the depth buffer entirely and handle the depths myself.

[quote name='Brother Bob' timestamp='1330602633' post='4918139']
Looks like your image is loaded either without an alpha channel or as a fully opaque image. Are you sure that the image is [i]saved[/i] with a proper alpha channel in the first place?
[/quote]

That's what I'm starting to doubt, the actual image. How can I be sure that is has the proper alpha channels and all that? Is there something I need to adjust with SDL when loading the image? (Like maybe how I need to change the format of the image to 32 bit if the screen is 32 bit)

This is the actual image:

[img]http://4urentertainment.org/storage/Joe.png[/img]

I do think this could be it. Because I kept playing around with
glAlphaFunc(GL_GREATER, 0.1f);

And setting it to any values from 0.1 to 1 doesn't have any effect, setting it to 0 makes nothing get drawn. So the function itself is working I think.
0

Share this post


Link to post
Share on other sites
I need to see more of the relevant code. The image itself has a correct alpha channel so the problem is not there at least. How do you draw the sprites? Using SDL, or using OpenGL as a texture, or something else? How do you load the images and/or textures?
0

Share this post


Link to post
Share on other sites
[quote name='Brother Bob' timestamp='1330609640' post='4918165']
I need to see more of the relevant code. The image itself has a correct alpha channel so the problem is not there at least. How do you draw the sprites? Using SDL, or using OpenGL as a texture, or something else? How do you load the images and/or textures?
[/quote]

I'm importing the graphic as an SDL_Surface, then rendering it as an openGL texture. I've got a GLShapes class which has all my drawing code, although it's a quite messy because of all the experimentation I've been doing over the past few days:

[CODE]
#include "Main.h"
using namespace std;
class GLshapes {
public:
void DrawBox(float X,float Y,int width,int height, float angle,string FilePath,float Z){
glDisable(GL_DEPTH_TEST);
glDepthFunc(GL_NEVER); //Remvoes depth sorting
// glEnable (GL_DEPTH_TEST); //Adds depth sorting
// Set the OpenGL state after creating the context with SDL_SetVideoMod

glEnable( GL_TEXTURE_2D ); // Need this to display a texture

////
if(Z == 1){
glEnable(GL_ALPHA_TEST) ;
glAlphaFunc(GL_GREATER, 0.1f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
//////
glLoadIdentity();
// Load the OpenGL texture
GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture
if ( (surface = IMG_Load(FilePath.c_str()) )) {
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
// printf("warning: image.bmp's width is not a power of 2\n");
}
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
//printf("warning: image.bmp's height is not a power of 2\n");
}
//surface = SDL_DisplayFormat(surface);
// Have OpenGL generate a texture object handle for us
SDL_SetAlpha(surface,SDL_SRCALPHA,0);
/*SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );*/

glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);

glGenTextures( 1, &texture );
// Bind the texture object


glBindTexture( GL_TEXTURE_2D, texture );
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// Edit the texture object's image data using the information SDL_Surface gives us
glTexImage2D( GL_TEXTURE_2D, 0, 3, (surface->w), surface->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );


}
// Free the SDL_Surface only if it was successfully created
if ( surface ) {
SDL_FreeSurface( surface );
}
// Clear the screen before drawing
// Bind the texture to which subsequent calls refer to
//glBindTexture( GL_TEXTURE_2D, texture );
glColor4f(1,1,1,1);
glTranslatef(X,Y,0);
glRotatef(angle,0,0,1.0);
glScalef(1.0, -1.0, 1.0);
glBegin( GL_QUADS );

// Top-left vertex (corner)
glTexCoord2i( 0.0, 0.0 );
glVertex3f( -width/2, -height/2, 0 );
// Bottom-left vertex (corner)
glTexCoord2i( 1.0, 0.0 );
glVertex3f( -width/2, height/2, 0 );
// Bottom-right vertex (corner)
glTexCoord2i( 1.0, 1.0 );
glVertex3f( width/2, height/2, 0 );
// Top-right vertex (corner)
glTexCoord2i( 0.0, 1.0 );
glVertex3f( width/2, -height/2, 0 );

glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDeleteTextures( 1, &texture );
glDisable(GL_ALPHA_TEST);

}
};

[/CODE]

Note: if you're wondering, "Z" is just an integer which I was using to toggle the alpha code there for testing.
0

Share this post


Link to post
Share on other sites
You're creating an RGB texture, so the texture doesn't even have an alpha channel. Check the third parameter to glTexImage; you're telling OpenGL that you only want three color components, the R, the G and the B channels, and to throw away the alpha channel. Pass GL_RGBA instead to make it an RGBA texture.

But on another note; don't create the texture all the time you draw like that. Create it once when you start the program, and then just save the texture ID and bind it every frame instead.
1

Share this post


Link to post
Share on other sites
[quote name='Brother Bob' timestamp='1330610505' post='4918168']
You're creating an RGB texture, so the texture doesn't even have an alpha channel. Check the third parameter to glTexImage; you're telling OpenGL that you only want three color components, the R, the G and the B channels, and to throw away the alpha channel. Pass GL_RGBA instead to make it an RGBA texture.

But on another note; don't create the texture all the time you draw like that. Create it once when you start the program, and then just save the texture ID and bind it every frame instead.
[/quote]

Oh my god...you, my good, sir, are brilliant! It works!!

[img]http://4urentertainment.org/storage/JoeBRILLIANCE.png[/img]

It's so beautiful!

You have also saved me *another* great deal of trouble and time, because I knew the way I was adding graphics was lagging immensely, but didn't know why.

I cannot thank you enough Brother Bob!

I guess I should have read the parameters more carefully when implementing the functions.
0

Share this post


Link to post
Share on other sites
Hi,

found this through google since I had the same problem. Here's the stand-alone solution for those who are still looking for it.

[code]#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
GLuint SDLOAT::Graphics::surfaceToTexture(SDL_Surface* surface)
{
GLuint texture; // This is a handle to our texture object
GLenum texture_format;
GLint nOfColors;
if (surface)
{
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 )
{
printf("warning: image width is not a power of 2\n");
}
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 )
{
printf("warning: image height is not a power of 2\n");
}
// get the number of channels in the SDL surface
nOfColors = surface->format->BytesPerPixel;
if (nOfColors == 4) // contains an alpha channel
{
printf("Alpha: yes");
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGBA;
else
texture_format = GL_BGRA;
}
else if (nOfColors == 3) // no alpha channel
{
printf("Alpha: no");
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGB;
else
texture_format = GL_BGR;
}
else
{
printf("warning: the image is not truecolor.. this will probably break\n");
// this error should not go unhandled
}


//Needed for 2d textures
glEnable(GL_TEXTURE_2D);

//Needed for transparency
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );

// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );


// Edit the texture object's image data using the information SDL_Surface gives us
glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels );
}
else
{
printf("SDL could not load image: %s\n", SDL_GetError());
}
if ( surface )
{
SDL_FreeSurface( surface );
}
return texture;
}[/code]
0

Share this post


Link to post
Share on other sites

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  
Followers 0