Added texture exporting to PSXObjectExporter component
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using PSXSplash.RuntimeCode;
|
using PSXSplash.RuntimeCode;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace PSXSplash.EditorCode
|
namespace PSXSplash.EditorCode
|
||||||
{
|
{
|
||||||
@@ -18,6 +19,7 @@ namespace PSXSplash.EditorCode
|
|||||||
if (GUILayout.Button("Export mesh"))
|
if (GUILayout.Button("Export mesh"))
|
||||||
{
|
{
|
||||||
comp.Mesh.Export(comp.gameObject);
|
comp.Mesh.Export(comp.gameObject);
|
||||||
|
GUIUtility.ExitGUI();
|
||||||
}
|
}
|
||||||
EditorGUILayout.EndVertical();
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
@@ -26,7 +28,53 @@ namespace PSXSplash.EditorCode
|
|||||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("Texture"));
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("Texture"));
|
||||||
if (GUILayout.Button("Export 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();
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
using PSXSplash.RuntimeCode;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Rendering;
|
using UnityEngine.Rendering;
|
||||||
@@ -78,10 +79,10 @@ public class QuantizedPreviewWindow : EditorWindow
|
|||||||
|
|
||||||
if (indexedPixelData != null)
|
if (indexedPixelData != null)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("Export pixel data"))
|
if (GUILayout.Button("Export texute data"))
|
||||||
{
|
{
|
||||||
string path = EditorUtility.SaveFilePanel(
|
string path = EditorUtility.SaveFilePanel(
|
||||||
"Save pixel data",
|
"Save texture data",
|
||||||
"",
|
"",
|
||||||
"pixel_data",
|
"pixel_data",
|
||||||
"bin"
|
"bin"
|
||||||
@@ -129,13 +130,14 @@ public class QuantizedPreviewWindow : EditorWindow
|
|||||||
|
|
||||||
private void GenerateQuantizedPreview()
|
private void GenerateQuantizedPreview()
|
||||||
{
|
{
|
||||||
Texture2D resizedTexture = ResizeTexture(originalTexture, targetWidth, targetHeight);
|
Texture2D resizedTexture = PSXTexture.ResizeTexture(originalTexture, targetWidth, targetHeight);
|
||||||
|
|
||||||
if (bpp == 16)
|
if (bpp == 16)
|
||||||
{
|
{
|
||||||
quantizedTexture = ConvertTo16Bpp(resizedTexture);
|
quantizedTexture = null;
|
||||||
|
indexedPixelData = PSXTexture.ConvertTo16Bpp(resizedTexture);
|
||||||
clut = null;
|
clut = null;
|
||||||
vramTexture = resizedTexture;
|
vramTexture = ConvertTo16BppTexture2D(resizedTexture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -153,7 +155,7 @@ public class QuantizedPreviewWindow : EditorWindow
|
|||||||
{
|
{
|
||||||
for (int x = 0; x < resizedTexture.width; x++)
|
for (int x = 0; x < resizedTexture.width; x++)
|
||||||
{
|
{
|
||||||
int index = 0;
|
int index;
|
||||||
|
|
||||||
if (pixelSize == 4)
|
if (pixelSize == 4)
|
||||||
{
|
{
|
||||||
@@ -231,34 +233,6 @@ public class QuantizedPreviewWindow : EditorWindow
|
|||||||
return vramTexture;
|
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)
|
private void DrawTexturePreview(Texture2D texture, int size, bool flipY = true)
|
||||||
{
|
{
|
||||||
Rect rect = GUILayoutUtility.GetRect(size, size, GUILayout.ExpandWidth(false));
|
Rect rect = GUILayoutUtility.GetRect(size, size, GUILayout.ExpandWidth(false));
|
||||||
@@ -328,21 +302,35 @@ public class QuantizedPreviewWindow : EditorWindow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Texture2D ConvertTo16BppTexture2D(Texture2D source)
|
||||||
private Texture2D ResizeTexture(Texture2D source, int newWidth, int newHeight)
|
|
||||||
{
|
{
|
||||||
RenderTexture rt = RenderTexture.GetTemporary(newWidth, newHeight);
|
int width = source.width;
|
||||||
rt.antiAliasing = 1;
|
int height = source.height;
|
||||||
Graphics.Blit(source, rt);
|
Texture2D convertedTexture = new Texture2D(width, height);
|
||||||
|
|
||||||
Texture2D resizedTexture = new Texture2D(newWidth, newHeight);
|
Color[] originalPixels = source.GetPixels();
|
||||||
RenderTexture.active = rt;
|
Color[] convertedPixels = new Color[originalPixels.Length];
|
||||||
resizedTexture.ReadPixels(new Rect(0, 0, newWidth, newHeight), 0, 0);
|
|
||||||
resizedTexture.Apply();
|
|
||||||
|
|
||||||
RenderTexture.active = null;
|
for (int y = 0; y < height; y++)
|
||||||
RenderTexture.ReleaseTemporary(rt);
|
{
|
||||||
|
for (int x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
int flippedY = height - y - 1;
|
||||||
|
|
||||||
return resizedTexture;
|
Color pixel = originalPixels[flippedY * width + x];
|
||||||
|
|
||||||
|
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[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;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace PSXSplash.RuntimeCode
|
namespace PSXSplash.RuntimeCode
|
||||||
@@ -26,9 +28,8 @@ namespace PSXSplash.RuntimeCode
|
|||||||
public int Height = 128;
|
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 ushort[] ExportTexture(GameObject gameObject)
|
||||||
public void Export(GameObject gameObject)
|
|
||||||
{
|
{
|
||||||
Debug.Log($"Export: {this}");
|
Debug.Log($"Export: {this}");
|
||||||
|
|
||||||
@@ -40,15 +41,101 @@ namespace PSXSplash.RuntimeCode
|
|||||||
{
|
{
|
||||||
Texture2D originalTexture = (Texture2D)texture;
|
Texture2D originalTexture = (Texture2D)texture;
|
||||||
|
|
||||||
Texture2D newTexture = new Texture2D(originalTexture.width, originalTexture.height, originalTexture.format, false);
|
Texture2D newTexture = ResizeTexture(originalTexture, Width, Height);
|
||||||
newTexture.SetPixels(originalTexture.GetPixels());
|
if (TextureType == PSXTextureType.TEX16_BPP)
|
||||||
newTexture.Apply();
|
{
|
||||||
Debug.Log((int)TextureType);
|
ushort[] converted = ConvertTo16Bpp(newTexture);
|
||||||
newTexture.Reinitialize(Width, Height, UnityEngine.Experimental.Rendering.GraphicsFormat.R8G8B8_UInt, false);
|
return converted;
|
||||||
var (quantizedPixels, clut) = ImageQuantizer.Quantize(originalTexture, (int)TextureType);
|
}
|
||||||
|
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