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) is not transparent …