2024-11-19 02:13:14 +03:00
|
|
|
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);
|
2024-11-23 01:32:12 +03:00
|
|
|
|
|
|
|
SetMinFilter(TextureMinFilter.Nearest);
|
|
|
|
SetMagFilter(TextureMagFilter.Nearest);
|
2024-11-19 02:13:14 +03:00
|
|
|
|
|
|
|
_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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|