10 using System.Collections.Generic;
17 private const string nameFormat =
"{0}/{1}-{2}.png";
18 private const string helpText =
"Take snapshot will use the current " +
19 "position and rotation to capture six directional screenshots to use as this " +
20 "skybox's textures. Note: This skybox is only used to override what shows up " +
21 "in the compositor (e.g. when loading levels). Add a Camera component to this " +
22 "object to override default settings like which layers to render. Additionally, " +
23 "by specifying your own targetTexture, you can control the size of the textures " +
24 "and other properties like antialiasing. Don't forget to disable the camera.\n\n" +
25 "For stereo screenshots, a panorama is render for each eye using the specified " +
26 "ipd (in millimeters) broken up into segments cellSize pixels square to optimize " +
27 "generation.\n(32x32 takes about 10 seconds depending on scene complexity, 16x16 " +
28 "takes around a minute, while will 8x8 take several minutes.)\n\nTo test, hit " +
29 "play then pause - this will activate the skybox settings, and then drop you to " +
30 "the compositor where the skybox is rendered.";
32 public override void OnInspectorGUI()
34 DrawDefaultInspector();
36 EditorGUILayout.HelpBox(helpText, MessageType.Info);
38 if (GUILayout.Button(
"Take snapshot"))
40 var directions =
new Quaternion[] {
41 Quaternion.LookRotation(Vector3.forward),
42 Quaternion.LookRotation(Vector3.back),
43 Quaternion.LookRotation(Vector3.left),
44 Quaternion.LookRotation(Vector3.right),
45 Quaternion.LookRotation(Vector3.up, Vector3.back),
46 Quaternion.LookRotation(Vector3.down, Vector3.forward)
49 Camera tempCamera = null;
52 var targetScene = target.gameObject.scene;
53 var sceneName = Path.GetFileNameWithoutExtension(targetScene.path);
54 var scenePath = Path.GetDirectoryName(targetScene.path);
55 var assetPath = scenePath +
"/" + sceneName;
56 if (!AssetDatabase.IsValidFolder(assetPath))
58 var guid = AssetDatabase.CreateFolder(scenePath, sceneName);
59 assetPath = AssetDatabase.GUIDToAssetPath(guid);
62 var camera = target.GetComponent<Camera>();
65 if (tempCamera == null)
66 tempCamera =
new GameObject().AddComponent<Camera>();
70 var targetTexture = camera.targetTexture;
71 if (camera.targetTexture == null)
73 targetTexture =
new RenderTexture(1024, 1024, 24);
74 targetTexture.antiAliasing = 8;
75 camera.targetTexture = targetTexture;
78 var oldPosition = target.transform.localPosition;
79 var oldRotation = target.transform.localRotation;
80 var baseRotation = target.transform.rotation;
82 var t = camera.transform;
83 t.position = target.transform.position;
84 camera.orthographic =
false;
85 camera.fieldOfView = 90;
87 for (
int i = 0; i < directions.Length; i++)
89 t.rotation = baseRotation * directions[i];
93 RenderTexture.active = targetTexture;
94 var texture =
new Texture2D(targetTexture.width, targetTexture.height, TextureFormat.ARGB32,
false);
95 texture.ReadPixels(
new Rect(0, 0, texture.width, texture.height), 0, 0);
97 RenderTexture.active = null;
99 var assetName = string.Format(nameFormat, assetPath, target.name, i);
100 System.IO.File.WriteAllBytes(assetName, texture.EncodeToPNG());
103 if (camera != tempCamera)
105 target.transform.localPosition = oldPosition;
106 target.transform.localRotation = oldRotation;
110 if (tempCamera != null)
112 Object.DestroyImmediate(tempCamera.gameObject);
116 AssetDatabase.Refresh();
119 var targetScene = target.gameObject.scene;
120 var sceneName = Path.GetFileNameWithoutExtension(targetScene.path);
121 var scenePath = Path.GetDirectoryName(targetScene.path);
122 var assetPath = scenePath +
"/" + sceneName;
124 for (
int i = 0; i < directions.Length; i++)
126 var assetName = string.Format(nameFormat, assetPath, target.name, i);
127 var importer = AssetImporter.GetAtPath(assetName) as TextureImporter;
128 #if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0)
129 importer.textureFormat = TextureImporterFormat.RGB24;
131 importer.textureCompression = TextureImporterCompression.Uncompressed;
133 importer.wrapMode = TextureWrapMode.Clamp;
134 importer.mipmapEnabled =
false;
135 importer.SaveAndReimport();
137 var texture = AssetDatabase.LoadAssetAtPath<Texture>(assetName);
138 target.SetTextureByIndex(i, texture);
142 else if (GUILayout.Button(
"Take stereo snapshot"))
144 const int width = 4096;
145 const int height = width / 2;
146 const int halfHeight = height / 2;
148 var textures =
new Texture2D[] {
149 new Texture2D(width, height, TextureFormat.ARGB32,
false),
150 new Texture2D(width, height, TextureFormat.ARGB32,
false) };
152 var timer =
new System.Diagnostics.Stopwatch();
154 Camera tempCamera = null;
159 var targetScene = target.gameObject.scene;
160 var sceneName = Path.GetFileNameWithoutExtension(targetScene.path);
161 var scenePath = Path.GetDirectoryName(targetScene.path);
162 var assetPath = scenePath +
"/" + sceneName;
163 if (!AssetDatabase.IsValidFolder(assetPath))
165 var guid = AssetDatabase.CreateFolder(scenePath, sceneName);
166 assetPath = AssetDatabase.GUIDToAssetPath(guid);
169 var camera = target.GetComponent<Camera>();
172 if (tempCamera == null)
173 tempCamera =
new GameObject().AddComponent<Camera>();
179 var oldTargetTexture = camera.targetTexture;
180 var oldOrthographic = camera.orthographic;
181 var oldFieldOfView = camera.fieldOfView;
182 var oldAspect = camera.aspect;
184 var oldPosition = target.transform.localPosition;
185 var oldRotation = target.transform.localRotation;
186 var basePosition = target.transform.position;
187 var baseRotation = target.transform.rotation;
189 var transform = camera.transform;
191 int cellSize = int.Parse(target.StereoCellSize.ToString().Substring(1));
192 float ipd = target.StereoIpdMm / 1000.0f;
193 int vTotal = halfHeight / cellSize;
194 float dv = 90.0f / vTotal;
195 float dvHalf = dv / 2.0f;
197 var targetTexture =
new RenderTexture(cellSize, cellSize, 24);
198 targetTexture.wrapMode = TextureWrapMode.Clamp;
199 targetTexture.antiAliasing = 8;
201 camera.fieldOfView = dv;
202 camera.orthographic =
false;
203 camera.targetTexture = targetTexture;
211 for (
int v = 0; v < vTotal; v++)
213 var pitch = 90.0f - (v * dv) - dvHalf;
214 var uTotal = width / targetTexture.width;
215 var du = 360.0f / uTotal;
216 var duHalf = du / 2.0f;
218 var vTarget = v * halfHeight / vTotal;
220 for (
int i = 0; i < 2; i++)
225 vTarget = height - vTarget - cellSize;
228 for (
int u = 0; u < uTotal; u++)
230 var yaw = -180.0f + (u * du) + duHalf;
232 var uTarget = u * width / uTotal;
234 var xOffset = -ipd / 2 * Mathf.Cos(pitch * Mathf.Deg2Rad);
236 for (
int j = 0; j < 2; j++)
238 var texture = textures[j];
245 var offset = baseRotation * Quaternion.Euler(0, yaw, 0) *
new Vector3(xOffset, 0, 0);
246 transform.position = basePosition + offset;
248 var direction = Quaternion.Euler(pitch, yaw, 0.0f);
249 transform.rotation = baseRotation * direction;
252 var N = direction * Vector3.forward;
255 var phi0 = yaw - (du / 2);
256 var phi1 = phi0 + du;
259 var theta0 = pitch + (dv / 2);
260 var theta1 = theta0 - dv;
262 var midPhi = (phi0 + phi1) / 2;
263 var baseTheta = Mathf.Abs(theta0) < Mathf.Abs(theta1) ? theta0 : theta1;
266 var V00 = Quaternion.Euler(baseTheta, phi0, 0.0f) * Vector3.forward;
267 var V01 = Quaternion.Euler(baseTheta, phi1, 0.0f) * Vector3.forward;
270 var V0M = Quaternion.Euler(theta0, midPhi, 0.0f) * Vector3.forward;
271 var V1M = Quaternion.Euler(theta1, midPhi, 0.0f) * Vector3.forward;
274 var P00 = V00 / Vector3.Dot(V00, N);
275 var P01 = V01 / Vector3.Dot(V01, N);
276 var P0M = V0M / Vector3.Dot(V0M, N);
277 var P1M = V1M / Vector3.Dot(V1M, N);
280 var P00_P01 = P01 - P00;
281 var P0M_P1M = P1M - P0M;
283 var uMag = P00_P01.magnitude;
284 var vMag = P0M_P1M.magnitude;
286 var uScale = 1.0f / uMag;
287 var vScale = 1.0f / vMag;
289 var uAxis = P00_P01 * uScale;
290 var vAxis = P0M_P1M * vScale;
293 fx.Set(N, phi0, phi1, theta0, theta1,
297 camera.aspect = uMag / vMag;
300 RenderTexture.active = targetTexture;
301 texture.ReadPixels(
new Rect(0, 0, targetTexture.width, targetTexture.height), uTarget, vTarget);
302 RenderTexture.active = null;
309 for (
int i = 0; i < 2; i++)
311 var texture = textures[i];
314 var assetName = string.Format(nameFormat, assetPath, target.name, i);
315 File.WriteAllBytes(assetName, texture.EncodeToPNG());
319 if (camera != tempCamera)
321 camera.targetTexture = oldTargetTexture;
322 camera.orthographic = oldOrthographic;
323 camera.fieldOfView = oldFieldOfView;
324 camera.aspect = oldAspect;
326 target.transform.localPosition = oldPosition;
327 target.transform.localRotation = oldRotation;
331 tempCamera.targetTexture = null;
334 DestroyImmediate(targetTexture);
335 DestroyImmediate(fx);
338 Debug.Log(string.Format(
"Screenshot took {0} seconds.", timer.Elapsed));
341 if (tempCamera != null)
343 DestroyImmediate(tempCamera.gameObject);
346 DestroyImmediate(textures[0]);
347 DestroyImmediate(textures[1]);
350 AssetDatabase.Refresh();
353 var targetScene = target.gameObject.scene;
354 var sceneName = Path.GetFileNameWithoutExtension(targetScene.path);
355 var scenePath = Path.GetDirectoryName(targetScene.path);
356 var assetPath = scenePath +
"/" + sceneName;
358 for (
int i = 0; i < 2; i++)
360 var assetName = string.Format(nameFormat, assetPath, target.name, i);
361 var importer = AssetImporter.GetAtPath(assetName) as TextureImporter;
362 importer.mipmapEnabled =
false;
363 importer.wrapMode = TextureWrapMode.Repeat;
364 #if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0)
365 importer.SetPlatformTextureSettings(
"Standalone", width, TextureImporterFormat.RGB24);
367 var settings = importer.GetPlatformTextureSettings(
"Standalone");
368 settings.textureCompression = TextureImporterCompression.Uncompressed;
369 settings.maxTextureSize = width;
370 importer.SetPlatformTextureSettings(settings);
372 importer.SaveAndReimport();
374 var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetName);
375 target.SetTextureByIndex(i, texture);