Rewrote quantizer
This commit is contained in:
173
Runtime/PSXTexture2D.cs
Normal file
173
Runtime/PSXTexture2D.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace PSXSplash.RuntimeCode
|
||||
{
|
||||
|
||||
public enum PSXBPP
|
||||
{
|
||||
TEX_4BIT = 4,
|
||||
TEX_8BIT = 8,
|
||||
TEX_16BIT = 15
|
||||
}
|
||||
|
||||
public struct VRAMPixel
|
||||
{
|
||||
private ushort r; // 0-4 bits
|
||||
private ushort g; // 5-9 bits
|
||||
private ushort b; // 10-14 bits
|
||||
|
||||
public ushort R
|
||||
{
|
||||
get => r;
|
||||
set => r = (ushort)(value & 0b11111);
|
||||
}
|
||||
|
||||
public ushort G
|
||||
{
|
||||
get => g;
|
||||
set => g = (ushort)(value & 0b11111);
|
||||
}
|
||||
|
||||
public ushort B
|
||||
{
|
||||
get => b;
|
||||
set => b = (ushort)(value & 0b11111);
|
||||
}
|
||||
|
||||
public bool SemiTransparent { get; set; } // 15th bit
|
||||
|
||||
|
||||
public ushort Pack()
|
||||
{
|
||||
return (ushort)((r << 11) | (g << 6) | (b << 1) | (SemiTransparent ? 1 : 0));
|
||||
}
|
||||
|
||||
public void Unpack(ushort packedValue)
|
||||
{
|
||||
r = (ushort)((packedValue >> 11) & 0b11111);
|
||||
g = (ushort)((packedValue >> 6) & 0b11111);
|
||||
b = (ushort)((packedValue >> 1) & 0b11111);
|
||||
SemiTransparent = (packedValue & 0b1) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class PSXTexture2D
|
||||
{
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
public int[] Pixels { get; set; }
|
||||
public List<VRAMPixel> ColorPalette = new List<VRAMPixel>();
|
||||
public PSXBPP BitDepth;
|
||||
|
||||
private int _maxColors;
|
||||
|
||||
public static PSXTexture2D CreateFromTexture2D(Texture2D inputTexture, PSXBPP bitDepth, bool dither)
|
||||
{
|
||||
PSXTexture2D psxTex = new PSXTexture2D();
|
||||
|
||||
psxTex.Width = inputTexture.width;
|
||||
psxTex.Height = inputTexture.height;
|
||||
psxTex.BitDepth = bitDepth;
|
||||
|
||||
psxTex._maxColors = (int)Mathf.Pow((int)bitDepth, 2);
|
||||
|
||||
ImageQuantizer quantizer = new ImageQuantizer();
|
||||
quantizer.Quantize(inputTexture, psxTex._maxColors);
|
||||
|
||||
foreach (Color pixel in quantizer.Palette)
|
||||
{
|
||||
VRAMPixel vramPixel = new VRAMPixel { R = (ushort)(pixel.r * 31), G = (ushort)(pixel.g * 31), B = (ushort)(pixel.b * 31) };
|
||||
psxTex.ColorPalette.Add(vramPixel);
|
||||
}
|
||||
psxTex.Pixels = quantizer.Pixels;
|
||||
|
||||
return psxTex;
|
||||
}
|
||||
|
||||
public Texture2D GeneratePreview()
|
||||
{
|
||||
Texture2D tex = new Texture2D(Width, Height);
|
||||
|
||||
List<Color> colors = new List<Color>();
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
for (int x = 0; x < Width; x++)
|
||||
{
|
||||
int pixel = Pixels[y * Width + x];
|
||||
VRAMPixel color = ColorPalette[pixel];
|
||||
|
||||
float r = color.R / 31f;
|
||||
float g = color.G / 31f;
|
||||
float b = color.B / 31f;
|
||||
|
||||
colors.Add(new Color(r, g, b));
|
||||
}
|
||||
}
|
||||
tex.SetPixels(colors.ToArray());
|
||||
tex.Apply();
|
||||
return tex;
|
||||
}
|
||||
|
||||
public Texture2D GenerateVramPreview()
|
||||
{
|
||||
|
||||
int adjustedWidth = Width;
|
||||
|
||||
if (BitDepth == PSXBPP.TEX_4BIT)
|
||||
{
|
||||
adjustedWidth = Mathf.CeilToInt(Width / 4f);
|
||||
}
|
||||
else if (BitDepth == PSXBPP.TEX_8BIT)
|
||||
{
|
||||
adjustedWidth = Mathf.CeilToInt(Width / 2f);
|
||||
}
|
||||
|
||||
Texture2D vramTexture = new Texture2D(adjustedWidth, Height);
|
||||
|
||||
List<ushort> packedValues = new List<ushort>();
|
||||
|
||||
if (BitDepth == PSXBPP.TEX_4BIT)
|
||||
{
|
||||
for (int i = 0; i < Pixels.Length; i += 4)
|
||||
{
|
||||
ushort packed = (ushort)((Pixels[i] << 12) | (Pixels[i + 1] << 8) | (Pixels[i + 2] << 4) | Pixels[i + 3]);
|
||||
packedValues.Add(packed);
|
||||
}
|
||||
}
|
||||
else if (BitDepth == PSXBPP.TEX_8BIT)
|
||||
{
|
||||
for (int i = 0; i < Pixels.Length; i += 2)
|
||||
{
|
||||
ushort packed = (ushort)((Pixels[i] << 8) | Pixels[i + 1]);
|
||||
packedValues.Add(packed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<Color> colors = new List<Color>();
|
||||
for (int i = 0; i < packedValues.Count; i++)
|
||||
{
|
||||
int index = packedValues[i];
|
||||
|
||||
float r = (index & 31) / 31.0f;
|
||||
float g = ((index >> 5) & 31) / 31.0f;
|
||||
float b = ((index >> 10) & 31) / 31.0f;
|
||||
|
||||
colors.Add(new Color(r, g, b));
|
||||
}
|
||||
vramTexture.SetPixels(colors.ToArray());
|
||||
vramTexture.Apply();
|
||||
|
||||
return vramTexture;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user