GL_BLEND

Hi,
I’ve written a little sprite engine in opengl/sdl but when I enable GL_BLEND I get a blank screen. When its not enabled I get the sprites with a blue background.

some of the code is bellow

void SDL_GL_Enter2DMode()
{
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

int SDL_GL_LoadTexture(GLuint *texture, GLfloat *texcoord, int *w, int *h)
{
SDL_Surface *surface[7];
SDL_Surface *image[7];
SDL_Rect area[7];
Uint32 saved_flags[7];
Uint8 saved_alpha[7];
int d=0;

// open png for tile
surface[0]=IMG_Load("../graphics/ships/player/player.png");
surface[1]=IMG_Load("../graphics/ships/enemies/enemy1.png");
surface[2]=IMG_Load("../graphics/powerups/powerup.png");
surface[3]=IMG_Load("../graphics/powerups/shield.png");
surface[4]=IMG_Load("../graphics/money/cash-small.png");
surface[5]=IMG_Load("../graphics/money/cash-medium.png");
surface[6]=IMG_Load("../graphics/money/cash-large.png");

for(d=0;d<7;d++)
{
	*(w+d) = surface[d]->w;
	*(h+d) = surface[d]->h;
	texcoord[0] = 0.0f;			/* Min X */
	texcoord[1] = 0.0f;			/* Min Y */
	texcoord[2] = (GLfloat)surface[d]->w;	/* Max X */
	texcoord[3] = (GLfloat)surface[d]->h;	/* Max Y */

	image[d] = SDL_CreateRGBSurface(
			SDL_SWSURFACE,
			*(w+d), *(h+d),
			32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
			0x000000FF, 
			0x0000FF00, 
			0x00FF0000, 
			0xFF000000
#else
			0xFF000000,
			0x00FF0000, 
			0x0000FF00, 
			0x000000FF
#endif
		       );
	if ( image[d] == NULL ) {
		printf("Didnt load images

");
return 0;
}

	/* Save the alpha blending attributes */
	saved_flags[d] = surface[d]->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
	saved_alpha[d] = surface[d]->format->alpha;
	if ( (saved_flags[d] & SDL_SRCALPHA) == SDL_SRCALPHA ) {
		SDL_SetAlpha(surface[d], 0, 0);
	}

	/* Copy the surface into the GL texture image */
	area[d].x = 0;
	area[d].y = 0;
	area[d].w = surface[d]->w;
	area[d].h = surface[d]->h;
	SDL_BlitSurface(surface[d], &area[d], image[d], &area[d]);

	/* Restore the alpha blending attributes */
	if ( (saved_flags[d] & SDL_SRCALPHA) == SDL_SRCALPHA ) {
		SDL_SetAlpha(surface[d], saved_flags[d], saved_alpha[d]);
		//SDL_SetAlpha(surface, 0, SDL_ALPHA_TRANSPARENT);
	}
}
/* Create an OpenGL texture for the image */
glGenTextures(7, texture);

for(d=0;d<7;d++)
{
	glBindTexture(GL_TEXTURE_2D, *(texture+d));
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D,
		     0,
		     GL_RGBA,
		     *(w+d), *(h+d),
		     0,
		     GL_RGBA,
		     GL_UNSIGNED_BYTE,
		     image[d]->pixels);
	SDL_FreeSurface(image[d]); /* No longer needed */
	SDL_FreeSurface(surface[d]);
}

}

int draw(struct container *screen, int entity, GLuint texture[7], int x, int y, int w, int h)
{

SDL_GL_Enter2DMode();

glBegin( GL_QUADS );
	// Top-left vertex (corner)
	glTexCoord2i( 0, 1 );
	glVertex3f( x, y, 0 );

	// Bottom-left vertex (corner)
	glTexCoord2i( 0, 0 );
	glVertex3f( x, y+h, 0 );

	// Bottom-right vertex (corner)
	glTexCoord2i( 1, 0 );
	glVertex3f( x+w, y+h, 0 );

	// Top-right vertex (corner)
	glTexCoord2i( 1, 1 );
	glVertex3f( x+w, y, 0 );
glEnd();

SDL_GL_Leave2DMode();

}

int startup(struct container *screen, GLubyte *vendor, GLubyte *renderer, GLubyte *version, GLubyte *extensions)

{

int d=0;

int bpp=32;

// SDL INIT

if ( (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO ) == -1 ) ) 

{

	printf("Could not initialize SDL: %s.

", SDL_GetError());

	exit(-1);

}
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);

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,     32);
SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE,  8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE,    8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE,    8);



screen->image = SDL_SetVideoMode(screen->area.w, screen->area.h, bpp, SDL_OPENGL|SDL_HWSURFACE|SDL_GL_DOUBLEBUFFER); // |SDL_FULLSCREEN);  

// SDL INIT

/*

vendor=glGetString(GL_VENDOR);

renderer=glGetString(GL_RENDERER);

version=glGetString(GL_VERSION);

extensions=glGetString(GL_EXTENSIONS);

printf("%s

%s
%s

",vendor,renderer,version);

for(d=0;d<strlen(extensions);d++)

{

	if ( *(extensions+d) == 32 )	

		printf("

");

	else

		printf("%c",*(extensions+d));



}printf("

");*/

glClearColor(0.0,0.0,0.0,0.0);

SDL_GL_SwapBuffers();


glViewport(0,0,screen->area.w,screen->area.h);



glMatrixMode(GL_PROJECTION);

glLoadIdentity();



gluOrtho2D(0,screen->area.w,screen->area.h,0);



glMatrixMode(GL_MODELVIEW);

glLoadIdentity();



glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

}

Thank to anyone who can help,
Image28

Sounds like your fragment’s alpha values are 0. Assuming lighting is disabled, sticking a glColor4f( 0,0,0,1 ); before your glBegin will probably fix it.

Here’s the deal. With BLEND disabled, your fragment alpha doesn’t really matter to what you see. It passes through your DECAL texturing as the resulting post-texturing alpha value (see DECAL behavior here), but then because BLENDing is disabled, it just gets plopped on the framebuffer and not really used for anything (except maybe ALPHA_TEST, if you’ve got that enabled, which sounds like you don’t). Here’s a conceptual pipeline:

vertex color -> TEXTURING -> ALPHA_TEST -> BLENDING -> framebuffer

However, when you enable blend with src_alpha, 1-src_alpha blend func, it’s used as the blend factor between the incoming fragment color and the color already on the framebuffer. If it’s 0, then you get 0% of the color of your fragment and 100% the color that’s on the framebuffer, essentially killing your sprite’s color.

Calling glColor(0,0,0,1) before your glBegin sets the vertex color to opaque black (alpha = 1 = 100%), which with DECAL texturing means the fragment alpha post texturing is 1, meaning after the blend function you get 100% your sprite color and 0% of the background color. Tweak alpha value to-taste.

I had glColor4ub set to blue for some other rendering… after changing that and glBlendFunc to GL_ONE,GL_ONE the background is blended out, but when my sprites pass over each other they are partly opaque.

Setting it to GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA I get a black background around the objects… I have this commented out
//glEnable(GL_ALPHA_TEST);
//glAlphaFunc(GL_GREATER, 0.5);
when I uncomment it I get the same results, a black background where it should be alpha.