objarni's picture

TexUtil update & demo

I finished the CreateTextureFromBitmap-method of my TexUtil class.

And made a small ugly demo with a bouncing ball, which uses the alpha channel of the .png picture to not-render the transparent parts of the 64x64 ball image.

Update: The two new APIs are CreateTextureFromBitmap and CreateTextureFromFile:

int CreateTextureFromBitmap(Bitmap);
int CreateTextureFromFile(string); // convenience function since loading a Bitmap was a mouthful
using OpenTK.Graphics;
using System.Diagnostics;
using System.Drawing;
using Img = System.Drawing.Imaging;
 
/// The methods in this namespace assume you are familiar with the follow
/// texture concepts of OpenGL:
/// * their integer names
/// * their sizes (power of 2)
/// * the currently bound texture
/// * how pixels are colored based on the texture fragment + the current color
/// * how alpha blending works
/// If you are feeling unsure on any of these concepts, do some googling!
namespace TexLib
{
  /// <summary>
  /// The TexUtil class is released under the MIT-license.
  /// /Olof Bjarnason
  /// </summary>
  public static class TexUtil
  {
    #region Public
 
    /// <summary>
    /// Initialize OpenGL state to enable alpha-blended texturing.
    /// Disable again with GL.Disable(EnableCap.Texture2D).
    /// Call this before drawing any texture, when you boot your
    /// application, eg. in OnLoad() of GameWindow or Form_Load()
    /// if you're building a WinForm app.
    /// </summary>
    public static void InitTexturing()
    {
      GL.Disable(EnableCap.CullFace);
      GL.Enable(EnableCap.Texture2D);
      GL.Enable(EnableCap.Blend);
      GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
      GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
    }
 
    /// <summary>
    /// Create an opaque OpenGL texture object from a given byte-array of r,g,b-triplets.
    /// Make sure width and height is 1, 2, .., 32, 64, 128, 256 and so on in size since all
    /// 3d graphics cards support those dimensions. Not necessarily square. Don't forget
    /// to call GL.DeleteTexture(int) when you don't need the texture anymore (eg. when switching
    /// levels in your game).
    /// </summary>
    public static int CreateRGBTexture(int width, int height, byte[] rgb)
    {
      return CreateTexture(width, height, false, rgb);
    }
 
    /// <summary>
    /// Create a translucent OpenGL texture object from given byte-array of r,g,b,a-triplets.
    /// See CreateRGBTexture for more info.
    /// </summary>
    public static int CreateRGBATexture(int width, int height, byte[] rgba)
    {
      return CreateTexture(width, height, true, rgba);
    }
 
    /// <summary>
    /// Create an OpenGL texture (translucent or opaque) from a given Bitmap.
    /// 24- and 32-bit bitmaps supported.
    /// </summary>
    public static int CreateTextureFromBitmap(Bitmap bitmap)
    {
      Img.BitmapData data = bitmap.LockBits(
        new Rectangle(0, 0, bitmap.Width, bitmap.Height),
        Img.ImageLockMode.ReadOnly,
        Img.PixelFormat.Format32bppArgb);
      var tex = GiveMeATexture();
      GL.BindTexture(TextureTarget.Texture2D, tex);
      GL.TexImage2D(
        TextureTarget.Texture2D,
        0,
        PixelInternalFormat.Rgba,
        data.Width, data.Height,
        0,
        PixelFormat.Bgra,
        PixelType.UnsignedByte,
        data.Scan0);
      bitmap.UnlockBits(data);
      SetParameters();
      return tex;
    }
 
    /// <summary>
    /// Create an OpenGL texture (translucent or opaque) by loading a bitmap
    /// from file. 24- and 32-bit bitmaps supported.
    /// </summary>
    public static int CreateTextureFromFile(string path)
    {
      return CreateTextureFromBitmap(new Bitmap(Bitmap.FromFile(path));
    }
 
    #endregion
 
    private static int CreateTexture(int width, int height, bool alpha, byte[] bytes)
    {
      int expectedBytes = width * height * (alpha ? 4 : 3);
      Debug.Assert(expectedBytes == bytes.Length);
      int tex = GiveMeATexture();
      Upload(width, height, alpha, bytes);
      SetParameters();
      return tex;
    }
 
    private static int GiveMeATexture()
    {
      int tex = GL.GenTexture();
      GL.BindTexture(TextureTarget.Texture2D, tex);
      return tex;
    }
 
    private static void SetParameters()
    {
      GL.TexParameter(
        TextureTarget.Texture2D,
        TextureParameterName.TextureMinFilter,
        (int)TextureMinFilter.Nearest);
      GL.TexParameter(TextureTarget.Texture2D,
        TextureParameterName.TextureMagFilter,
        (int)TextureMagFilter.Nearest);
    }
 
    private static void Upload(int width, int height, bool alpha, byte[] bytes)
    {
      var internalFormat = alpha ? PixelInternalFormat.Rgba : PixelInternalFormat.Rgb;
      var format = alpha ? PixelFormat.Rgba : PixelFormat.Rgb;
      GL.TexImage2D<byte>(
        TextureTarget.Texture2D,
        0,
        internalFormat,
        width, height,
        0,
        format,
        PixelType.UnsignedByte,
        bytes);
    }
  }
}
Images

Comments

Comment viewing options

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

Attached is the ball.png image.

AttachmentSize
ball.png7.19 KB
triton's picture

Very handy. I think I'm gonna steal this class. :D

objarni's picture

Please go ahead :)

CheatCat's picture

Well... How I use it? xD
I load the image with CreateTextureFromFile(), right? But how to position the image in the window?

objarni's picture

The easiest way to get started is start reading Nehe tutorials.

CheatCat's picture

Okey, thank you!

mooglegiant's picture

you think you can post a full demo showing this off?

Thanks

triton's picture

I think I didn't tell you before that I used this code in my game. Thanks, it was useful. :)

(btw: I credited you in the README, in case you care :D)

objarni's picture

triton: cool, and thanks for the credit!

Maybe I should put the "TexLib" source at Launchpad thus opensourcing it..? Together with a GameWindow-based example showing how to use it.

triton's picture

Maybe there could be a section in the OpenTK website (maybe there already is, dunno) with a collection of big examples (for example, games) and utility libraries.

That could be useful for people starting out with OpenTK.