   How to show png with an alpha channel correctly
  I'm trying to load a 32 bit png file and to render it by opengl. There are 2 problems for me to do this. The first of all it seems the alpha channel ignored by opengl. The second problem is that the rendering is very very slow. If I load a normal bmp file with the same code, it will be rendered very fast.Here is my code. Can anybody advise?////////////////////////////////////////////////////////////////   main.cpp#include "wxgl.h"//wxWidgets Applicationclass MyApp : public wxApp{public:    virtual bool OnInit();};IMPLEMENT_APP(MyApp);class MyFrame: public wxFrame{public:    MyFrame(wxFrame *frame, const wxString& title);    ~MyFrame();private:    void OnFullScreen(wxCommandEvent& event);    DECLARE_EVENT_TABLE();    wxGL* gl;};bool MyApp::OnInit(){    ::wxInitAllImageHandlers();    MyFrame* frame = new MyFrame(0L, _("wxWidgets Application Template"));    frame->Show();    return true;}int idMenuFullscreen = 1001;int idMenuQuit = 1002;int idMenuAbout = 1003;BEGIN_EVENT_TABLE(MyFrame, wxFrame)    EVT_MENU(idMenuFullscreen, MyFrame::OnFullScreen)    EVT_MENU(idMenuQuit, MyFrame::OnQuit)END_EVENT_TABLE()MyFrame::MyFrame(wxFrame *frame, const wxString& title)   : wxFrame(frame, -1, title){#if wxUSE_MENUS    // create a menu bar    wxMenuBar* mbar = new wxMenuBar();    wxMenu* fileMenu = new wxMenu(_T(""));    fileMenu->AppendCheckItem(idMenuFullscreen, _("Full &screen\tF12"), _("Full screen"));    fileMenu->Append(idMenuQuit, _("&Quit\tAlt-F4"), _("Quit the application"));    mbar->Append(fileMenu, _("&File"));    SetMenuBar(mbar);#endif // wxUSE_MENUS    int w,h;    GetClientSize(&w,&h);wxInt32 attrib[] = {WX_GL_RGBA,WX_GL_DEPTH_SIZE,32,WX_GL_DOUBLEBUFFER,0,};    gl =new wxGL(this,-1,wxPoint(0,0),wxSize(w,h),0,wxT(""),&attrib[0]);}MyFrame::~MyFrame(){}void MyFrame::OnFullScreen(wxCommandEvent& event){    gl->OnFullScreen(event);    ShowFullScreen(event.IsChecked());}void MyFrame::OnQuit(wxCommandEvent& event){    Close();}////////////////////////////////////////////////////////////  wxgl.h#ifndef WXGL_H#define WXGL_H#include <wx/glcanvas.h>#include <gl/glu.h>class wxGL : public wxGLCanvas{public:    wxGL(wxWindow* parent, wxWindowID id = -1,   const wxPoint& pos = wxDefaultPosition,   const wxSize& size = wxDefaultSize,   long style=0,   const wxString& name="GLCanvas",   int* attribList = 0);    virtual ~wxGL();    void OnPaint(wxPaintEvent& event);    void OnSize(wxSizeEvent& event);    void OnEraseBackground(wxEraseEvent& event);    void OnFullScreen(wxCommandEvent& event);    void OnIdle(wxIdleEvent& event);private:    bool    InitGL();    void    ResizeGL();    void    RenderScene();    bool    LoadTextures();    DECLARE_EVENT_TABLE()};#endif // WXGL_H/////////////////////////////////////////////////////////////////// wxgl.cpp#include "wxgl.h"#include <wx/image.h>boolkeys[256];// Array Used For The Keyboard Routineboolactive=true;// Window Active Flag Set To TRUE By Defaultboolfullscreen=false;// Fullscreen Flag Set To Fullscreen Mode By DefaultGLfloatxrot;// X Rotation ( NEW )GLfloatyrot;// Y Rotation ( NEW )GLfloatzrot;// Z Rotation ( NEW )GLuinttexture[1];// Storage For One Texture ( NEW )wxImage image;BEGIN_EVENT_TABLE(wxGL,wxGLCanvas)    EVT_IDLE(wxGL::OnIdle)    EVT_PAINT(wxGL::OnPaint)    EVT_SIZE(wxGL::OnSize)    EVT_ERASE_BACKGROUND(wxGL::OnEraseBackground)END_EVENT_TABLE()wxGL::wxGL(wxWindow *parent, wxWindowID id,   const wxPoint& pos,   const wxSize& size,   long style, const wxString& name,int* attribList )    : wxGLCanvas(parent, (wxGLCanvas*) NULL, id, pos, size,   style|wxFULL_REPAINT_ON_RESIZE , name, attribList ){    if ( InitGL() )    {    }}wxGL::~wxGL(){}void wxGL::OnEraseBackground(wxEraseEvent& WXUNUSED(event)){  // Do nothing, to avoid flashing.}void wxGL::OnSize(wxSizeEvent& event){    event.Skip();    ResizeGL();}void wxGL::OnPaint( wxPaintEvent& WXUNUSED(event) ){    wxPaintDC dc(this);    //RenderScene();}void wxGL::OnIdle(wxIdleEvent& event){    event.Skip();    RenderScene();    event.RequestMore();}void wxGL::OnFullScreen(wxCommandEvent& event){    fullscreen = event.IsChecked();}bool wxGL::InitGL(){    if (GetContext())    {   SetCurrent();   if (!LoadTextures()) // Jump To Texture Loading Routine ( NEW )   {  return false;    // If Texture Didn't Load Return FALSE   }   glEnable(GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )   glShadeModel(GL_SMOOTH); // Enable Smooth Shading   glClearColor(0.0f, 0.0f, 0.0f, 0.5f);// Black Background   glClearDepth(1.0f);// Depth Buffer Setup   glEnable(GL_DEPTH_TEST);// Enables Depth Testing   glDepthFunc(GL_LEQUAL);// The Type Of Depth Testing To Do   // Really Nice Perspective Calculations   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    }    ResizeGL();    return true;}void wxGL::ResizeGL(){    if (GetContext())    {   SetCurrent();   int w, h;   GetClientSize(&w, &h);   if (h==0) // Prevent A Divide By Zero By   {  h=1;// Making Height Equal One   }   glViewport(0,0,w,h);// Reset The Current Viewport   glMatrixMode(GL_PROJECTION);// Select The Projection Matrix   glLoadIdentity();// Reset The Projection Matrix   // Calculate The Aspect Ratio Of The Window   gluPerspective(45.0f,(GLfloat)w/(GLfloat)h,0.1f,100.0f);   glMatrixMode(GL_MODELVIEW);// Select The Modelview Matrix   glLoadIdentity();    }}void wxGL::RenderScene(){    if (!GetContext()) return;    SetCurrent();glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();// Reset The ViewglTranslatef(0.0f,0.0f,-5.0f);glRotatef(xrot,1.0f,0.0f,0.0f);glRotatef(yrot,0.0f,1.0f,0.0f);glRotatef(zrot,0.0f,0.0f,1.0f);glBindTexture(GL_TEXTURE_2D, texture[0]);glBegin(GL_QUADS);// Front FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);// Back FaceglTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);// Top FaceglTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);// Bottom FaceglTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);// Right faceglTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);// Left FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);glEnd();xrot+=0.3f;yrot+=0.2f;zrot+=0.4f;    glFlush();    SwapBuffers();}bool wxGL::LoadTextures(){    if (!image.LoadFile(wxT("test.png"),wxBITMAP_TYPE_ANY))   return false;    glGenTextures(1, &texture[0]);// Create The Texture    // Typical Texture Generation Using Data From The Bitmap    glBindTexture(GL_TEXTURE_2D, texture[0]);    glTexImage2D(GL_TEXTURE_2D, 0, 3, image.GetWidth(), image.GetHeight(),   0, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);}
  For the alpha, the problem is that you aren't enabling blending. You'll need to glEnable(GL_BLEND), and set the blend function glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).I'm not certain about the speed. You're not generating mipmaps (see gluBuild2DMipmaps), which may have an effect.You're also drawing whenever you're idle. Unless wx forces the GL to finish rendering after your code returns from the idle function, you may, depending upon your system configuration, get 'lag' when you do something like resize the window, switch to fullscreen or exit the program, as the GL 'catches up' with the rendering commands still pending before it can continue. This won't make your framerate low, but it would effect the interactivity of the application. If you do suffer from this problem, using glFinish after each frame will solve it.In either case, it's not obvious why this wouldn't also effect a BMP file, so there may be some more esoteric explanation.   ;  Thanks for your reply.I followed your instruction and added the following codes in InitGL() function:   glEnable(GL_BLEND);   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);But the result is the same. The white background is still showed. What's wrong with it?;  Don't expect the alpha channel to work if you explicitely tell OpenGL you don't want an alpha channel. Check this line.glTexImage2D(GL_TEXTURE_2D, 0, 3, image.GetWidth(), image.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());Having third parameter set to 3 is identical to GL_RGB, which in turn tells OpenGL you want a R, G anb B channel, but the A channel should not be present and that any attemp to read that texture should behave as if the alpha channel was set to 1. So the least you have to do to get the alpha channel to even enter the texture, you have to set the third parameter to GL_RGBA.Second, the third last parameter describes the color order of the source data being passed to OpenGL. If you pass GL_RGB, you tell OpenGL that there are only three channels present in the source data; R, G anb B, but no A. If the data you pass is actually RGBA, then you must pass GL_RGBA or OpenGL will interpret the data wrong.So the least you have to do to even get the alpha channel into the texture correctly is to pass GL_RGBA for third and third last parameter.   ;  Sorry. Actually it's my mistake. My original code is like:    glTexImage2D(GL_TEXTURE_2D, 0, 4, image.GetWidth(), image.GetHeight(),   0, GL_RGBA, GL_UNSIGNED_BYTE, image.GetData());But the display is just not correct. Is it possible because of my png file itself?  How can I verify my alpha channel is correct in my png file?;  If the original code doesn't look like the one you posted, then what you posted isn't the original one. Remember next time to post the correct code. The error did not come from when you pasted it here (like you copied GL_RGBA and pasted GL_RGB), it was in the code you copied so chances are you didn't copy the code you actually had problems with. The original code may be different in other, possibly important, places aswell. We need the correct code to assist you. Anyway, assuming there's nothing else that is different from the code you actually have problems with, did you check the texture dimensions? Unless you're on a new platform, power of two dimensions are a must.   ;  Sorry for my carelessness. Because I'm doing various testing for my code so I posted code from one of my testing.My png file is 96x96 so there should not be any texture dimension problem.   ;  As I said, it must be a POWER of two, 96 is MULTIPLE of two, but not a power of two. Powers of two are 2n for an integer n. That is, 32, 64, 128, 256 and some bigger and smaller values, but no more values between the ones i just presented.   ;Quote:Original post by frankmail007...My png file is 96x96 so there should not be any texture dimension problem.96 is a multiple of two but it is not a power of two.  A power of two satisfies the equation x = 2n, for some integer n.  The closest powers of two to 96 are 26 and 27, or 64 and 128 respectively.EDIT:  D'oh, too slow.   ;Quote:Original post by KalidorEDIT:  D'oh, too slow.But funny how we wrote pretty much the same thing. We both emphasized the multiple/power words, gave the 2n equation and the set of values for n, and gave some examples of powers around 96 [smile]   