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" && 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, &RGBAFormat, SDL_SWSURFACE); } else surface = SDL_ConvertSurface(orig, &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" && false); } // Have OpenGL generate a texture object handle for us 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, 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.




