Added texture exporting to PSXObjectExporter component
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using PSXSplash.RuntimeCode;
|
||||
using System.IO;
|
||||
|
||||
namespace PSXSplash.EditorCode
|
||||
{
|
||||
@@ -18,6 +19,7 @@ namespace PSXSplash.EditorCode
|
||||
if (GUILayout.Button("Export mesh"))
|
||||
{
|
||||
comp.Mesh.Export(comp.gameObject);
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
@@ -26,7 +28,53 @@ namespace PSXSplash.EditorCode
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("Texture"));
|
||||
if (GUILayout.Button("Export texture"))
|
||||
{
|
||||
comp.Texture.Export(comp.gameObject);
|
||||
ushort[] textureData = comp.Texture.ExportTexture(comp.gameObject);
|
||||
string path = EditorUtility.SaveFilePanel(
|
||||
"Save texture data",
|
||||
"",
|
||||
"texture_data",
|
||||
"bin"
|
||||
);
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write))
|
||||
using (BinaryWriter writer = new BinaryWriter(fileStream))
|
||||
{
|
||||
foreach (ushort value in textureData)
|
||||
{
|
||||
writer.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
|
||||
if (comp.Texture.TextureType != PSXTextureType.TEX16_BPP)
|
||||
{
|
||||
if (GUILayout.Button("Export clut"))
|
||||
{
|
||||
ushort[] clutData = comp.Texture.ExportClut(comp.gameObject);
|
||||
string path = EditorUtility.SaveFilePanel(
|
||||
"Save clut data",
|
||||
"",
|
||||
"clut_data",
|
||||
"bin"
|
||||
);
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write))
|
||||
using (BinaryWriter writer = new BinaryWriter(fileStream))
|
||||
{
|
||||
foreach (ushort value in clutData)
|
||||
{
|
||||
writer.Write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using PSXSplash.RuntimeCode;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
@@ -78,10 +79,10 @@ public class QuantizedPreviewWindow : EditorWindow
|
||||
|
||||
if (indexedPixelData != null)
|
||||
{
|
||||
if (GUILayout.Button("Export pixel data"))
|
||||
if (GUILayout.Button("Export texute data"))
|
||||
{
|
||||
string path = EditorUtility.SaveFilePanel(
|
||||
"Save pixel data",
|
||||
"Save texture data",
|
||||
"",
|
||||
"pixel_data",
|
||||
"bin"
|
||||
@@ -129,13 +130,14 @@ public class QuantizedPreviewWindow : EditorWindow
|
||||
|
||||
private void GenerateQuantizedPreview()
|
||||
{
|
||||
Texture2D resizedTexture = ResizeTexture(originalTexture, targetWidth, targetHeight);
|
||||
Texture2D resizedTexture = PSXTexture.ResizeTexture(originalTexture, targetWidth, targetHeight);
|
||||
|
||||
if (bpp == 16)
|
||||
{
|
||||
quantizedTexture = ConvertTo16Bpp(resizedTexture);
|
||||
quantizedTexture = null;
|
||||
indexedPixelData = PSXTexture.ConvertTo16Bpp(resizedTexture);
|
||||
clut = null;
|
||||
vramTexture = resizedTexture;
|
||||
vramTexture = ConvertTo16BppTexture2D(resizedTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -153,7 +155,7 @@ public class QuantizedPreviewWindow : EditorWindow
|
||||
{
|
||||
for (int x = 0; x < resizedTexture.width; x++)
|
||||
{
|
||||
int index = 0;
|
||||
int index;
|
||||
|
||||
if (pixelSize == 4)
|
||||
{
|
||||
@@ -231,34 +233,6 @@ public class QuantizedPreviewWindow : EditorWindow
|
||||
return vramTexture;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Texture2D ConvertTo16Bpp(Texture2D source)
|
||||
{
|
||||
int width = source.width;
|
||||
int height = source.height;
|
||||
Texture2D convertedTexture = new Texture2D(width, height);
|
||||
|
||||
Color[] originalPixels = source.GetPixels();
|
||||
Color[] convertedPixels = new Color[originalPixels.Length];
|
||||
|
||||
for (int i = 0; i < originalPixels.Length; i++)
|
||||
{
|
||||
Color pixel = originalPixels[i];
|
||||
|
||||
float r = Mathf.Floor(pixel.r * 31) / 31.0f; // 5 bits for red
|
||||
float g = Mathf.Floor(pixel.g * 31) / 31.0f; // 5 bits for green
|
||||
float b = Mathf.Floor(pixel.b * 31) / 31.0f; // 5 bits for blue
|
||||
|
||||
convertedPixels[i] = new Color(r, g, b, pixel.a);
|
||||
}
|
||||
|
||||
convertedTexture.SetPixels(convertedPixels);
|
||||
convertedTexture.Apply();
|
||||
|
||||
return convertedTexture;
|
||||
}
|
||||
|
||||
private void DrawTexturePreview(Texture2D texture, int size, bool flipY = true)
|
||||
{
|
||||
Rect rect = GUILayoutUtility.GetRect(size, size, GUILayout.ExpandWidth(false));
|
||||
@@ -328,21 +302,35 @@ public class QuantizedPreviewWindow : EditorWindow
|
||||
}
|
||||
}
|
||||
|
||||
private Texture2D ConvertTo16BppTexture2D(Texture2D source)
|
||||
{
|
||||
int width = source.width;
|
||||
int height = source.height;
|
||||
Texture2D convertedTexture = new Texture2D(width, height);
|
||||
|
||||
private Texture2D ResizeTexture(Texture2D source, int newWidth, int newHeight)
|
||||
Color[] originalPixels = source.GetPixels();
|
||||
Color[] convertedPixels = new Color[originalPixels.Length];
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
RenderTexture rt = RenderTexture.GetTemporary(newWidth, newHeight);
|
||||
rt.antiAliasing = 1;
|
||||
Graphics.Blit(source, rt);
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int flippedY = height - y - 1;
|
||||
|
||||
Texture2D resizedTexture = new Texture2D(newWidth, newHeight);
|
||||
RenderTexture.active = rt;
|
||||
resizedTexture.ReadPixels(new Rect(0, 0, newWidth, newHeight), 0, 0);
|
||||
resizedTexture.Apply();
|
||||
Color pixel = originalPixels[flippedY * width + x];
|
||||
|
||||
RenderTexture.active = null;
|
||||
RenderTexture.ReleaseTemporary(rt);
|
||||
float r = Mathf.Floor(pixel.r * 31) / 31.0f; // 5 bits for red
|
||||
float g = Mathf.Floor(pixel.g * 31) / 31.0f; // 5 bits for green
|
||||
float b = Mathf.Floor(pixel.b * 31) / 31.0f; // 5 bits for blue
|
||||
|
||||
return resizedTexture;
|
||||
convertedPixels[y * width + x] = new Color(r, g, b, pixel.a);
|
||||
}
|
||||
}
|
||||
|
||||
convertedTexture.SetPixels(convertedPixels);
|
||||
convertedTexture.Apply();
|
||||
|
||||
return convertedTexture;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PSXSplash.RuntimeCode
|
||||
@@ -26,9 +28,8 @@ namespace PSXSplash.RuntimeCode
|
||||
public int Height = 128;
|
||||
|
||||
|
||||
// TODO: This just uses the quantization and doesn't store the result anywhere
|
||||
// Maybe it should return the image and the clut back to the SceneExporter / The Editor code for only-texture export?
|
||||
public void Export(GameObject gameObject)
|
||||
|
||||
public ushort[] ExportTexture(GameObject gameObject)
|
||||
{
|
||||
Debug.Log($"Export: {this}");
|
||||
|
||||
@@ -40,15 +41,101 @@ namespace PSXSplash.RuntimeCode
|
||||
{
|
||||
Texture2D originalTexture = (Texture2D)texture;
|
||||
|
||||
Texture2D newTexture = new Texture2D(originalTexture.width, originalTexture.height, originalTexture.format, false);
|
||||
newTexture.SetPixels(originalTexture.GetPixels());
|
||||
newTexture.Apply();
|
||||
Debug.Log((int)TextureType);
|
||||
newTexture.Reinitialize(Width, Height, UnityEngine.Experimental.Rendering.GraphicsFormat.R8G8B8_UInt, false);
|
||||
var (quantizedPixels, clut) = ImageQuantizer.Quantize(originalTexture, (int)TextureType);
|
||||
Texture2D newTexture = ResizeTexture(originalTexture, Width, Height);
|
||||
if (TextureType == PSXTextureType.TEX16_BPP)
|
||||
{
|
||||
ushort[] converted = ConvertTo16Bpp(newTexture);
|
||||
return converted;
|
||||
}
|
||||
else
|
||||
{
|
||||
var (indexedPixels, _) = ImageQuantizer.Quantize(newTexture, (int)TextureType, 100);
|
||||
return indexedPixels;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ushort[] ExportClut(GameObject gameObject)
|
||||
{
|
||||
Debug.Log($"Export: {this}");
|
||||
|
||||
MeshRenderer meshRenderer = gameObject.GetComponent<MeshRenderer>();
|
||||
if (meshRenderer != null)
|
||||
{
|
||||
Texture texture = meshRenderer.material.mainTexture;
|
||||
if (texture is Texture2D)
|
||||
{
|
||||
Texture2D originalTexture = (Texture2D)texture;
|
||||
|
||||
Texture2D newTexture = ResizeTexture(originalTexture, Width, Height);
|
||||
if (TextureType == PSXTextureType.TEX16_BPP)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var (_, generatedClut) = ImageQuantizer.Quantize(newTexture, (int)TextureType, 100);
|
||||
return generatedClut;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Texture2D ResizeTexture(Texture2D source, int newWidth, int newHeight)
|
||||
{
|
||||
RenderTexture rt = RenderTexture.GetTemporary(newWidth, newHeight);
|
||||
rt.antiAliasing = 1;
|
||||
Graphics.Blit(source, rt);
|
||||
|
||||
Texture2D resizedTexture = new Texture2D(newWidth, newHeight);
|
||||
RenderTexture.active = rt;
|
||||
resizedTexture.ReadPixels(new Rect(0, 0, newWidth, newHeight), 0, 0);
|
||||
resizedTexture.Apply();
|
||||
|
||||
RenderTexture.active = null;
|
||||
RenderTexture.ReleaseTemporary(rt);
|
||||
|
||||
return resizedTexture;
|
||||
}
|
||||
|
||||
public static ushort[] ConvertTo16Bpp(Texture2D source)
|
||||
{
|
||||
int width = source.width;
|
||||
int height = source.height;
|
||||
ushort[] packedData = new ushort[width * height];
|
||||
|
||||
Color[] originalPixels = source.GetPixels();
|
||||
|
||||
// Flip the image on the Y-axis
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int flippedY = height - y - 1;
|
||||
|
||||
int index = flippedY * width + x;
|
||||
|
||||
// Retrieve the pixel color
|
||||
Color pixel = originalPixels[index];
|
||||
|
||||
// Convert to 5-bit components
|
||||
int r = Mathf.Clamp(Mathf.RoundToInt(pixel.r * 31), 0, 31); // 5 bits for red
|
||||
int g = Mathf.Clamp(Mathf.RoundToInt(pixel.g * 31), 0, 31); // 5 bits for green
|
||||
int b = Mathf.Clamp(Mathf.RoundToInt(pixel.b * 31), 0, 31); // 5 bits for blue
|
||||
|
||||
// Pack into a ushort: R(0..4), G(5..9), B(10..14), Padding(15)
|
||||
packedData[y * width + x] = (ushort)((b << 10) | (g << 5) | r);
|
||||
}
|
||||
}
|
||||
|
||||
return packedData;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user