nlraley's picture

Texture not displaying...

Hello, I'm new to the OpenTK and OpenGL as a whole and I am trying a simple windows forms application using C#.

I currently have a form with a GLControl located on it.

I am trying to load a png file as a Bitmap and display it on the control. Sounds simple enough, but I nothing is displaying.

I walked through the Clear and the sections on drawing triangles and everything was rendering fine with those, any idea what I'm missing?

On my Paint method of my GLControl I am performing the following:

 private void glControl1_Paint(object sender, PaintEventArgs e)
{
	if (!loaded)
		return;
 
	GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
	GL.Enable(EnableCap.Texture2D);
 
	int texture =  GL.GenTexture();
	GL.BindTexture(TextureTarget.Texture2D, texture);
 
	Bitmap bmp = new Bitmap("C:\\Program Files (x86)\\EMTRAC Systems\\EMTRAC Maps\\OSM\\18\\101725\\42185.png");
	BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 
	GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmpData.Width, bmpData.Height, 0,
		OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0);            
 
	bmp.UnlockBits(bmpData);
 
	GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
	GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
 
	GL.BindTexture(TextureTarget.Texture2D, texture);
 
	glControl1.SwapBuffers();
}

What am I missing? I have checked and I am getting the appropriate BitmapData. Any ideas?


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Violet_CLM's picture

It looks like you are loading the texture but not including any code for drawing it to the GLControl. Look up the GL.Begin() and GL.End() functions.

nlraley's picture

So, I basically have to do a:
GL.Begin(BeginMode.Quads);

After I have finished copying the Bitmap into the GL memory and then create a quad, with the vertices being where I want the texture to be displayed on the control? I'm going to have to do this for each and every texture I want to load as my background? For a single texture it would look like so:

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
            GL.Enable(EnableCap.Texture2D);
            GL.Enable(EnableCap.Blend);
 
            GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
 
            GL.GenTextures(1, out texture);
            GL.BindTexture(TextureTarget.Texture2D, texture);
 
            Bitmap bmp = new Bitmap(Bitmap.FromFile("C:\\Program Files (x86)\\EMTRAC Systems\\EMTRAC Maps\\OSM\\18\\101725\\42185.png"));
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 
            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, bmpData.Width, bmpData.Height, 0,
                OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0);
            GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
 
            bmp.UnlockBits(bmpData);
            bmp.Dispose();
 
            GL.Begin(BeginMode.Quads);
 
            GL.TexCoord2(0, 0); GL.Vertex2(0, 0);
            GL.TexCoord2(1, 0); GL.Vertex2(256, 0);
            GL.TexCoord2(1, 1); GL.Vertex2(256, 256);
            GL.TexCoord2(0, 1); GL.Vertex2(0, 256);
 
            GL.End();
            GL.Flush();
 
            glControl1.SwapBuffers();

I'm porting a DirectX application I wrote last year to OpenGL. I had previously accomplished this with their sprite class, and therefore didn't have to go and designate each quad individually. I don't suppose OpenGL supports anything like the DirectX sprite class does it?

What I am trying to do is on the startup, preload several textures even though some may not be in view, then only draw the ones that are in the viewport. I want to do this to avoid the time it takes to create each texture whenever I would want to display a different set of textures for my background. I'm not sure what each step is actually doing.

If I create a Texture class, I could have a constructor like so:

public Texture(string filename)
        {
            GLTexture = GL.GenTexture();
            GL.BindTexture(TextureTarget.Texture2D, GLTexture);
 
            Bitmap bmp = new Bitmap(Bitmap.FromFile(filename));
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmpData.Width, bmpData.Height, 0,
                OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0);
            GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
 
            bmp.UnlockBits(bmpData);
            bmp.Dispose();
        }

For each texutre I need I'd create a Texture object. It was my understanding that all of this pushes it to the OpenGl memory, and my GLTexture would hold a pointer so that GL knows which texture is which? How would I call this texture at a later time when I am drawing my quads for the textures that need to be loaded? Is it as simple as calling the
GL.BindTexture(TextureTarget.Texture2D, Texture.texture)
For the Texture object?

the Fiddler's picture

3d hardware doesn't support displaying bitmaps directly. The sprite class in DirectX is actually a shortcut to drawing a textured quad (AFAIK this isn't part of the D3D API but it comes with the D3DX library).

OpenGL doesn't offer anything equivalent out of the box but, fortunately, this is quite simple to implement in a generic fashion.

Quote:

For each texutre I need I'd create a Texture object. It was my understanding that all of this pushes it to the OpenGl memory, and my GLTexture would hold a pointer so that GL knows which texture is which? How would I call this texture at a later time when I am drawing my quads for the textures that need to be loaded? Is it as simple as calling the
GL.BindTexture(TextureTarget.Texture2D, Texture.texture)
For the Texture object?

Pretty much. The simple approach (call GL.BindTexture(), draw a quad, repeat as necessary) will work perfectly fine for hundreds or thousands of sprites, depending on the hardware.

I wouldn't worry about this at first, but you can improve performance by sorting sprites by texture ids (i.e. draw all sprites with the same texture at once). Sprite sheets can also help significantly (i.e. load multiple sprites into a single texture, in order to minimize the amount GL.BindTexture() calls) and display lists / VBOs can reduce CPU load over GL.Vertex3 et al.

Violet_CLM's picture

Remember the most vital bit of information you want to get out of creating a texture is the Int that can be used for GL.BindTexture(). That hypothetical Texture class would be all right if you want to be able to access other properties of each texture individually, like width and height, but if you already know what the textures will be and won't need to access that kind of information, TexLib will simplify your life.

nlraley's picture

Thanks for the help and the point in the right direction. I thought that was how it was being handled but didn't find any documentation stating that for a fact.

I now have the application up and running and displaying all the textures just fine.

Next step will be doing polygons and polylines, which should be substantially easier as well as non background textures.

I assume that for a non background sprite we would use the transparency and set the transparency of the Bitmap after you have loaded it?