Files
UltimateFishing2020/Assets/Scripts/Assembly-CSharp/LilyRender360.cs
2026-03-04 10:03:45 +08:00

253 lines
6.8 KiB
C#

using System;
using System.IO;
using UnityEngine;
public class LilyRender360 : MonoBehaviour
{
public enum Format
{
PNG = 0,
EXR = 1
}
public enum CubeFace
{
PX = 0,
NX = 1,
PY = 2,
NY = 3,
PZ = 4,
NZ = 5
}
public int targetFramerate = 30;
public Format format;
public string prefix = "Recordings/";
public int nDigits = 4;
public bool overwriteFile;
public int width = 1024;
public bool enableHeight;
public int height = 1024;
public int startFrame;
public bool enableEndFrame;
public int endFrame = -1;
public float horizontalFov = 360f;
public float verticalFov = 180f;
public float overlap = 0.5f;
public Transform stitchingOrientation;
public bool showStitchLines;
public bool enableCubeFaceSize;
public int cubeFaceSize = 512;
public bool doubleRender;
public bool smoothStitching = true;
private Camera _cam;
private Texture2D _tex;
private int _frame;
private Material _equirectMat;
private RenderTexture[] _faces;
private RenderTexture _equirect;
public string AbsolutePrefix
{
get
{
string text = Path.GetDirectoryName(Application.dataPath).Replace(Path.DirectorySeparatorChar, '/') + "/";
if (!Path.IsPathRooted(prefix))
{
return text + prefix;
}
return prefix;
}
}
public int MaxFrame => (int)Mathf.Min((enableEndFrame && endFrame > -1) ? ((float)endFrame) : float.PositiveInfinity, Mathf.Pow(10f, nDigits) - 1f);
public float FullWidth => Mathf.Min((float)(width * 360) / horizontalFov, 8 * width);
public float SuggestedHeight => FullWidth / 2f * verticalFov / 180f;
public string AbsoluteFramePath(int frame)
{
return string.Format("{0}{1:D" + nDigits + "}.{2}", AbsolutePrefix, frame, (format == Format.EXR) ? "exr" : "png");
}
public void ChechParameters()
{
if (!enableHeight)
{
height = (int)SuggestedHeight;
}
if (!enableCubeFaceSize)
{
cubeFaceSize = (int)(FullWidth / 4f * (1f + overlap * 2f));
}
}
private void InitCubemap()
{
int num = (doubleRender ? 12 : 6);
_faces = new RenderTexture[num];
for (int i = 0; i < num; i++)
{
_faces[i] = new RenderTexture(cubeFaceSize, cubeFaceSize, 24, (format != Format.PNG) ? RenderTextureFormat.ARGBFloat : RenderTextureFormat.ARGB32);
}
_equirect = new RenderTexture(width, height, 24, (format != Format.PNG) ? RenderTextureFormat.ARGBFloat : RenderTextureFormat.ARGB32);
}
private RenderTexture Face(CubeFace face, int cube = 0)
{
return _faces[(int)(face + cube * 6)];
}
private void RenderCubemap(int cube = 0)
{
float fieldOfView = _cam.fieldOfView;
Quaternion rotation = _cam.transform.rotation;
RenderTexture targetTexture = _cam.targetTexture;
if (stitchingOrientation != null)
{
_cam.transform.rotation = stitchingOrientation.rotation;
}
if (cube == 1)
{
_cam.transform.Rotate(-45f, 45f, 0f);
}
_cam.fieldOfView = 2f * Mathf.Atan(1f + overlap) / MathF.PI * 180f;
_cam.targetTexture = Face(CubeFace.PX, cube);
_cam.transform.Rotate(0f, 90f, 0f);
_cam.Render();
_cam.targetTexture = Face(CubeFace.NZ, cube);
_cam.transform.Rotate(0f, 90f, 0f);
_cam.Render();
_cam.targetTexture = Face(CubeFace.NX, cube);
_cam.transform.Rotate(0f, 90f, 0f);
_cam.Render();
_cam.targetTexture = Face(CubeFace.PZ, cube);
_cam.transform.Rotate(0f, 90f, 0f);
_cam.Render();
_cam.targetTexture = Face(CubeFace.PY, cube);
_cam.transform.Rotate(90f, 0f, 0f);
_cam.Render();
_cam.targetTexture = Face(CubeFace.NY, cube);
_cam.transform.Rotate(180f, 0f, 0f);
_cam.Render();
_cam.fieldOfView = fieldOfView;
_cam.transform.rotation = rotation;
_cam.targetTexture = targetTexture;
}
private void ConvertToEquirect()
{
Matrix4x4 matrix4x = Matrix4x4.identity;
if (stitchingOrientation != null)
{
Vector3 eulerAngles = (_cam.transform.worldToLocalMatrix * stitchingOrientation.localToWorldMatrix).rotation.eulerAngles;
matrix4x = Matrix4x4.Rotate(Quaternion.identity * Quaternion.AngleAxis(eulerAngles.z, Vector3.forward) * Quaternion.AngleAxis(eulerAngles.x, Vector3.right) * Quaternion.AngleAxis(0f - eulerAngles.y, Vector3.up));
}
_equirectMat.SetTexture("_FaceTexPX", Face(CubeFace.PX));
_equirectMat.SetTexture("_FaceTexNX", Face(CubeFace.NX));
_equirectMat.SetTexture("_FaceTexPY", Face(CubeFace.PY));
_equirectMat.SetTexture("_FaceTexNY", Face(CubeFace.NY));
_equirectMat.SetTexture("_FaceTexPZ", Face(CubeFace.PZ));
_equirectMat.SetTexture("_FaceTexNZ", Face(CubeFace.NZ));
_equirectMat.SetMatrix("_OrientMatrix", matrix4x);
_equirectMat.SetFloat("_Beta", 1f / (1f + overlap));
_equirectMat.SetFloat("_HorizontalFov", horizontalFov * (MathF.PI / 180f));
_equirectMat.SetFloat("_VerticalFov", verticalFov * (MathF.PI / 180f));
if (doubleRender)
{
_equirectMat.SetTexture("_FaceTexPX2", Face(CubeFace.PX, 1));
_equirectMat.SetTexture("_FaceTexNX2", Face(CubeFace.NX, 1));
_equirectMat.SetTexture("_FaceTexPY2", Face(CubeFace.PY, 1));
_equirectMat.SetTexture("_FaceTexNY2", Face(CubeFace.NY, 1));
_equirectMat.SetTexture("_FaceTexPZ2", Face(CubeFace.PZ, 1));
_equirectMat.SetTexture("_FaceTexNZ2", Face(CubeFace.NZ, 1));
Matrix4x4 inverse = Matrix4x4.Rotate(Quaternion.Euler(45f, 45f, 0f)).inverse;
_equirectMat.SetMatrix("_OrientMatrix2", inverse * matrix4x);
}
Graphics.Blit(null, _equirect, _equirectMat);
}
private void Start()
{
ChechParameters();
InitCubemap();
_cam = GetComponent<Camera>();
_tex = new Texture2D(_equirect.width, _equirect.height, (format == Format.EXR) ? TextureFormat.RGBAFloat : TextureFormat.RGB24, mipChain: false);
Time.maximumDeltaTime = 1f / (float)targetFramerate;
Time.captureFramerate = targetFramerate;
_equirectMat = new Material(Shader.Find("Hidden/LilyRender/Equirectangular"));
_equirectMat.EnableKeyword("ORIENT_CUBE");
if (showStitchLines)
{
_equirectMat.EnableKeyword("SHOW_STITCH_LINES");
}
if (doubleRender)
{
_equirectMat.EnableKeyword("TWO_CUBES");
}
if (smoothStitching && overlap > 0f)
{
_equirectMat.EnableKeyword("SMOOTH_STITCHING");
}
Directory.CreateDirectory(Path.GetDirectoryName(AbsoluteFramePath(0)));
}
private void LateUpdate()
{
ChechParameters();
if (_frame >= startFrame)
{
string text = AbsoluteFramePath(_frame);
if (File.Exists(text) && !overwriteFile)
{
Debug.LogWarning("File '" + text + "' already exists. Skipping frame (check 'Override' to force overriding existing files).");
}
else
{
RenderCubemap();
if (doubleRender)
{
RenderCubemap(1);
}
ConvertToEquirect();
RenderTexture.active = _equirect;
_tex.ReadPixels(new Rect(0f, 0f, _equirect.width, _equirect.height), 0, 0);
byte[] bytes = ((format == Format.EXR) ? _tex.EncodeToEXR(Texture2D.EXRFlags.CompressZIP) : _tex.EncodeToPNG());
RenderTexture.active = null;
File.WriteAllBytes(text, bytes);
}
}
_frame++;
if (_frame > MaxFrame)
{
Application.Quit();
}
}
}