You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
2.8 KiB
77 lines
2.8 KiB
2 years ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.IO;
|
||
|
using gaemstone.ECS;
|
||
|
using Silk.NET.OpenGL;
|
||
|
using SixLabors.ImageSharp;
|
||
|
using SixLabors.ImageSharp.PixelFormats;
|
||
|
using Size = System.Drawing.Size;
|
||
|
|
||
|
namespace gaemstone.Client;
|
||
|
|
||
|
public static class TextureManager
|
||
|
{
|
||
|
private static readonly Dictionary<Texture, TextureInfo> _byTexture = new();
|
||
|
private static readonly Dictionary<string, TextureInfo> _bySourceFile = new();
|
||
|
|
||
|
public static void Initialize(Universe universe)
|
||
|
{
|
||
|
var GL = universe.Lookup<Game>().Get<Windowing.Canvas>().GL;
|
||
|
// Upload single-pixel white texture into texture slot 0, so when
|
||
|
// "no" texture is bound, we can still use the texture sampler.
|
||
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
||
|
Span<byte> pixel = stackalloc byte[4];
|
||
|
pixel.Fill(255);
|
||
|
GL.TexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgba,
|
||
|
1, 1, 0, PixelFormat.Rgba, PixelType.UnsignedByte, in pixel[0]);
|
||
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
|
||
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
|
||
|
}
|
||
|
|
||
|
public static Texture Load(Universe universe, string name)
|
||
|
{
|
||
|
using var stream = Resources.GetStream(name);
|
||
|
return CreateFromStream(universe, stream, name);
|
||
|
}
|
||
|
|
||
|
public static Texture CreateFromStream(Universe universe, Stream stream, string? sourceFile = null)
|
||
|
{
|
||
|
var GL = universe.Lookup<Game>().Get<Windowing.Canvas>().GL;
|
||
|
var texture = new Texture(TextureTarget.Texture2D, GL.GenTexture());
|
||
|
GL.BindTexture(texture.Target, texture.Handle);
|
||
|
|
||
|
var image = Image.Load<Rgba32>(stream);
|
||
|
ref var origin = ref image.Frames[0].PixelBuffer[0, 0];
|
||
|
|
||
|
GL.TexImage2D(texture.Target, 0, (int)PixelFormat.Rgba,
|
||
|
(uint)image.Width, (uint)image.Height, 0,
|
||
|
PixelFormat.Rgba, PixelType.UnsignedByte, origin);
|
||
|
GL.TexParameter(texture.Target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
|
||
|
GL.TexParameter(texture.Target, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
|
||
|
|
||
|
var info = new TextureInfo(texture, sourceFile, new(image.Width, image.Height));
|
||
|
_byTexture.Add(texture, info);
|
||
|
if (sourceFile != null) _bySourceFile.Add(sourceFile, info);
|
||
|
|
||
|
GL.BindTexture(texture.Target, 0);
|
||
|
return texture;
|
||
|
}
|
||
|
|
||
|
|
||
|
public static TextureInfo? Lookup(Texture texture)
|
||
|
=> _byTexture.TryGetValue(texture, out var value) ? value : null;
|
||
|
|
||
|
public static TextureInfo? Lookup(string sourceFile)
|
||
|
=> _bySourceFile.TryGetValue(sourceFile, out var value) ? value : null;
|
||
|
}
|
||
|
|
||
|
public class TextureInfo
|
||
|
{
|
||
|
public Texture Texture { get; }
|
||
|
public string? SourceFile { get; }
|
||
|
public Size Size { get; }
|
||
|
|
||
|
public TextureInfo(Texture texture, string? sourceFile, Size size)
|
||
|
=> (Texture, SourceFile, Size) = (texture, sourceFile, size);
|
||
|
}
|