namespace TheLabs; using OpenTK.Graphics.OpenGL4; using StbImageSharp; using System.IO; public class Texture : IDisposable { public readonly int Handle; public Texture(string path) { // Generate the handle Handle = GL.GenTexture(); // Bind the texture so we can configure it GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, Handle); // --- Set texture parameters --- // Repeat the texture if UVs go outside [0, 1] GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); // Set filter for shrinking (mipmap) and stretching (linear) GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); // --- Load and upload the image data --- StbImage.stbi_set_flip_vertically_on_load(1); // Load the image from disk using (var stream = File.OpenRead(path)) { ImageResult image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha); // Upload data to the GPU GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, image.Data); } // Generate mipmaps for better quality shrinking GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); // Unbind the texture GL.BindTexture(TextureTarget.Texture2D, 0); } // A simple method to bind the texture to a specific unit public void Use(TextureUnit unit = TextureUnit.Texture0) { GL.ActiveTexture(unit); GL.BindTexture(TextureTarget.Texture2D, Handle); } public void Dispose() { GL.DeleteTexture(Handle); } }