0
mirror of https://github.com/sampletext32/ParkanPlayground.git synced 2025-05-18 11:21:18 +03:00
ParkanPlayground/NResUI/OpenGlTexture.cs
bird_egop bba3f2a810 fix color ordering in 4444
fix blur when x2 scale
add TFNT texture open support
2024-11-23 01:32:12 +03:00

155 lines
6.2 KiB
C#

using System.Runtime.CompilerServices;
using Silk.NET.OpenGL;
namespace NResUI
{
public enum TextureCoordinate
{
S = TextureParameterName.TextureWrapS,
T = TextureParameterName.TextureWrapT,
R = TextureParameterName.TextureWrapR
}
public class OpenGlTexture : IDisposable
{
public const SizedInternalFormat Srgb8Alpha8 = (SizedInternalFormat)GLEnum.Srgb8Alpha8;
public const SizedInternalFormat Rgb32F = (SizedInternalFormat)GLEnum.Rgb32f;
public const GLEnum MaxTextureMaxAnisotropy = (GLEnum)0x84FF;
public static float? MaxAniso;
private readonly GL _gl;
public readonly string Name;
public readonly uint GlTexture;
public readonly uint Width, Height;
public readonly uint MipmapLevels;
public readonly SizedInternalFormat InternalFormat;
public OpenGlTexture(GL gl, int width, int height, IntPtr data, bool generateMipmaps = false, bool srgb = false)
{
_gl = gl;
MaxAniso ??= gl.GetFloat(MaxTextureMaxAnisotropy);
Width = (uint)width;
Height = (uint)height;
InternalFormat = srgb ? Srgb8Alpha8 : SizedInternalFormat.Rgba8;
MipmapLevels = (uint)(generateMipmaps == false ? 1 : (int)Math.Floor(Math.Log(Math.Max(Width, Height), 2)));
GlTexture = _gl.GenTexture();
Bind();
_gl.TexStorage2D(GLEnum.Texture2D, MipmapLevels, InternalFormat, Width, Height);
_gl.TexSubImage2D(GLEnum.Texture2D, 0, 0, 0, Width, Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
if (generateMipmaps) _gl.GenerateTextureMipmap(GlTexture);
SetWrap(TextureCoordinate.S, TextureWrapMode.Repeat);
SetWrap(TextureCoordinate.T, TextureWrapMode.Repeat);
_gl.TexParameterI(GLEnum.Texture2D, TextureParameterName.TextureMaxLevel, MipmapLevels - 1);
}
public OpenGlTexture(GL gl, int width, int height, byte[] data, bool generateMipmaps = false, bool srgb = false)
{
_gl = gl;
MaxAniso ??= gl.GetFloat(MaxTextureMaxAnisotropy);
Width = (uint)width;
Height = (uint)height;
InternalFormat = srgb ? Srgb8Alpha8 : SizedInternalFormat.Rgba8;
MipmapLevels = (uint)(generateMipmaps == false ? 1 : (int)Math.Floor(Math.Log(Math.Max(Width, Height), 2)));
GlTexture = _gl.GenTexture();
Bind();
_gl.TexStorage2D(GLEnum.Texture2D, MipmapLevels, InternalFormat, Width, Height);
_gl.TexSubImage2D(GLEnum.Texture2D, 0, 0, 0, Width, Height, PixelFormat.Bgra, PixelType.UnsignedByte, Unsafe.AsRef(ref data[0]));
if (generateMipmaps) _gl.GenerateTextureMipmap(GlTexture);
SetWrap(TextureCoordinate.S, TextureWrapMode.Repeat);
SetWrap(TextureCoordinate.T, TextureWrapMode.Repeat);
SetMinFilter(TextureMinFilter.Nearest);
SetMagFilter(TextureMagFilter.Nearest);
_gl.TexParameterI(GLEnum.Texture2D, TextureParameterName.TextureMaxLevel, MipmapLevels - 1);
}
public OpenGlTexture(GL gl, int width, int height, byte[] data, PixelFormat pixelFormat, bool generateMipmaps = false, bool srgb = false)
{
_gl = gl;
MaxAniso ??= gl.GetFloat(MaxTextureMaxAnisotropy);
Width = (uint)width;
Height = (uint)height;
InternalFormat = srgb ? Srgb8Alpha8 : SizedInternalFormat.Rgba8;
MipmapLevels = (uint)(generateMipmaps == false ? 1 : (int)Math.Floor(Math.Log(Math.Max(Width, Height), 2)));
GlTexture = _gl.GenTexture();
Bind();
_gl.TexStorage2D(GLEnum.Texture2D, MipmapLevels, InternalFormat, Width, Height);
_gl.TexSubImage2D(GLEnum.Texture2D, 0, 0, 0, Width, Height, pixelFormat, PixelType.UnsignedByte, Unsafe.AsRef(ref data[0]));
if (generateMipmaps) _gl.GenerateTextureMipmap(GlTexture);
SetWrap(TextureCoordinate.S, TextureWrapMode.Repeat);
SetWrap(TextureCoordinate.T, TextureWrapMode.Repeat);
_gl.TexParameterI(GLEnum.Texture2D, TextureParameterName.TextureMaxLevel, MipmapLevels - 1);
}
public void UpdateData(byte[] data, PixelFormat pixelFormat)
{
Bind();
_gl.TexSubImage2D(GLEnum.Texture2D, 0, 0, 0, Width, Height, pixelFormat, PixelType.UnsignedByte, Unsafe.AsRef(ref data[0]));
}
public byte[] DownloadData()
{
Bind();
byte[] data = new byte[Width * Height * 4];
_gl.GetTexImage(TextureTarget.Texture2D, 0, PixelFormat.Rgba, PixelType.UnsignedByte, out Unsafe.AsRef(ref data[0]));
return data;
}
public void Bind()
{
_gl.BindTexture(GLEnum.Texture2D, GlTexture);
}
public void SetMinFilter(TextureMinFilter filter)
{
_gl.TexParameterI(GLEnum.Texture2D, TextureParameterName.TextureMinFilter, (int)filter);
}
public void SetMagFilter(TextureMagFilter filter)
{
_gl.TexParameterI(GLEnum.Texture2D, TextureParameterName.TextureMagFilter, (int)filter);
}
// public void SetAnisotropy(float level)
// {
// const TextureParameterName textureMaxAnisotropy = (TextureParameterName)0x84FE;
// _gl.TexParameter(GLEnum.Texture2D, (GLEnum)textureMaxAnisotropy, Util.Clamp(level, 1, MaxAniso.GetValueOrDefault()));
// }
public void SetLod(int @base, int min, int max)
{
_gl.TexParameterI(GLEnum.Texture2D, TextureParameterName.TextureLodBias, @base);
_gl.TexParameterI(GLEnum.Texture2D, TextureParameterName.TextureMinLod, min);
_gl.TexParameterI(GLEnum.Texture2D, TextureParameterName.TextureMaxLod, max);
}
public void SetWrap(TextureCoordinate coord, TextureWrapMode mode)
{
_gl.TexParameterI(GLEnum.Texture2D, (TextureParameterName)coord, (int)mode);
}
public void Dispose()
{
_gl.DeleteTexture(GlTexture);
}
}
}