[OpenGL 1.X] Drawing 2D Texture with custom Transparency

Good morning.

I am an ex XNA developer and i start to migrate to OpenGL 1.X to begin.

My goal is to make a very simple 2D drawing library which could draw primitives (circles, boxes, lines) and texture. with parametrized alpha value and color.

I use C# language and OpenGL wrapper called TAO which provide me 1-1 mapping to OpenGL functions.

I have some problems on displaying a texture with both invisible part (it’s some background not to be drawn) and a custom transparency value.

I have a second problem which is (i think) is linked to the first one : i could not change the color of primitives to be drawn, it always keep the same value.

This is my code below :

First i used a class called Texture containing some information for my 2d resource :



    public sealed class Texture
    {
        #region Fields

        private Color _alphaColor;
        private int _width;
        private int _height;
        private int _index;

        #endregion

        #region Properties

        public Color GetAlphaColor()
        {
            return _alphaColor;
        }

        public int GetWidth()
        {
            return _width;
        }

        public int GetHeight()
        {
            return _height;
        }

        public int GetIndex()
        {
            return _index;
        }

        #endregion

        #region Ctors

        public Texture(int width, int height, int index, ref Color alphaColor)
        {
            _alphaColor = alphaColor;
            _width = width;
            _height = height;
            _index = index;
        }

        #endregion
    }


I load my texture from my own type file containing the color of background, height, width and a bytes list figuring RGB datas.



 private static Texture LoadTexture(string path)
        {
            Texture surface;

            using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open)))
            {
                byte rValue = reader.ReadByte();
                byte gValue = reader.ReadByte();
                byte bValue = reader.ReadByte();

                Color alphaColor = Color.FromArgb(rValue, gValue, bValue);

                int width = reader.ReadInt32();
                int height = reader.ReadInt32();

                int colorCount = reader.ReadInt32() / 3;

                byte[] bytes = new byte[colorCount * 4];
                int indexBytes = 0, indexColor;

                byte aValue;

                for (indexColor = 0; indexColor < colorCount; ++indexColor)
                {
                    bValue = reader.ReadByte();
                    gValue = reader.ReadByte();
                    rValue = reader.ReadByte();

                    aValue = 255;

                    if (rValue == alphaColor.R && gValue == alphaColor.G && bValue == alphaColor.B)
                    {
                        aValue = 0;
                    }

                    bytes[indexBytes] = rValue; ++indexBytes;
                    bytes[indexBytes] = gValue; ++indexBytes;
                    bytes[indexBytes] = bValue; ++indexBytes;
                    bytes[indexBytes] = aValue; ++indexBytes;
                }

                reader.Close();

                Gl.glBindTexture(Gl.GL_TEXTURE_2D, _textureIds[0]);

                Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
                Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);

                Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, 4, width, height, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, bytes);

                surface = new Texture(width, height, _textureIds[0], ref alphaColor);
            }

            return surface;
        }


In initialization process i used a PIXELFORMATDESCRIPTOR with default values :



Gdi.PIXELFORMATDESCRIPTOR pfd = new Gdi.PIXELFORMATDESCRIPTOR();    
pfd.nSize = (short)Marshal.SizeOf(pfd);                             
pfd.nVersion = 1;                                                   
pfd.dwFlags = Gdi.PFD_DRAW_TO_WINDOW |    Gdi.PFD_SUPPORT_OPENGL |   Gdi.PFD_DOUBLEBUFFER;                                           
pfd.iPixelType = (byte)Gdi.PFD_TYPE_RGBA;                           
pfd.cColorBits = (byte)bits;                                        
pfd.cRedBits = 0;                                                  
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0;                                               
pfd.cAlphaShift = 0;                                                
pfd.cAccumBits = 0;                                                 
pfd.cAccumRedBits = 0;                                              
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 16;                                                
pfd.cStencilBits = 0;                                               
pfd.cAuxBuffers = 0;                                                
pfd.iLayerType = (byte)Gdi.PFD_MAIN_PLANE;                          
pfd.bReserved = 0;                                                 
pfd.dwLayerMask = 0;                                                
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;


I initialize OpenGl wuth those flags.



 public static bool InitGL()
        {            
            Gl.glClearColor(0, 0, 0, 1);
            Gl.glGenTextures(1, _textureIds);

            _currentTexture = LoadTexture("A.pof");
                        
            Gl.glEnable(Gl.GL_TEXTURE_2D);
            
            Gl.glDisable(Gl.GL_DEPTH_TEST);
            Gl.glDisable(Gl.GL_LIGHTING);
            Gl.glDisable(Gl.GL_DITHER);

            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
            Gl.glOrtho(0, 640, 480, 0, 0, 1);
            Gl.glMatrixMode(Gl.GL_MODELVIEW);

            Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_TEXTURE_ENV_MODE, Gl.GL_REPLACE);

            return true;
        }


Here come my drawing primitives :



 public static void DrawPoint(int x, int y, Color color)
        {
            Gl.glColor3b(color.R, color.G, color.B);

            Gl.glBegin(Gl.GL_POINTS);

            Gl.glVertex2i(x, y);

            Gl.glEnd();
        }

        public static void DrawLine(Point p1, Point p2, Color color)
        {
            Gl.glColor4b(color.R, color.G, color.B, 255);

            Gl.glBegin(Gl.GL_LINES);

            Gl.glVertex2i(p1.X, p1.Y);
            Gl.glVertex2i(p2.X, p2.Y);

            Gl.glEnd();
        }

        public static void DrawFilledRectangle(Rectangle rectangle, Color color, byte alpha)
        {
            int tempX = rectangle.X + rectangle.Width, tempY = rectangle.Y + rectangle.Height;

           
            Gl.glBegin(Gl.GL_QUADS);

            Gl.glColor4b(color.R, color.G, color.B, alpha);

            Gl.glVertex2i(rectangle.X, rectangle.Y);
            Gl.glVertex2i(tempX, rectangle.Y);
            Gl.glVertex2i(tempX, tempY);
            Gl.glVertex2i(rectangle.X, tempY);

            Gl.glEnd();
        }

        public static void DrawRectangle(Rectangle rectangle, Color color)
        {
            int tempX = rectangle.X + rectangle.Width, tempY = rectangle.Y + rectangle.Height;

            Gl.glColor4b(color.R, color.G, color.B, 255);

            Gl.glBegin(Gl.GL_LINE_LOOP);
            
            Gl.glVertex2i(rectangle.X, rectangle.Y);
            Gl.glVertex2i(tempX, rectangle.Y);
            Gl.glVertex2i(tempX, tempY);
            Gl.glVertex2i(rectangle.X, tempY);

            Gl.glEnd();
        }



Now my texture drawing function :



 public static void DrawTexture(Texture texture, Point point, byte alpha)
        {
            Gl.glEnable(Gl.GL_ALPHA_TEST);
            Gl.glAlphaFunc(Gl.GL_GREATER, 0);

            Gl.glEnable(Gl.GL_BLEND);
            
            Gl.glColor4b(255, 255, 255, alpha);
            
            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
           
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture.GetIndex());
                                    
            Gl.glBegin(Gl.GL_QUADS);

            Gl.glTexCoord2d(0, 0);
            Gl.glVertex2i(point.X, point.Y);

            Gl.glTexCoord2d(1, 0);
            Gl.glVertex2i(point.X + texture.GetWidth(), point.Y);

            Gl.glTexCoord2d(1, 1);
            Gl.glVertex2i(point.X + texture.GetWidth(), point.Y + texture.GetHeight());

            Gl.glTexCoord2d(0, 1);
            Gl.glVertex2i(point.X, point.Y + texture.GetHeight());

            Gl.glEnd();

            Gl.glDisable(Gl.GL_ALPHA_TEST);
            Gl.glDisable(Gl.GL_BLEND);
        }


I use this function to call drawings :



public static bool DrawGLScene()
        {
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            
            Point p1 = new Point(0, 0);
            Point p2 = new Point(30, 200);
            
            DrawTexture(_currentTexture, p1, 255);

            DrawTexture(_currentTexture, p2, 64);

            DrawRectangle(new Rectangle(0, 0, 50, 60), Color.White);
            DrawFilledRectangle(new Rectangle(0, 0, 50, 60), Color.Blue, 255);

            DrawLine(p1, p2, Color.Blue);

            DrawPoint(p2.X, p2.Y, Color.White);
            
            return true;
        }


But the second drawing texture 'DrawTexture(_currentTexture, p2, 64):wink: is not transparent …