First off is just the prefix, Loading a texture in its simplest form.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | private Bitmap texture_source; private int texture; protected override void OnLoad(EventArgs e) { base.OnLoad(e); GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); //Load texture from file texture_source = new Bitmap("texture.png"); //Generate empty texture texture = GL.GenTexture(); //Link empty texture to texture2d GL.BindTexture(TextureTarget.Texture2D, texture); //Must be set else the texture will show glColor GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); //Describe to gl what we want the bound texture to look like GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texture_source.Width, texture_source.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero); //Lock pixel data to memory and prepare for pass through System.Drawing.Imaging.BitmapData bitmap_data = texture_source.LockBits(new Rectangle(0, 0, texture_source.Width, texture_source.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); //Tell gl to write the data from are bitmap image/data to the bound texture GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture_source.Width, texture_source.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bitmap_data.Scan0); //Release from memory texture_source.UnlockBits(bitmap_data); //Release texture GL.BindTexture(TextureTarget.Texture2D, 0); //Enable textures from texture2d target GL.Enable(EnableCap.Texture2D); } |
Method
For convenience
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | private int LoadTexture(string path, int quality = 0, bool repeat = true, bool flip_y = false) { Bitmap bitmap = new Bitmap(path); //Flip the image if (flip_y) bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); //Generate a new texture target in gl int texture = GL.GenTexture(); //Will bind the texture newly/empty created with GL.GenTexture //All gl texture methods targeting Texture2D will relate to this texture GL.BindTexture(TextureTarget.Texture2D, texture); //The reason why your texture will show up glColor without setting these parameters is actually //TextureMinFilters fault as its default is NearestMipmapLinear but we have not established mipmapping //We are only using one texture at the moment since mipmapping is a collection of textures pre filtered //I'm assuming it stops after not having a collection to check. switch (quality) { case 0: default://Low quality GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); break; case 1://High quality //This is in my opinion the best since it doesnt average the result and not blurred to shit //but most consider this low quality... GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Nearest); break; } if (repeat) { //This will repeat the texture past its bounds set by TexImage2D GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Repeat); } else { //This will clamp the texture to the edge, so manipulation will result in skewing //It can also be useful for getting rid of repeating texture bits at the borders GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); } //Creates a definition of a texture object in opengl /* Parameters * Target - Since we are using a 2D image we specify the target Texture2D * MipMap Count / LOD - 0 as we are not using mipmapping at the moment * InternalFormat - The format of the gl texture, Rgba is a base format it works all around * Width; * Height; * Border - must be 0; * * Format - this is the images format not gl's the format Bgra i believe is only language specific * C# uses little-endian so you have ARGB on the image A 24 R 16 G 8 B, B is the lowest * So it gets counted first, as with a language like Java it would be PixelFormat.Rgba * since Java is big-endian default meaning A is counted first. * but i could be wrong here it could be cpu specific :P * * PixelType - The type we are using, eh in short UnsignedByte will just fill each 8 bit till the pixelformat is full * (don't quote me on that...) * you can be more specific and say for are RGBA to little-endian BGRA -> PixelType.UnsignedInt8888Reversed * this will mimic are 32bit uint in little-endian. * * Data - No data at the moment it will be written with TexSubImage2D */ GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bitmap.Width, bitmap.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero); //Load the data from are loaded image into virtual memory so it can be read at runtime System.Drawing.Imaging.BitmapData bitmap_data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); //Writes data to are texture target /* Target; * MipMap; * X Offset - Offset of the data on the x axis * Y Offset - Offset of the data on the y axis * Width; * Height; * Format; * Type; * Data - Now we have data from the loaded bitmap image we can load it into are texture data */ GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bitmap.Width, bitmap.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bitmap_data.Scan0); //Release from memory bitmap.UnlockBits(bitmap_data); //get rid of bitmap object its no longer needed in this method bitmap.Dispose(); /*Binding to 0 is telling gl to use the default or null texture target *This is useful to remember as you may forget that a texture is targeted *And may overflow to functions that you dont necessarily want to *Say you bind a texture * * Bind(Texture); * DrawObject1(); * <-- Insert Bind(NewTexture) or Bind(0) * DrawObject2(); * * Object2 will use Texture if not set to 0 or another. */ GL.BindTexture(TextureTarget.Texture2D, 0); return texture; } |
Usage Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | private int current_texture; protected override void OnLoad(EventArgs e) { base.OnLoad(e); GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); current_texture = LoadTexture("texture.png", 1); GL.Enable(EnableCap.Texture2D); //Basically enables the alpha channel to be used in the color buffer GL.Enable(EnableCap.Blend); //The operation/order to blend GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); //Use for pixel depth comparing before storing in the depth buffer GL.Enable(EnableCap.DepthTest); } protected override void OnRenderFrame(FrameEventArgs e) { base.OnRenderFrame(e); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); GL.PushMatrix(); GL.Translate(0, 0, -5); GL.Color4(Color.White); GL.BindTexture(TextureTarget.Texture2D, current_texture); GL.Begin(BeginMode.Quads); //Bind texture coordinates to vertices in ccw order //Top-Right GL.TexCoord2(1.0f, 0.0f); GL.Vertex2(1.0f, 1.0f); //Top-Left GL.TexCoord2(0f, 0f); GL.Vertex2(-1.0f, 1.0f); //Bottom-Left GL.TexCoord2(0f, 1f); GL.Vertex2(-1.0f, -1.0f); //Bottom-Right GL.TexCoord2(1f, 1f); GL.Vertex2(1.0f, -1.0f); GL.End(); GL.BindTexture(TextureTarget.Texture2D, 0); GL.PopMatrix(); SwapBuffers(); } |