Thread: problem with texture coming out white with alpha blend

  1. #1
    Registered User
    Join Date
    Oct 2006
    Location
    New York
    Posts
    124

    problem with texture coming out white with alpha blend

    I am using 32bit PNG texture image with transparency. The rest of the code works other then the texture appearing white.


    this is my main code
    Code:
    #include "EzGame.h"
    enum MOVEMENT { M_UP, M_DOWN , M_LEFT , M_RIGHT};
    struct Link
    {
        MOVEMENT curMove;
        int noUp , noDown , noLeft , noRight;
        SDL_Rect curPos;
    
         Link & operator=(const Link & rhs )
         {
            if (this != &rhs)
            {
    
              this->curMove     = rhs.curMove;
              this->curPos.h    = rhs.curPos.h;
              this->curPos.w    = rhs.curPos.w;
              this->curPos.x    = rhs.curPos.x;
              this->curPos.y    = rhs.curPos.y;
              this->noDown      = rhs.noDown;
              this->noLeft      = rhs.noLeft;
              this->noRight     = rhs.noRight;
              this->noUp        = rhs.noUp;
            }
    
            return *this;
        }
    
    
    };
    
    class Test_Game : public gamestate
    {
    public:
        Test_Game() { initState = false;}
        void update(Input_KeyBoard  & kb, Input_Mouse & ms, gstate & Curstate )
        {
    
            if(!initState)
            {
              Link nPerson;
              nPerson.curPos.x = 128;
              nPerson.curPos.y = 128;
              nPerson.curPos.h = 16;
              nPerson.curPos.w = 16;
              nPerson.curMove  = M_DOWN;
              nPerson.noUp = nPerson.noRight = nPerson.noDown = nPerson.noLeft = 0;
              Data = nPerson;
    
              glMatrixMode (GL_PROJECTION);
              glLoadIdentity ();
              glOrtho (0, 256, 256, 0, 0, 1);
              glDisable(GL_DEPTH_TEST);
              glMatrixMode (GL_MODELVIEW);
              glLoadIdentity();
              glClearColor(0, 0, 0, 0);
              glClear(GL_COLOR_BUFFER_BIT);
              initState = true;
            }
    
             if(!Data.empty())
        {
                Link Temp = boost::any_cast<Link>(Data);
            if( kb.keyDown(SDLK_UP) )
            {
              Temp.curPos.y -= 5;
              Temp.curMove = M_UP;
              Temp.noUp += 1;
              Temp.noDown = Temp.noLeft = Temp.noRight = 0;
            }
            if( kb.keyDown(SDLK_DOWN) )
            {
              Temp.curPos.y += 5;
              Temp.curMove = M_DOWN;
              Temp.noDown += 1;
              Temp.noUp = Temp.noLeft = Temp.noRight = 0;
            }
            if( kb.keyDown(SDLK_LEFT) )
            {
              Temp.curPos.x -= 5;
              Temp.curMove = M_LEFT;
              Temp.noLeft += 1;
              Temp.noDown = Temp.noUp = Temp.noRight = 0;
            }
            if( kb.keyDown(SDLK_RIGHT) )
            {
              Temp.curPos.x += 5;
              Temp.curMove = M_RIGHT;
              Temp.noRight += 1;
              Temp.noDown = Temp.noLeft = Temp.noUp = 0;
            }
            Data = Temp;
        }
            if( kb.keyDown(SDLK_ESCAPE))
            {
                Curstate = gExit;
            }
    
    }
    
        void render(EzDraw & Ez )
        {
    
            glClearColor(0, 0, 0, 0.0);
            glClear(GL_COLOR_BUFFER_BIT);
    
            Ez.Begin(0, GL_TEXTURE_2D, false);
            SDL_Rect Rect;
            Rect.h = Rect.w = 256; Rect.x = 0; Rect.y = 0;
            Ez.DrawImage(Rect, 0.0 , 0.0 , 1.0);
            Ez.End(GL_TEXTURE_2D);
    
    
            Ez.Begin(1, GL_TEXTURE_2D|GL_BLEND, true);
    
            int Which;
             if(!Data.empty())
        {
                 Link Temp = boost::any_cast<Link>(Data);
    
            switch(Temp.curMove)
            {
            case M_LEFT:
                Which = Temp.noLeft % 2;
                if(Which == 0)
                {
                Ez.DrawImage(Temp.curPos, 0 , 0.03125 , .25 );
                }
                else
                {
                Ez.DrawImage(Temp.curPos, .25 , 0.03125 , .25 );
                }
                break;
            case M_DOWN:
                Which = Temp.noDown % 2;
                if(Which == 0)
                {
                Ez.DrawImage(Temp.curPos, 0.484375 , 0.03125 , .25 );
                }
                else
                {
                Ez.DrawImage(Temp.curPos, 0.734375 , 0.03125 , .25 );
                }
                break;
            case M_UP:
                Which = Temp.noUp % 2;
                if(Which == 0)
                {
                Ez.DrawImage(Temp.curPos, 0 , 0.359375 , .25 );
                }
                else
                {
                Ez.DrawImage(Temp.curPos, .25 , 0.359375 , .25 );
                }
                break;
            case M_RIGHT:
                Which = Temp.noRight % 2;
                if(Which == 0)
                {
                Ez.DrawImage(Temp.curPos, .5 , 0.359375 , .25 );
                }
                else
                {
                Ez.DrawImage(Temp.curPos, 0.734375 , 0.359375 , .25 );
                }
                break;
            }
    
        }
            Ez.End(GL_TEXTURE_2D|GL_BLEND );
    
    
        }
    };
    
    
    bool Init_Game(void)
    {
    
    
          if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
        {
            return false;
        }
    
         if( SDL_SetVideoMode( 256 , 256 , 32 , SDL_OPENGL ) == NULL )
        {
            return false;
        }
    
    
        //Set caption
        SDL_WM_SetCaption( "Test Game", NULL );
    
        return true;
    
    }
    int main(int argc, char *argv[])
    {
    
    
    
       if(Init_Game())
       {
        cGame Tester(gWorld);
        Tester._insert(gWorld, new Test_Game );
    
        EzDraw TestDraw(2);
        TestDraw.getImage("Scene.png");
        TestDraw.getImage("Link.png");
        Tester.run(TestDraw);
       }
        //Quit SDL
        SDL_Quit();
       return 0;
    }

    this is the definitions
    Code:
    #include "EzGame.h"
    #include <cmath>
    
    bool EzDraw::Begin(unsigned int select, GLenum flags , bool alpha )
    {
       if( select < Inc)
      {
       glEnable(flags);
       glBindTexture(GL_TEXTURE_2D, textures[select]);
       if(!alpha)
       {
           glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
       }
       glBegin( GL_QUADS );
       OkDraw = true;
       return true;
      }
    
      return false;
    }
    
    void EzDraw::End( GLenum flags )
    {
      if(OkDraw)
      {
        glEnd();
        glDisable(flags);
        OkDraw = false;
      }
    }
    EzDraw::EzDraw(unsigned int N)
    {
        Inc = 0;
        textures = new GLuint[ N ];
        glPixelStorei(GL_UNPACK_ALIGNMENT,4);
    	glGenTextures(N, &textures[ 0 ] );
    
    }
    
    #if SDL_BYTEORDER == SDL_LIL_ENDIAN
       static const Uint32 rmask = 0x000000FF;
       static const Uint32 bmask = 0x0000FF00;
       static const Uint32 gmask = 0x00FF0000;
       static const Uint32 amask = 0xFF000000;
    #else
       static const Uint32 rmask = 0xFF000000;
       static const Uint32 bmask = 0x00FF0000;
       static const Uint32 gmask = 0x0000FF00;
       static const Uint32 amask = 0x000000FF;
    #endif
    
    void EzDraw::getImage(const char * filename)
    {
        SDL_Surface * surface = IMG_Load(filename);
        if(surface == NULL)
        {
            // could not get filename
            return;
        }
    
    	SDL_PixelFormat *format = surface->format;
    	Uint32 widthPow = surface->w;
    	Uint32 heightPow  = surface->h;
    
    	// Create new empty surface.
    	SDL_Surface* newSurface = SDL_CreateRGBSurface( SDL_SRCALPHA,
    		   widthPow, heightPow, 32,
    		   rmask, bmask, gmask, amask );
    
    	// Fill sprite with alpha.
    	unsigned int alpha = SDL_MapRGBA( format, 0, 0, 0, amask );
    	SDL_Rect rect;
    	rect.x = 0;
    	rect.y = 0;
    	rect.h = heightPow;
    	rect.w = widthPow;
    	SDL_FillRect( newSurface, &rect, alpha);
    	surface->flags &= !SDL_SRCALPHA;
    
    	SDL_SetAlpha( newSurface, SDL_SRCALPHA, SDL_ALPHA_TRANSPARENT );
    
    	// Copy image data to our new surface.
    	SDL_BlitSurface( surface, 0, newSurface, 0 );
    
    	// Bind the texture.
    
    	glBindTexture(GL_TEXTURE_2D, textures[Inc]);
    
    	// Convert surface to Open GL format.
    	gluBuild2DMipmaps(GL_TEXTURE_2D, 4,
    		widthPow, heightPow, GL_RGBA,GL_UNSIGNED_BYTE,
                    newSurface->pixels);
    
    	// Free our temporary SDL buffers.
    	SDL_FreeSurface( surface );
    	SDL_FreeSurface( newSurface );
    
    	++Inc;
    }
    
    
    void EzDraw::DrawImage( SDL_Rect & rect, float sx , float sy , float sL )
    {
        float dx = (float)rect.x;
        float dy = (float)rect.y;
    
        glTexCoord2f(sx, sy);
        glVertex2f(dx, dy);
    
        glTexCoord2d(sx + sL, sy);
        glVertex2f(dx + rect.w, dy);
    
        glTexCoord2d(sx + sL, sy + sL);
        glVertex2f(dx + rect.w, dy + rect.h);
    
        glTexCoord2d(sx , sy + sL);
        glVertex2f(dx, dy + rect.h);
    }
    
    
    Input_KeyBoard::Input_KeyBoard(void)
    {
      Uint32 iKey;
      for( iKey = 0x00; iKey < 0xB1; iKey++ )
      {
          Keys_Pressed[ iKey ] = false;
      }
    
    }
    
    void    Input_KeyBoard::listen(SDL_Event & event )
    {
        switch(event.type)
    			{
    			    case SDL_KEYDOWN:
    				Keys_Pressed[event.key.keysym.sym]  = true;
    				break;
                    case SDL_KEYUP:
    				Keys_Pressed[event.key.keysym.sym] = false;
    				break;
    
    			}
    
    }
    
    bool    Input_KeyBoard::keyDown( SDLKey  sym )
    {
        return Keys_Pressed[sym];
    }
    
    
    Input_Mouse::Input_Mouse(void)
    {
        g_MouseClicked = false;
        g_MouseX = 0;
    	g_MouseY = 0;
    }
    
    void Input_Mouse::listen(SDL_Event & event )
    {
        switch(event.type)
    			{
    				//Mouse gathering information
    			case SDL_MOUSEMOTION:
                    g_MouseX = event.motion.x;
    				g_MouseY = event.motion.y;
    				break;
    			case SDL_MOUSEBUTTONDOWN:
    					button = event.button.button;
    					g_MouseClicked = true;
    					break;
    			case SDL_MOUSEBUTTONUP:
    					g_MouseClicked = false;
    					break;
                }
    
    }
    
    bool Input_Mouse::isclick()
    {
        return g_MouseClicked;
    }
    
    bool Input_Mouse::ishover(int & x, int & y, int & h, int & w )
    {
    	if(  (g_MouseX >= x ) && (g_MouseX <= x + w ) )
    		if( (g_MouseY >= y) && ( g_MouseY <= y+h ) )
    			return true;
    	return false;
    }
    
    
    void  Input_Mouse::mousebutton(click_t button )
    {
    	if( button & SDL_BUTTON(1) )
    	button = left_click;
    
    	if( button & SDL_BUTTON(3) )
    	button = right_click;
    }
    
    bool Input_Mouse::isclick(int & x, int & y, int & h, int & w )
    {
    
    	if( ishover(x,y,h,w) )
    		if( isclick() )
    			return true;
    	return false;
    }
    
    void Input_Mouse::scroller( unsigned int & value)
    {
    	if( button == 4 )
    		++value;
    	if( button == 5 )
    		--value;
    }
    
    
    cGame:: cGame(gstate gs)
    {
      Curstate = gs;
    }
    
    void cGame::_insert( gstate Index , gamestate * perm )
    {
        gsList[Index] = perm ;
    }
    
    #define TICKS_PER_SECOND  50
    #define SKIP_TICKS  1000 / TICKS_PER_SECOND
    #define MAX_FRAMESKIP  100
    void cGame::run(EzDraw & Ez)
    {
        Uint32 next_game_tick = SDL_GetTicks();
        int loops;
        gamestate * gMode = gsList[Curstate];
        gstate temp = Curstate;
        while( Curstate != gExit )
        {
            loops = 0;
            while( (SDL_GetTicks() > next_game_tick) && (loops < MAX_FRAMESKIP) )
            {
                while ( SDL_PollEvent(&gevent) )
                {
                    kb.listen(gevent);
                    mc.listen(gevent);
                }
                gMode->update(kb , mc , temp);
    
                if( Curstate != temp )
                {
                  gworld    = gMode->getWorld();
                  Curstate  = temp;
                  gMode     = gsList[Curstate];
                  gMode->_Setup(gworld);
                }
                next_game_tick += SKIP_TICKS;
                loops++;
            }
    
            gMode->render(Ez);
            SDL_GL_SwapBuffers();
        }
    }
    sorry for the long post of source code, but what did I do wrong?
    Last edited by Darkinyuasha1; 06-10-2012 at 04:42 PM. Reason: weird spacing for some reason

  2. #2
    Registered User
    Join Date
    Oct 2006
    Location
    New York
    Posts
    124
    Here is a simpler version
    Code:
    #include <string>
    #include <cmath>
    #include "SDL/SDL.h"
    #include "SDL/SDL_opengl.h"
    #include "SDL_image.h"
    
    void Opengl_init()
    {
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity ();
        glOrtho (0, 200, 200, 0, 0, 1);
        glDisable(GL_DEPTH_TEST);
        glMatrixMode (GL_MODELVIEW);
        glLoadIdentity();
    
        glClearColor(.3, .3, .3, 0);
        glClear(GL_COLOR_BUFFER_BIT);
    }
    
    
    #if SDL_BYTEORDER == SDL_LIL_ENDIAN
       static const Uint32 rmask = 0x000000FF;
       static const Uint32 bmask = 0x0000FF00;
       static const Uint32 gmask = 0x00FF0000;
       static const Uint32 amask = 0xFF000000;
    #else
       static const Uint32 rmask = 0xFF000000;
       static const Uint32 bmask = 0x00FF0000;
       static const Uint32 gmask = 0x0000FF00;
       static const Uint32 amask = 0x000000FF;
    #endif
    
    
    
    void get_texture(std::string filename)
    {
        SDL_Surface * surface = IMG_Load(filename.c_str());
        if(surface == NULL)
        {
            // could not get filename
            return;
        }
    
    	SDL_PixelFormat *format = surface->format;
    
    
    
    
    	// Create new empty surface.
    	SDL_Surface* newSurface = SDL_CreateRGBSurface( SDL_SRCALPHA, surface->w , surface->h, 32,rmask, bmask, gmask, amask );
    
    	// Fill sprite with alpha.
    	Uint32 alpha = SDL_MapRGBA( format, 0, 0, 0, amask );
    	SDL_Rect rect;
    	rect.x = 0;
    	rect.y = 0;
    	rect.h = surface->h;
    	rect.w = surface->w;
    	SDL_FillRect( newSurface, &rect, alpha);
    	surface->flags &= !SDL_SRCALPHA;
    
    	SDL_SetAlpha( newSurface, SDL_SRCALPHA, SDL_ALPHA_TRANSPARENT );
    
    	// Copy image data to our new surface.
    	SDL_BlitSurface( surface, 0, newSurface, 0 );
    
        GLuint texture;
    	// create the texture.
        glPixelStorei(GL_UNPACK_ALIGNMENT,4);
    	glGenTextures(1, &texture );
    	glBindTexture(GL_TEXTURE_2D, texture);
    
    	// Convert surface to Open GL format.
    	gluBuild2DMipmaps(GL_TEXTURE_2D, 4,surface->w, surface->h, GL_RGBA,GL_UNSIGNED_BYTE,newSurface->pixels);
    
    	// Free our temporary SDL buffers.
    	SDL_FreeSurface( surface );
    	SDL_FreeSurface( newSurface );
    }
    
    void DrawProcedure(void)
    {
        glEnable(GL_TEXTURE_2D | GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glBegin( GL_QUADS );
    
        //Upper Left
        glTexCoord2f(0, 0);
        glVertex2f(0, 0);
    
        //Upper Right
        glTexCoord2d(1, 0);
        glVertex2f(32, 0);
    
        //Lower Right
        glTexCoord2d(1, 1);
        glVertex2f(32, 32);
    
        //Lower Left
        glTexCoord2d(0 , 1);
        glVertex2f(0, 32);
        glEnd();
        glDisable(GL_TEXTURE_2D | GL_BLEND);
    }
    
    
    int main(int argc, char **argv)
    {
      if(SDL_Init(SDL_INIT_EVERYTHING) < 0 )
        return -1;
      SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 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 );
      if( SDL_SetVideoMode(200,200, 32, SDL_OPENGL) == NULL)
          return -1;
    
      Opengl_init();
    
      get_texture("Sign.png");
      DrawProcedure();
      SDL_GL_SwapBuffers();
    
      SDL_Event event;
      bool Process = true;
      while(Process)
      while ( SDL_PollEvent(&event) )
            switch (event.type)
            {
                case SDL_QUIT:
                    Process = false;
            }
      SDL_Quit();
      return 0;
    }

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Believe it or not, your only problem is this:
    Code:
        glEnable(GL_TEXTURE_2D | GL_BLEND);
        // ...
        glDisable(GL_TEXTURE_2D | GL_BLEND);
    You can't OR together flags for glEnable/glDisable in that way. If I change that to
    Code:
        glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND);
        // ...
        glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND);
    then your code works.

    Some other things to consider:
    • I get a warning when I compile your code. You should pay attention to warnings.
      Code:
      file.cpp:53:53: warning: large integer implicitly truncated to unsigned type [-Woverflow]
      In this case, amask is too big a parameter for SDL_CreateRGBSurface(). The args are unsigned chars, you should pass 0-255. In your case, probably 255, since that would indicate transparency.
    • The standard is red, green, then blue. You're using r, b, g, which is technically correct since you're consistent, but it's really confusing.
    • You're mixing *d and *f functions (like glTexCoord2d vs glTexCoord2f). You can actually use the *i functions if you're just passing ints... it's all converted to the same type internally. (Probably.)
    • Your main program is running in an infinite loop (at least, your simplified version is). It will use 100% of the CPU. You may want to insert some SDL_Delay() calls and try to get it running at 60 FPS or whatever. Sorry if you're already aware of this.
    • Your code's indentation makes it difficult to read. It mixes spaces and tabs, sometimes 2 space indentation, sometimes 4, sometimes more... if you're consistent, you'll find that you become more efficient with your own code. Your brain doesn't have to figure as much out because it's all in the form it would have predicted.


    By the way, I don't think you need to go to all that trouble to create an alpha-blended surface. It should happen automatically since you have a nonzero amask, I think. Food for thought: this is some texture-loading code from a program that I wrote. It handles transparency perfectly well.
    Code:
    GLuint TextureManager::loadTexture(const std::string &file) {
        SDL_Surface *image = IMG_Load(file.c_str());
        if(!image) {
            return 0;
        }
        
        SDL_Surface *copy = SDL_CreateRGBSurface(
            SDL_SWSURFACE, image->w, image->h, 32,
    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
            0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
    #else
            0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    #endif
            );
        
        SDL_BlitSurface(image, NULL, copy, NULL);
        
        GLuint id;
        glGenTextures(1, &id);
        glBindTexture(GL_TEXTURE_2D, id);
        
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
            copy->w, copy->h, 0,
            GL_RGBA, GL_UNSIGNED_BYTE, copy->pixels);
        
        SDL_FreeSurface(copy);
        SDL_FreeSurface(image);
        
        return id;
    }
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Texture Map shows all white in the cube not the pictures
    By christina123y in forum Game Programming
    Replies: 1
    Last Post: 08-25-2010, 02:20 PM
  2. Direct3D Alpha Blend with Lighting ?
    By rocketman03 in forum Game Programming
    Replies: 10
    Last Post: 07-07-2009, 04:04 PM
  3. D3DXSprite and alpha blend
    By Magos in forum Game Programming
    Replies: 1
    Last Post: 05-23-2006, 04:55 AM
  4. Alpha-Blending Texture - DX9
    By X PaYnE X in forum Game Programming
    Replies: 5
    Last Post: 11-17-2004, 10:02 AM
  5. texture is all white in opengl!
    By Crossbow in forum Game Programming
    Replies: 7
    Last Post: 03-31-2002, 11:54 AM