1 using Microsoft.Xna.Framework.Graphics;
3 using System.Threading.Tasks;
6 using Color = Microsoft.Xna.Framework.Color;
13 public static class TextureLoader
15 public static Texture2D PlaceHolderTexture
21 private static volatile bool cancelAll =
false;
23 public static void Init(GraphicsDevice graphicsDevice,
bool needsBmp =
false)
25 _graphicsDevice = graphicsDevice;
27 Color[] data =
new Color[32 * 32];
28 for (
int i = 0; i < 32 * 32; i++)
30 data[i] = Color.Magenta;
33 CrossThread.RequestExecutionOnMainThread(() =>
35 PlaceHolderTexture =
new Texture2D(graphicsDevice, 32, 32);
36 PlaceHolderTexture.SetData(data);
40 public static void CancelAll()
45 private static byte[] CompressDxt5(
byte[] data,
int width,
int height)
47 var output =
new byte[width * height];
50 toExclusive: width * height / 16,
54 int inputOffset = (i4 % width + (i4 / width) * 4 * width) * 4;
55 int outputOffset = i * 16;
56 CompressDxt5Block(data, inputOffset, width, output, outputOffset);
61 private static void CompressDxt5Block(
byte[] data,
int inputOffset,
int width,
byte[] output,
int outputOffset)
63 int r1 = 255, g1 = 255, b1 = 255, a1 = 255;
64 int r2 = 0, g2 = 0, b2 = 0, a2 = 0;
73 for (
int i = 0; i < 16; i++)
75 int pixelOffset = inputOffset + (4 * ((i % 4) + (width * (i >> 2))));
76 int r = data[pixelOffset + 0];
77 int g = data[pixelOffset + 1];
78 int b = data[pixelOffset + 2];
79 int a = data[pixelOffset + 3];
80 int y = r * 299 + g * 587 + b * 114;
83 r1 = r; g1 = g; b1 = b; y1 = y;
87 r2 = r; g2 = g; b2 = b; y2 = y;
89 if (a < a1) { a1 = a; }
90 if (a > a2) { a2 = a; }
94 int r1_565 = r1 >> (8 - 5);
95 int g1_565 = g1 >> (8 - 6);
96 int b1_565 = b1 >> (8 - 5);
98 int r2_565 = r2 >> (8 - 5);
99 int g2_565 = g2 >> (8 - 6);
100 int b2_565 = b2 >> (8 - 5);
102 int y2y1Diff = y2 - y1;
103 if (y2y1Diff > 0 || a1 < a2)
105 for (
int i = 0; i < 16; i++)
107 int pixelOffset = inputOffset + (4 * ((i % 4) + (width * (i >> 2))));
108 int r = data[pixelOffset + 0];
109 int g = data[pixelOffset + 1];
110 int b = data[pixelOffset + 2];
114 int a = data[pixelOffset + 3];
116 a = (a * 0x7) / (a2 - a1);
125 NetBitWriter.WriteByte((
byte)a, 3, output, (outputOffset * 8) + 16 + (i * 3));
129 if (y2y1Diff <= 0) {
continue; }
131 int y = r * 299 + g * 587 + b * 114;
133 int paletteIndex = (diffY * 4) / y2y1Diff;
134 paletteIndex = paletteIndex
switch
141 output[outputOffset + 12 + (i / 4)] |= (
byte)(paletteIndex << (2 * (i % 4)));
145 output[outputOffset + 0] = (byte)a2;
146 output[outputOffset + 1] = (byte)a1;
148 output[outputOffset + 9] = (byte)((r1_565 << 3) | (g1_565 >> 3));
149 output[outputOffset + 8] = (byte)((g1_565 << 5) | b1_565);
150 output[outputOffset + 11] = (byte)((r2_565 << 3) | (g2_565 >> 3));
151 output[outputOffset + 10] = (byte)((g2_565 << 5) | b2_565);
154 public static Texture2D FromFile(
string path,
bool compress =
true,
bool mipmap =
false, ContentPackage contentPackage =
null)
156 using FileStream fileStream = File.OpenRead(path);
157 return FromStream(fileStream, path, compress, mipmap, contentPackage);
160 public static Texture2D FromStream(System.IO.Stream stream,
string path =
null,
bool compress =
true,
bool mipmap =
false, ContentPackage contentPackage =
null)
164 path = path.CleanUpPath();
165 byte[] textureData =
null;
166 textureData = Texture2D.TextureDataFromStream(stream, out
int width, out
int height, out
int channels);
168 SurfaceFormat format = SurfaceFormat.Color;
169 if (GameSettings.CurrentConfig.Graphics.CompressTextures && compress)
171 if (((width & 0x03) == 0) && ((height & 0x03) == 0))
173 textureData = CompressDxt5(textureData, width, height);
174 format = SurfaceFormat.Dxt5;
179 DebugConsole.AddWarning($
"Could not compress a texture because the dimensions aren't a multiple of 4 (path: {path ?? "null"}, size: {width}x{height})",
184 Texture2D tex =
null;
185 CrossThread.RequestExecutionOnMainThread(() =>
187 if (cancelAll) {
return; }
188 tex =
new Texture2D(_graphicsDevice, width, height, mipmap, format);
189 tex.SetData(textureData);
196 if (e is SharpDX.SharpDXException) {
throw; }
199 DebugConsole.ThrowError(
string.IsNullOrEmpty(path) ?
"Loading texture from stream failed!" :
200 "Loading texture \"" + path +
"\" failed!", e);
205 private static GraphicsDevice _graphicsDevice;