Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 7 of 7

Thread: Alpha Blending Oddities

  1. #1
    Junior Member Newbie
    Join Date
    Mar 2009
    Posts
    6

    Alpha Blending Oddities

    I'm working on a project with a friend and we are using SDL with OpenGL, and we also have alpha blending.

    Now, alpha blending is giving us a few oddities, and here is a link to how it normally looks.

    http://img249.imageshack.us/img249/5103/normal.png

    Sometimes, however, it transforms into this...

    http://img249.imageshack.us/img249/9671/strange.png

    When the program really hates me, it does this --

    http://img256.imageshack.us/img256/4835/strange2.png


    So, any ideas as to why its doing this?

    -------------

    I understand that rendering order is important: the screen is rendered as such:

    (grid then selections then UI then units -- see code below if this was confusing)

    Code :
    void GameScreen::render()
    {
            grid.Draw();
     
    	if((draw_selection))
    	{
    		// If we are not in the panel's plane, then don't draw the selection box
    		if(!UI.CursorIsInPanels(MouseOffsetsScreen.x, MouseOffsetsScreen.y))
    			DrawPrimitives->DrawSquare(selection_startX - ClipPlane->GetX(), selection_startY - ClipPlane->GetY(), selection_endX - ClipPlane->GetX(), selection_endY - ClipPlane->GetY(), blue);
     
    		for(int i = 0; i < characters.size(); i++)
    			if(characters[i]->Intersects(GetRect(selection_startX, selection_startY, selection_endX, selection_endY)))
    				characters[i]->DrawRect();
    	}
     
            glDepthMask(GL_FALSE);
    	RenderSelections();
     
    	UI.DrawTrans();
    	overlay.DrawTrans();
    	soundGUI.DrawTrans();
    	aNavGraph.DisplayEdges();
    	DrawPrimitives->DrawSquare(10, 555, 120, 590, black, 1.0f);
     
    	soundGUI.DrawOpaq();
    	overlay.DrawOpaq();
    	UI.DrawOpac();
     
    	glDepthMask(GL_TRUE);
     
        //Calculate the frames per second and create the string
    	TextDisplay->DisplayMessage("FPS: ", red, 20, 560, float(FONT_SIZE_MEDIUM));
    	TextDisplay->DisplayMessage(fpsCaption, red, 80, 560, float(FONT_SIZE_MEDIUM));
     
    	if(fpsCounter.get_ticks() > 150)
    	{
     
    		_itoa_s(int(fpsFrame / (fpsCounter.get_ticks() / 1000.f)), fpsCaption, 10);
    		fpsCounter.start();
    		fpsFrame = 0;
     
    	}
     
    	fpsFrame++;
     
    	RenderEntities();
    }

    Here is how the grid is rendered
    Code :
    void Grid::Draw()
    {
     
    	for(int x = 0; x < MAP_WIDTH; x++)
    		for(int y = 0; y < MAP_HEIGHT; y++)
    		{
    			Entity::ResetZLevel();
    			for(int i = 0; i < NUMBER_OF_LAYERS; ++i)
    			{
     
    			        if(!gridButtons[i][x][y].IsIgnoredTile())
    				       gridButtons[i][x][y].applySurface();
     
     
     
    			        if(gridButtons[i][x][y].GetDrawBox())
    				       gridButtons[i][x][y].DrawBox();
     
     
    		}
     
    	}
     
     
    }

    The DrawTrans // RenderSelection functions just call this function:
    Code :
    void GLPrimitives::DrawSquare(int x1, int y1, int x2, int y2, OGL_Color color)
    {
    	glColor4f(color.r, color.g, color.b, color.a);
    	SDL_Rect aRect = GetRect(x1, y1, x2, y2);
     
    	glBegin(GL_QUADS);
    		glVertex3f( GLfloat(aRect.x), GLfloat(aRect.y), 1.0f );
    		glVertex3f( GLfloat(aRect.x + aRect.w), GLfloat(aRect.y), 1.0f );
    		glVertex3f( GLfloat(aRect.x + aRect.w), GLfloat(aRect.y + aRect.h), 1.0f );
    		glVertex3f( GLfloat(aRect.x), GLfloat(aRect.y + aRect.h), 1.0f );
    	glEnd();
    }

    The RenderEntities function just calls the applySurface function
    Code :
    void Entity::applySurface()
    {
     
            if(imageID == ignoredImage) // optimization; don't draw something that isn't going to show up!
                    return;                                
     
     
    	SDL_Rect aRect(Rect);
     
            // Zooming in / out
    	aRect.x *= m_scaler;
    	aRect.y *= m_scaler;
    	aRect.w *= m_scaler;
    	aRect.h *= m_scaler;
     
    	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
     
    	if(ClipPlane->IsInPlane(aRect))
    	{
    	        glScalef(m_scaler, m_scaler, 1.0f);
     
    	        glTranslatef(Rect.x - ClipPlane->GetX(), Rect.y - ClipPlane->GetY(), m_z);
    		glCallList(m_displayLists[imageID]);
    		glLoadIdentity();
    	}
    }

    Here is the texture loading function (includes glCallList(...), marked with a big ----------------- comment)

    Code :
    void Entity::Load_Image(const char* filename)
    {
     
    	// ... big or small endian code commented out
     
    	// Load in the image from the filename
    	SDL_Surface *orig;
    	orig = IMG_Load(filename);
    	if(orig == NULL)
    	{
    		assert("Texture not correctly loaded" &amp;&amp; false);
    	}
     
    	SDL_Surface* paddedOrig = SDL_CreateRGBSurface(SDL_SWSURFACE, unsignedNextPowerOfTwo(orig->w), unsignedNextPowerOfTwo(orig->h), WINDOW_BPP,
    		RGBAFormat.Rmask, RGBAFormat.Gmask, RGBAFormat.Bmask, RGBAFormat.Amask);
     
    	SDL_Surface *surface;
    	if(orig->w != unsignedNextPowerOfTwo(orig->w) || orig->h != unsignedNextPowerOfTwo(orig->h))
    	{
    		SDL_BlitSurface(orig, NULL, paddedOrig, NULL);
    		surface = SDL_ConvertSurface(paddedOrig, &amp;RGBAFormat, SDL_SWSURFACE);
    	}
    	else 
    		surface = SDL_ConvertSurface(orig, &amp;RGBAFormat, SDL_SWSURFACE);
     
    	// Convert the surface to a format readable by openGL
    	m_images_sizes.resize(m_images_sizes.size() + 1);
    	m_images_sizes[m_images_sizes.size() - 1].h = paddedOrig->h;
    	m_images_sizes[m_images_sizes.size() - 1].w = paddedOrig->w;
     
    	SDL_FreeSurface(orig);
    	SDL_FreeSurface(paddedOrig);
     
    	// get the number of channels in the SDL surface
        nOfColors = surface->format->BytesPerPixel;
        if (nOfColors == 4)     // contains an alpha channel
        {
                if (surface->format->Rmask == 0x000000ff)
                        texture_format = GL_RGBA;
                else
                        texture_format = GL_BGRA;
        } else if (nOfColors == 3)     // no alpha channel
        {
                if (surface->format->Rmask == 0x000000ff)
                        texture_format = GL_RGB;
                else
                        texture_format = GL_BGR;
        } else {
                assert("Loaded image is not truecolor" &amp;&amp; false);
        }
     
    	// Have OpenGL generate a texture object handle for us
    	glGenTextures( 1, &amp;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, nOfColors, surface->w, surface->h, 0,
                          texture_format, GL_UNSIGNED_BYTE, surface->pixels );
     
     
     
    	// Free memory and return the texture
    	SDL_FreeSurface(surface);
     
        m_images.push_back(texture);
     
     
    	// Increase display list size
    	m_displayLists.resize(m_displayLists.size() + 1);
    	m_displayLists[m_displayLists.size() - 1] = glGenLists(1);
     
     
            /* ---------------------------------------------------------------------- */
    	/* Build the list ------------------------------------------------------- */
            /* ---------------------------------------------------------------------- */
    	glNewList(m_displayLists[m_displayLists.size() - 1], GL_COMPILE);
     
    		// Set color to (nothing)
    		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
     
    		// Bind the texture
    		glBindTexture(GL_TEXTURE_2D, texture);
     
     
    		SDL_Rect aRect;
    		aRect.x = 0;
    		aRect.y = 0;
     
    		aRect.x = (aRect.x - ClipPlane->GetX());
    		aRect.y = (aRect.y - ClipPlane->GetY());
    		aRect.w = m_images_sizes[m_images_sizes.size() - 1].w;
    		aRect.h = m_images_sizes[m_images_sizes.size() - 1].h;
     
     
    		glBegin(GL_QUADS);
    			//Top-left vertex (corner)
    			glTexCoord2i( 0, 0 );
    			glVertex3f( aRect.x, aRect.y, 0.0f );
     
    			//Bottom-left vertex (corner)
    			glTexCoord2i( 1, 0 );
    			glVertex3f( GLfloat(aRect.x + aRect.w), GLfloat(aRect.y), 0.0f );
     
    			//Bottom-right vertex (corner)
    			glTexCoord2i( 1, 1 );
    			glVertex3f( GLfloat(aRect.x + aRect.w), GLfloat(aRect.y + aRect.h), 0.0f );
     
    			//Top-right vertex (corner)
    			glTexCoord2i( 0, 1 );
    		        glVertex3f( GLfloat(aRect.x), GLfloat(aRect.y + aRect.h), 0.0f );
    	        glEnd();
    	glEndList();
    }
     
    Here is how I have set up OpenGL
     
     
    void initGL()
    {
     
        glClearColor( 0, 0, 0, 1 );
     
        glMatrixMode( GL_PROJECTION );
            glPushMatrix();
        glLoadIdentity();
     
        glOrtho( 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0.0f, -1.0f, 2.0f );
     
        glMatrixMode( GL_MODELVIEW );
    	glPushMatrix();
        glLoadIdentity();
     
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
        glFrontFace(GL_CW);
        glEnable(GL_ALPHA_TEST);
        glEnable(GL_TEXTURE_ENV);
     
    }

    And finally, here is how I have set up OpenGL
    Code :
    void initGL()
    {
     
        glClearColor( 0, 0, 0, 1 );
     
        glMatrixMode( GL_PROJECTION );
            glPushMatrix();
        glLoadIdentity();
     
        glOrtho( 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0.0f, -1.0f, 2.0f );
     
        glMatrixMode( GL_MODELVIEW );
    	glPushMatrix();
        glLoadIdentity();
     
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
        glFrontFace(GL_CW);
        glEnable(GL_ALPHA_TEST);
        glEnable(GL_TEXTURE_ENV);
     
    }

    Sorry for the long post; hopefully you all can help me solve this rather obnoxious issue.

    Thanks.

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Feb 2006
    Location
    Sweden
    Posts
    748

    Re: Alpha Blending Oddities

    My theory is that your setting the blendfunc somewhere else as well.

    OpenGL is a state machine, that means it saves the rendering state until it's changed.
    However it also means people get careless and think these states will be there forever, you can never be sure of that.
    So the proper way to do it is to enable and disable states for each group of polygons you render, this includes blending.

  3. #3
    Junior Member Newbie
    Join Date
    Mar 2009
    Posts
    6

    Re: Alpha Blending Oddities

    I just went through the project and wherever objects are rendered I added glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA). (Right above the code.) Sadly, this did not help the situation. Thanks, and do you happen to have any other ideas? If you want to see the entire project, its at http://code.google.com/p/basicrpg34253/source/browse/

  4. #4
    Intern Contributor
    Join Date
    Feb 2000
    Location
    Germany
    Posts
    95

    Re: Alpha Blending Oddities

    Just took a very quick look at the source.
    Perhaps your global color variables (green) get corupted somewhere, since it does also affect other UI elements.

  5. #5
    Junior Member Newbie
    Join Date
    Mar 2009
    Posts
    6

    Re: Alpha Blending Oddities

    The only issue that I have with them being corrupted is that the colors snap back. Also, it would probably help if I told you all that I discovered something: the alpha levels only change when the bottom right hand pixel of the screen is over water.

    Again, thanks. I'll look into the global color variables as well and check to see if they are being corrupted.

    Edit:
    Could loading images in at different BPP levels be a cause of this?

    Thanks.

  6. #6
    Advanced Member Frequent Contributor
    Join Date
    Feb 2006
    Location
    Sweden
    Posts
    748

    Re: Alpha Blending Oddities

    no.
    Btw. did you disable and manage textures correctly, the reason is that sometimes you might get the last drawn texture in the form of a solid color from a corner or something, it could be getting the corrupt alpha from there

  7. #7
    Junior Member Newbie
    Join Date
    Mar 2009
    Posts
    6

    Re: Alpha Blending Oddities

    zeoverlord -- I thought about what you said and decided to try a glDisable(GL_TEXTURE_2D) right before I draw any primitives and it worked.

    --
    Thanks all. I have no idea why something like this would effect it, but then again, OpenGL is one big behemoth.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •