using NUnit.Framework; using System; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class RenderText : MonoBehaviour { int frame = 60; public int m_CaptureFrameRate; public float m_YHeight = 0; public string outputDirectory = "SampleRecordings/Projection"; [HideInInspector] public Texture2D texture; public ProjectionType m_ProjectionType = ProjectionType.Gnomic; public bool m_Record = false; public bool m_RecordOnAwake = true; int txt_W; int txt_H; public int m_RecordedFrames; public Material material; float x_FOV; float y_FOV; float y_Rotation; float x_Rotation; float y_Divide; float x_Divide; string m_Timestamp; GameObject m_CubeMapPrefab = null; List m_ShaderList = new List(); public enum ProjectionType { Cropped, CroppedFOV, Squeezed, Gnomic } private void Awake() { SetupMatShaders(); m_RecordedFrames = 0; } // Initial configuration for frame rate private void Start() { SetupFrameRateConfiguration(); if (m_RecordOnAwake) { m_Timestamp = DateTime.Now.ToString("yyyyMMddHHmmss"); m_Record = true; } } private void Update() { ToggleRecording(); if (m_Record) { for (int frameCount = 0; frameCount < 4; frameCount++) { SetMaterialParametersBasedOnProjectionType(frameCount); } m_RecordedFrames++; } else { m_RecordedFrames = 0; } frame++; } void SetMaterialParametersBasedOnProjectionType(int frameCount) { var m_HeightY = 0f; if (frameCount == 0 || frameCount == 2) { // Set Front & Back if(m_ProjectionType == ProjectionType.Gnomic) { txt_W = 8192; txt_H = 889; x_FOV = 1.5f; y_FOV = 0.2f; y_Rotation = 5.13f; x_Rotation = 0.25f; m_HeightY = 7f; material.shader = m_ShaderList[1]; } if (m_ProjectionType == ProjectionType.Cropped) { txt_W = 6750; txt_H = 1080;; y_Rotation = 4.8f; x_Rotation = 1f; y_Divide = 5.8f; x_Divide = 4f; m_HeightY = 0.5f; material.shader = m_ShaderList[0]; } if (m_ProjectionType == ProjectionType.CroppedFOV) { txt_W = 8192; txt_H = 889; y_Rotation = 4.8f; x_Rotation = 0f; y_Divide = 5.8f; x_Divide = 2.666f; m_HeightY = 0.5f; material.shader = m_ShaderList[0]; } if (m_ProjectionType == ProjectionType.Squeezed) { txt_W = 6750; txt_H = 1080; y_Rotation = 0.85f; x_Rotation = 1f; y_Divide = 3.5f; x_Divide = 4f; m_HeightY = 5f; material.shader = m_ShaderList[0]; } } else { // Set Left & right if (m_ProjectionType == ProjectionType.Gnomic) { txt_W = 3510; txt_H = 1080; x_FOV = 0.9f; y_FOV = 0.3f; y_Rotation = 5.23f; x_Rotation = 0.25f; m_HeightY = 7f; material.shader = m_ShaderList[1]; } if (m_ProjectionType == ProjectionType.Cropped) { txt_W = 6750; txt_H = 1080; y_Rotation = 4.8f; x_Rotation = 1f; y_Divide = 5.8f; x_Divide = 4f; m_HeightY = 0.5f; material.shader = m_ShaderList[0]; } if (m_ProjectionType == ProjectionType.CroppedFOV) { txt_W = 3510; txt_H = 1080; y_Rotation = 4.8f; x_Rotation = 0f; y_Divide = 5.8f; x_Divide = 8f; m_HeightY = 0.5f; material.shader = m_ShaderList[0]; } if (m_ProjectionType == ProjectionType.Squeezed) { txt_W = 6750; txt_H = 1080; y_Rotation = 0.85f; x_Rotation = 1f; y_Divide = 3.5f; x_Divide = 4f; m_HeightY = 5f; material.shader = m_ShaderList[0]; } } CycleThroughOrientations(frameCount, m_HeightY); } void CycleThroughOrientations(int frameCount, float m_HeightY) { m_CubeMapPrefab.transform.localPosition = new Vector3(m_CubeMapPrefab.transform.localPosition.x, m_YHeight, m_CubeMapPrefab.transform.localPosition.z); if (m_ProjectionType != ProjectionType.CroppedFOV) { material.SetFloat("_EquiRotation", x_Rotation * frameCount); } else { if(frameCount == 0 || frameCount == 2) { material.SetFloat("_EquiRotation", x_Rotation + frameCount); } else { material.SetFloat("_EquiRotation", frameCount + 0.5f); } } material.SetFloat("_EquiRotationY", y_Rotation); if (m_ProjectionType == ProjectionType.Gnomic) { material.SetFloat("_FOVScale_X", x_FOV); material.SetFloat("_FOVScale_Y", y_FOV); } else { material.SetFloat("_DivideY", y_Divide); material.SetFloat("_DivideX", x_Divide); } ExportTexture(frameCount); } private void ExportTexture(int frameCount) { RenderTexture buffer = new RenderTexture( txt_W, txt_H, 0, // No depth/stencil buffer RenderTextureFormat.ARGB32, // Standard colour format RenderTextureReadWrite.sRGB // No sRGB conversions ); texture = new Texture2D(txt_W, txt_H); Graphics.Blit(null, buffer, material); RenderTexture.active = buffer; // If not using a scene camera texture.ReadPixels( new Rect(0, 0, txt_W, txt_H), // Capture the whole texture 0, 0, // Write starting at the top-left texel false); // No mipmaps // Create a timestamped folder in the /SampleRecordings directory var recordingsDir = Path.Combine(Application.dataPath, "..", outputDirectory, m_Timestamp); // Create the direction-specific folder if it doesn't exist var directionFolder = ""; switch (frameCount) { case 0: directionFolder = "SideB"; break; case 1: directionFolder = "SideA"; break; case 2: directionFolder = "SideD"; break; case 3: directionFolder = "SideC"; break; } var fullDirectionPath = Path.Combine(recordingsDir, directionFolder); if (!Directory.Exists(fullDirectionPath)) { Directory.CreateDirectory(fullDirectionPath); } // Save the PNG file with a frame-specific name var filePath = Path.Combine(fullDirectionPath, $"{directionFolder}_{frame:D4}.png"); System.IO.File.WriteAllBytes(filePath, texture.EncodeToPNG()); RenderTexture.active = null; RenderTexture.Destroy(texture); buffer.Release(); } private void SetupMatShaders() { ///material = this.GetComponent().material; m_ShaderList.Add(Shader.Find("Conversion/CubemapToEquirectangularSqueeze")); m_ShaderList.Add(Shader.Find("Conversion/CubemapToEquirectangularGnomic")); material.shader = m_ShaderList[1]; } private void SetupFrameRateConfiguration() { frame = 0; m_CubeMapPrefab = this.transform.parent.gameObject; Application.targetFrameRate = m_CaptureFrameRate; QualitySettings.vSyncCount = 0; Time.captureDeltaTime = 1.0f / m_CaptureFrameRate; } private void ToggleRecording() { if (Input.GetKeyUp(KeyCode.R) && !m_RecordOnAwake) { m_Timestamp = DateTime.Now.ToString("yyyyMMddHHmmss"); m_Record = true; } if (Input.GetKeyUp(KeyCode.T)) { m_Record = false; } } }