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.
the Fiddler's picture

Create Content -> Project and select Contributed/Example as project type.

objarni's picture

Thanks Fiddler! Didn't know it was so easy to add a project to OpenTK.com.

I've added the "Texture Utility Library" under contributed:

http://www.opentk.com/project/all