Draw text using OpenTK - c#

I'm going crazy trying to draw some text over an OpenGL window using OpenTK!
I followed some of the tutorials around but I can't make it work, when I enable the texture where the text is drawn, then I just have a white window and the QUAD I'm drawing for test just disappears.
If someone has the time to check the code, it is below. I can also send my test program to check it out faster. Thanks in advance for any help on this.
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using OpenTK.Graphics.OpenGL;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Bitmap textBmp;
int textTexture = -1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (!glControl1.Context.IsCurrent)
{
glControl1.MakeCurrent();
}
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, glControl1.Width, 0, glControl1.Height, -1000, 1000);
GL.Scale(1, 1, 1);
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
GL.ClearColor(Color.White);
// Better point and line drawing
GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest);
GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest);
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
GL.Enable(EnableCap.PointSmooth);
GL.Enable(EnableCap.LineSmooth);
GL.Enable(EnableCap.Blend);
// Hide stuff behind in 3D
GL.Enable(EnableCap.DepthTest);
// Enable the texture
GL.Enable(EnableCap.Texture2D);
// Create Bitmap and OpenGL texture
textBmp = new Bitmap((int)glControl1.Width, (int)glControl1.Height);
textTexture = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, textTexture);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, textBmp.Width, textBmp.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
ErrorCode errorCode = GL.GetError();
Debug.Assert(errorCode == ErrorCode.NoError, "OpenTK error!");
}
private void glControl1_Paint(object sender, PaintEventArgs e)
{
ErrorCode errorCode;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
GL.PushMatrix();
GL.Color3(Color.Black);
GL.Begin(PrimitiveType.Quads);
GL.Vertex3(10, 10, 10);
GL.Vertex3(40, 10, 10);
GL.Vertex3(40, 50, 10);
GL.Vertex3(10, 50, 10);
GL.End();
if (textBmp != null)
{
using (Graphics gfx = Graphics.FromImage(textBmp))
{
gfx.Clear(Color.Transparent);
gfx.DrawString("text", new Font("Arial", 10), Brushes.Black, new PointF(textBmp.Width / 2, textBmp.Height));
}
BitmapData data = textBmp.LockBits(new Rectangle(0, 0, textBmp.Width, textBmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)glControl1.Width, (int)glControl1.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
textBmp.UnlockBits(data);
errorCode = GL.GetError();
Debug.Assert(errorCode == ErrorCode.NoError, "OpenTK error!");
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0f, 1f); GL.Vertex2(0f, 0f);
GL.TexCoord2(1f, 1f); GL.Vertex2(1f, 0f);
GL.TexCoord2(1f, 0f); GL.Vertex2(1f, 1f);
GL.TexCoord2(0f, 0f); GL.Vertex2(0f, 1f);
GL.End();
}
errorCode = GL.GetError();
Debug.Assert(errorCode == ErrorCode.NoError, "OpenTK error!");
glControl1.SwapBuffers();
}
}
}

Ok, I finally managed to make it work.
On initialization I just did:
if (!control.Context.IsCurrent)
{
control.MakeCurrent();
}
GL.Ortho(0, controlWidth, 0, controlHeight, -1000, 1000);
GL.Scale(1, -1, 1); // I work with a top/left image and openGL is bottom/left
GL.Viewport(0, 0, controlWidth, controlHeight);
GL.ClearColor(Color.White);
GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest);
GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest);
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
GL.Enable(EnableCap.PointSmooth);
GL.Enable(EnableCap.LineSmooth);
GL.Enable(EnableCap.Blend);
GL.Enable(EnableCap.DepthTest);
GL.ShadeModel(ShadingModel.Smooth);
GL.Enable(EnableCap.AutoNormal);
bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
gfx = Graphics.FromImage(bmp);
gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
texture = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
Then to write text in the bitmap:
gfx.DrawString(text, font, brush, new PointF(x, y));
And to render:
if (!control.Context.IsCurrent)
{
control.MakeCurrent();
}
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Modelview);
GL.Enable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, Texture);
GL.Begin(PrimitiveType.Quads);
GL.TexCoord3(0.0f, 0.0f, 0f); GL.Vertex3(0f, 0f, 0f);
GL.TexCoord3(1.0f, 0.0f, 0f); GL.Vertex3(realWidth, 0f, 0f);
GL.TexCoord3(1.0f, 1.0f, 0f); GL.Vertex3(realWidth, realHeight, 0f);
GL.TexCoord3(0.0f, 1.0f, 0f); GL.Vertex3(0f, realHeight, 0f);
GL.End();
GL.Disable(EnableCap.Texture2D);
control.SwapBuffers();
That did the trick.
Very important (at least I think it is):
- the GL.Enable(EnableCap.Texture2D) just before rendering the quad with the texture and GL.Disable(EnableCap.Texture2D) afterwords.
- the GL.BindTexture(TextureTarget.Texture2D, Texture) after enabling GL.Enable(EnableCap.Texture2D).
Hope this helps someone. If I manage to have some time I'll make a C# class with it and post it here.

Related

OpenCV webcam frames to OpenGL texture

I am working on C# and using OpenTK(OpenGL wrapper) and EmguCV(OpenCV wrapper).
What I want to do is easy to understand: Grab the webcam video stream and put it on a GLControl.
I have a static class called Capturer which has a method that captures a frame and returns it as a cv::Mat wrapped object:
internal static void Initialize()
{
cap = new VideoCapture(1);
cap.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps, 25);
cap.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 1920);
cap.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 1080);
}
internal static Mat GetCurrentFrame()
{
mat = cap.QueryFrame();
if (!mat.IsEmpty)
{
return mat;
}
return null;
}
Now in my GLControl Load event I initialize the capturer and OpenGL:
Capturer.Initialize();
GL.ClearColor(Color.Blue);
GL.Enable(EnableCap.Texture2D);
GL.Viewport(-glControl1.Width, -glControl1.Height, glControl1.Width * 2, glControl1.Height * 2);
And finally, in the GLControl Paint event:
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
Mat m = Capturer.GetCurrentFrame();
if (m != null)
{
GL.GenTextures(1, out textureId);
GL.BindTexture(TextureTarget.Texture2D, this.textureId);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (float)TextureWrapMode.Clamp);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (float)TextureWrapMode.Clamp);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, 1920, 1080, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgr, PixelType.UnsignedByte, m.DataPointer);
}
m.Dispose();
glControl1.SwapBuffers();
glControl1.Invalidate();
This is showing a full Blue screen. I think the error is on m.DataPointer.
(I have tried rendering the frames with Bitmap using the property m.Bitmapand it works but the performance is so bad.)
Drawing a rectangle bounding the GLControl solved it:
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0, 0); GL.Vertex2(0, 0);
GL.TexCoord2(0, 1); GL.Vertex2(0, 1);
GL.TexCoord2(1, 1); GL.Vertex2(1, 1);
GL.TexCoord2(1, 0); GL.Vertex2(1, 0);
GL.End();
m.Dispose();
Be sure to dispose the object after drawing the frame so you will not run out of memory.

Setting up OpenGL camera

I'm having trouble setting up my camera in 3D space.
Here's my code:
private void SetupViewPort()
{
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, 1000,0,1000, 0, 1);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
Vector3d eyePos = new Vector3d(0, 0, 1);
Vector3d point = new Vector3d(500, 500, 0.01);
Vector3d up = new Vector3d(0, 0 , 1);
Matrix4d mat = Matrix4d.LookAt(eyePos, point, up);
//mat.Invert();
GL.LoadMatrix(ref mat);
}
I'm expecting to see shapes that I've drawn onto the 2D plane. But I get a blank screen every time.
Here's the code where my shapes are drawn:
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!loaded)
return;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.DepthTest);
GL.DepthMask(true);
GL.ClearDepth(1.0);
GL.Color3(Color.Yellow);
GL.Begin(PrimitiveType.Triangles);
GL.Vertex2(0, 0);
GL.Vertex2(0, 600);
GL.Vertex2(600, 600);
GL.Vertex2(100, 100);
GL.Vertex2(50, 70);
GL.Vertex2(200, 100);
GL.End();
glControl1.SwapBuffers();
}
An orthonormal projection matrix and a lookAt view matrix don't play well together. Since you are drawing 2D just leave the lookAt matrix out and use the identity matrix.

Rendering triangles with OpenTK from VBO

I cannot render triangles for the life of me with a VBO in OpenTK. I am loading my data to the VBO in glControl_Load() event. I get a background screen with no triangles when running. The data is a from a mesh m.OpenGLArrays(out data, out indices) outputs a list of floats and ints. The list of floats for the vertices T1v1, T1v2, T1v3, T2v1, T2v2, T2v3, .... , all three vertices for each triangle back to back.
However given a blank screen with the code when I comment the "intermediate" rendering code everything renders fine....??? What am I doing wrong?
private void glControl_Load(object sender, EventArgs e)
{
loaded = true;
glControl.MouseMove += new MouseEventHandler(glControl_MouseMove);
glControl.MouseWheel += new MouseEventHandler(glControl_MouseWheel);
GL.ClearColor(Color.DarkSlateGray);
GL.Color3(1f, 1f, 1f);
m.OpenGLArrays(out data, out indices);
this.indicesSize = (uint)indices.Length;
GL.GenBuffers(1, out VBOid[0]);
GL.GenBuffers(1, out VBOid[1]);
SetupViewport();
}
private void SetupViewport()
{
if (this.WindowState == FormWindowState.Minimized) return;
glControl.Width = this.Width - 32;
glControl.Height = this.Height - 80;
Frame_label.Location = new System.Drawing.Point(glControl.Width / 2, glControl.Height + 25);
GL.MatrixMode(MatrixMode.Projection);
//GL.LoadIdentity();
GL.Ortho(0, glControl.Width, 0, glControl.Height, -1, 1); // Bottom-left corner pixel has coordinate (0, 0)
GL.Viewport(0, 0, glControl.Width, glControl.Height); // Use all of the glControl painting area
GL.Enable(EnableCap.DepthTest);
GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[0]);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(data.Length * sizeof(float)), data, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
float aspect_ratio = this.Width / (float)this.Height;
projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect_ratio, 1, 1024);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref projection);
}
private void glControl_Paint(object sender, PaintEventArgs e)
{
if (loaded)
{
GL.Clear(ClearBufferMask.ColorBufferBit |
ClearBufferMask.DepthBufferBit |
ClearBufferMask.StencilBufferBit);
modelview = Matrix4.LookAt(0f, 0f, -200f + zoomFactor, 0, 0, 0, 0.0f, 1.0f, 0.0f);
var aspect_ratio = Width / (float)Height;
projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect_ratio, 1, 512);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref projection);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref modelview);
GL.Rotate(angleY, 1.0f, 0, 0);
GL.Rotate(angleX, 0, 1.0f, 0);
GL.EnableClientState(ArrayCap.VertexArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[0]);
GL.Color3(Color.Yellow);
GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
GL.DrawArrays(PrimitiveType.Triangles, 0, data.Length);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.DisableClientState(ArrayCap.VertexArray);
//GL.Color3(Color.Yellow);
//GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
//GL.Begin(PrimitiveType.Triangles);
//for (int i = 0; i < this.md.mesh.Count; i++)
//{
// GL.Normal3(this.md.mesh[i].normal);
// GL.Vertex3(this.md.mesh[i].vertices[0]);
// GL.Vertex3(this.md.mesh[i].vertices[1]);
// GL.Vertex3(this.md.mesh[i].vertices[2]);
//}
//GL.End();
//GL.EndList();
glControl.SwapBuffers();
Frame_label.Text = "Frame: " + frameNum++;
}
}
If something doesn't seem right, then it probably isn't. I seriously questioned my understanding of opengl and spent hours looking at this. However it was just a simple error of forgetting to iterate a count variable in a for loop to transfer the mesh from one object to another. Each triangle had identical vertices! Always expect the unexpected when it comes to debugging!

Beginner troubles with 2D projection and textures in OpenGL

Lately I have been trying to learn/use OpenGL 3+. I have looked through tutorials and examples but I've run into a wall trying to get textures and 2D projection to work without problems.
The goal for now is to have a function which can draw a textured quad to the screen with it's position specified by pixels (not [-1,1]).
For readability and testing I made a new barebones program with the knowledge I currently have, and it exhibits nearly the same problems. Help would be appreciated since i'm starting to go bald over this :(..
The current code shows a garbled texture instead of the image itself (texture is 128x128px).
[Program.cs]
namespace OpenGLTester
{
static class Program
{
public static GameWindow window;
public static String programDirectory = Directory.GetCurrentDirectory();
public static int testTexture;
public static int uniform_fragment_texture;
public static int shaderProgram;
[STAThread]
static void Main()
{
window = new GameWindow(1024, 768, new GraphicsMode(new ColorFormat(8, 8, 8, 8), 0, 8), "OpenGLTester", GameWindowFlags.Default, DisplayDevice.Default, 3, 1, GraphicsContextFlags.Default);
GL.Viewport(new Size(1024,768));
shaderProgram = GL.CreateProgram();
int vertexShader = GL.CreateShader(ShaderType.VertexShader);
int fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(vertexShader, File.ReadAllText(programDirectory + #"\vertex.vert"));
GL.ShaderSource(fragmentShader, File.ReadAllText(programDirectory + #"\fragment.frag"));
GL.CompileShader(vertexShader);
GL.CompileShader(fragmentShader);
GL.AttachShader(shaderProgram, vertexShader);
GL.AttachShader(shaderProgram, fragmentShader);
GL.LinkProgram(shaderProgram);
if (GL.GetError() != ErrorCode.NoError) { System.Diagnostics.Debugger.Break(); }
Console.WriteLine(GL.GetProgramInfoLog(shaderProgram));
GL.UseProgram(shaderProgram);
Matrix4 projectionMatrix = Matrix4.CreateOrthographic(1024, 768, 0, 1);
GL.UniformMatrix4(GL.GetUniformLocation(shaderProgram, "vertex_projection"), false, ref projectionMatrix);
uniform_fragment_texture = GL.GetUniformLocation(shaderProgram, "fragment_texture");
testTexture = loadTexture(programDirectory + #"\test.png");
GL.Disable(EnableCap.DepthTest);
GL.Disable(EnableCap.Lighting);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
window.UpdateFrame += window_UpdateFrame;
window.RenderFrame += window_RenderFrame;
window.Resize += window_Resize;
window.TargetRenderFrequency = 60;
window.Run();
}
static void window_Resize(object sender, EventArgs e)
{
//Don't allow resizing for now.
window.Size = new Size(1024, 768);
}
static void window_UpdateFrame(object sender, FrameEventArgs e)
{
ErrorCode currentError = GL.GetError();
if (currentError != ErrorCode.NoError)
{
Console.WriteLine(Enum.GetName(typeof(ErrorCode), currentError));
System.Diagnostics.Debugger.Break();
}
}
static void window_RenderFrame(object sender, FrameEventArgs e)
{
GL.ClearColor(0, 0, 0, 0);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.StencilBufferBit);
//test texture is 128x128pixels.
drawTexRect(100, 228, 100, 228, testTexture);
window.SwapBuffers();
}
static int loadTexture(String filePath)
{
GL.Enable(EnableCap.Texture2D);
int id = GL.GenTexture();
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, id);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBaseLevel, 0);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, 0);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
Bitmap bmp = new Bitmap(filePath);
BitmapData bmp_data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp_data.Width, bmp_data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, bmp_data.Scan0);
bmp.UnlockBits(bmp_data);
bmp.Dispose();
return id;
}
static void drawTexRect(float top, float bottom, float left, float right, int texture)
{
//topLeft,bottomLeft,bottomRight,topRight
float[] vertices = new float[] {
left, top, 0, 0,
left, bottom, 0, 1,
right, bottom, 1, 1,
right, top, 1, 0,
};
int buffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData<float>(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
//vec2 - screen position
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 4, 0);
//vec2 - texture coordinates
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 4, 2 * sizeof(float));
GL.Enable(EnableCap.Texture2D);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, texture);
GL.Uniform1(uniform_fragment_texture, 0);
GL.DrawArrays(PrimitiveType.Quads, 0, 4);
GL.DeleteBuffer(buffer);
}
}
}
[vertex.vert]
#version 330
in vec2 vertex_position;
in vec2 vertex_texturePosition;
uniform mat4 vertex_projection;
out vec2 fragment_texturePosition;
void main()
{
gl_Position = vec4(vertex_position,0.0,1.0) * vertex_projection;
fragment_texturePosition = vertex_texturePosition;
}
[fragment.frag]
#version 330
in vec2 fragment_texturePosition;
uniform sampler2D fragment_texture;
out vec4 output_color;
void main()
{
output_color = texture(fragment_texture,fragment_texturePosition);
}
After changes suggested by #j-p one problem remains:
After texture position change suggested by #j-p:
The projection is also wrong given the position i expect it to be 100 px from the left and 100 px from the top, don't see how i can fix this..
The stride parameter is in byte:
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 4 * sizeof(float), 0);
//vec2 - texture coordinates
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 4 * sizeof(float), 2 * sizeof(float));
Also,the corresponding opengl pixel format for windows argb bitmap is BGRA. (link)
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,**OpenTK.Graphics.OpenGL.PixelFormat.Bgra**, PixelType.UnsignedByte, data.Scan0);
And finally, your texture coordinates should be adjusted as follow:
float[] vertices = new float[] {
left, top, 0, 1,
left, bottom, 0, 0,
right, bottom, 1, 0,
right, top, 1, 1
};

OpenTK OpenGL texture not drawing

I am having issues drawing a texture onto my quad but it remains white. I have looked through a number of guides and I don't seem to be doing anything different from them.
To load the texture:
Bitmap bitmap = new Bitmap("Textures/Sprite_Can.png");
GL.GenTextures(1, out textureID);
GL.BindTexture(TextureTarget.Texture2D, textureID);
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
bitmap.UnlockBits(data);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
Setup and apply an orthographic projection:
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, control.Width, 0, control.Height, -1, 1);
GL.Viewport(0, 0, control.Width, control.Height);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.ClearColor(Color4.CornflowerBlue);
And finally the draw:
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.LoadIdentity();
GL.Translate(30, 30, 0);
GL.BindTexture(TextureTarget.Texture2D, textureID);
GL.Begin(BeginMode.Quads);
GL.TexCoord2(0, 0);
GL.Vertex2(-1 * width / 2, 1 * height / 2);
GL.TexCoord2(1, 0);
GL.Vertex2(1 * width / 2, 1 * height / 2);
GL.TexCoord2(1, 1);
GL.Vertex2(1 * width / 2, -1 * height / 2);
GL.TexCoord2(0, 1);
GL.Vertex2(-1 * width / 2, -1 * height / 2);
GL.End();
GL.Flush();
control.SwapBuffers();
So basically, the quad draws just fine. However, the texture is not rendered. As a result, all I have is just a white square.
In the fixed-function OpenGL pipeline, you must also Enable texture units before a texture bound to one will be applied to anything you draw.
The normal OpenGL API binding for this is glEnable (GL_TEXTURE_2D). The OpenTK equivalent would be: GL.Enable (EnableCap.Texture2D).

Categories

Resources