public class StarProcessorWithMultipleTextures : MonoBehaviour
public string directoryPath; // Directory containing BIN files
public int maxRows = 1000; // Maximum number of stars to process
private const int TextureWidth = 1024;
private const int TextureHeight = 1024;
private Texture2D positionTexture; // Texture to store XYZ positions
private Texture2D colorTexture; // Texture to store decoded color (as Color32)
private Texture2D sizeMagnitudeTexture; // Texture to store size and magnitude
if (!Directory.Exists(directoryPath))
Debug.LogError("Directory does not exist: " + directoryPath);
string[] files = Directory.GetFiles(directoryPath, "*.bin");
Array.Sort(files); // Sort files alphabetically
NativeArray<float> starData = new NativeArray<float>(maxRows * 6, Allocator.TempJob); // Each star has 6 values: x, y, z, appmag, encodedColor, size
foreach (string file in files)
if (totalStarsRead >= maxRows)
using (BinaryReader reader = new BinaryReader(File.Open(file, FileMode.Open)))
int starsRead = ReadBinFile(reader, starData, totalStarsRead, maxRows);
totalStarsRead += starsRead;
CreateAndSaveTextures(starData, totalStarsRead);
private int ReadBinFile(BinaryReader reader, NativeArray<float> starData, int startIdx, int maxRows)
int numberOfStars = ReadIntBigEndian(reader);
while (count < numberOfStars && startIdx + count < maxRows)
ReadStar(reader, starData, startIdx + count);
private void ReadStar(BinaryReader reader, NativeArray<float> starData, int index)
// Read position (normalized)
double x = ReadDoubleBigEndian(reader);
double y = ReadDoubleBigEndian(reader);
double z = ReadDoubleBigEndian(reader);
Vector3 position = new Vector3((float)x, (float)y, (float)z).normalized;
reader.BaseStream.Seek(48, SeekOrigin.Current);
// Read attributes (appmag, absmag, encodedColor, size)
float appmag = ReadFloatBigEndian(reader);
float absmag = ReadFloatBigEndian(reader);
float encodedColor = ReadFloatBigEndian(reader);
float size = ReadFloatBigEndian(reader);
reader.BaseStream.Seek(24, SeekOrigin.Current);
// Read name length and skip the name
int nameLength = ReadIntBigEndian(reader);
reader.BaseStream.Seek(nameLength * 2, SeekOrigin.Current);
starData[baseIdx] = position.x;
starData[baseIdx + 1] = position.y;
starData[baseIdx + 2] = position.z;
starData[baseIdx + 3] = appmag;
starData[baseIdx + 4] = encodedColor; // Store encoded color as a float
starData[baseIdx + 5] = size;
private void CreateAndSaveTextures(NativeArray<float> starData, int totalStars)
positionTexture = new Texture2D(TextureWidth, TextureHeight, TextureFormat.RGBAFloat, false);
colorTexture = new Texture2D(TextureWidth, TextureHeight, TextureFormat.RGBA32, false);
sizeMagnitudeTexture = new Texture2D(TextureWidth, TextureHeight, TextureFormat.RGFloat, false);
NativeArray<Color> positionTextureData = positionTexture.GetRawTextureData<Color>();
NativeArray<Color32> colorTextureData = colorTexture.GetRawTextureData<Color32>();
NativeArray<Vector2> sizeMagnitudeTextureData = sizeMagnitudeTexture.GetRawTextureData<Vector2>();
ProcessStarDataJob job = new ProcessStarDataJob
PositionTextureData = positionTextureData,
ColorTextureData = colorTextureData,
SizeMagnitudeTextureData = sizeMagnitudeTextureData,
JobHandle handle = job.Schedule(positionTextureData.Length, 64); // Schedule parallel processing
positionTexture.Apply(); // Apply changes to the position texture
colorTexture.Apply(); // Apply changes to the color texture
sizeMagnitudeTexture.Apply(); // Apply changes to the size-magnitude texture
// Save the textures to the Assets folder
SaveTextureAsAsset(positionTexture, "Assets/PositionTexture.asset");
SaveTextureAsAsset(colorTexture, "Assets/ColorTexture.asset");
SaveTextureAsAsset(sizeMagnitudeTexture, "Assets/SizeMagnitudeTexture.asset");
// Clean up native arrays
positionTextureData.Dispose();
colorTextureData.Dispose();
sizeMagnitudeTextureData.Dispose();
private void SaveTextureAsAsset(Texture2D texture, string assetPath)
// Ensure the directory exists
string directory = Path.GetDirectoryName(assetPath);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
// Encode texture to a format and save as asset
byte[] textureData = texture.EncodeToEXR(Texture2D.EXRFlags.OutputAsFloat);
File.WriteAllBytes(assetPath, textureData);
// Import the asset to Unity’s AssetDatabase
AssetDatabase.ImportAsset(assetPath);
TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(assetPath);
importer.textureCompression = TextureImporterCompression.Uncompressed;
importer.SaveAndReimport();
private struct ProcessStarDataJob : IJobParallelFor
[ReadOnly] public NativeArray<float> StarData;
public NativeArray<Color> PositionTextureData;
public NativeArray<Color32> ColorTextureData;
public NativeArray<Vector2> SizeMagnitudeTextureData;
public void Execute(int index)
// Write XYZ to position texture
PositionTextureData[index] = new Color(
1.0f // Alpha channel, can be used or ignored
// Decode and write color to color texture
float encodedColor = StarData[baseIdx + 4];
Color32 decodedColor = DecodeColor(encodedColor);
ColorTextureData[index] = decodedColor;
// Write size and magnitude to size-magnitude texture
SizeMagnitudeTextureData[index] = new Vector2(
StarData[baseIdx + 5], // Size
StarData[baseIdx + 3] // Appmag
// Fill remaining texture space with default values
PositionTextureData[index] = Color.black;
ColorTextureData[index] = new Color32(0, 0, 0, 0);
SizeMagnitudeTextureData[index] = Vector2.zero;
private Color32 DecodeColor(float encodedColor)
uint colorBits = math.asuint(encodedColor);
byte r = (byte)((colorBits >> 24) & 0xFF);
byte g = (byte)((colorBits >> 16) & 0xFF);
byte b = (byte)((colorBits >> 8) & 0xFF);
byte a = (byte)(colorBits & 0xFF);
return new Color32(r, g, b, a);
private int ReadIntBigEndian(BinaryReader reader)
byte[] bytes = reader.ReadBytes(4);
if (BitConverter.IsLittleEndian)
return BitConverter.ToInt32(bytes, 0);
private float ReadFloatBigEndian(BinaryReader reader)
byte[] bytes = reader.ReadBytes(4);
if (BitConverter.IsLittleEndian)
return BitConverter.ToSingle(bytes, 0);
private double ReadDoubleBigEndian(BinaryReader reader)
byte[] bytes = reader.ReadBytes(8);
if (BitConverter.IsLittleEndian)