unity3d渲染到CubeMap的貼圖保存工具


之前美術mm想做一個唯美天空盒,將某相機在球形模型中的視野渲染到cubemap上,然后賦給天空盒.她想再次編輯cubemap中某一面的貼圖,無奈無法獲得這些貼圖.機會來了!!

自己寫了個工具類,可以渲染,可以保存某一張圖片,也可以一次性全部導出這些貼圖,問題解決.

/// <summary>
/// 將某相機所看渲染到CubeMap,並選擇性的保存此CubeMap貼圖
/// </summary>
using UnityEngine;
using UnityEditor;

/// <summary>
/// CubeMap 六個面 
/// </summary>
enum CubeMapFaces
{
	right = 0,
	left,
	top,
	bottom,
	front,
	back
}

public class RenderToCubeMapTool : EditorWindow
{
	
	[MenuItem ("Window/CubeMapTool %m")]
	static void AddWindow ()
	{       
		//創建窗口
		Rect wr = new Rect (0, 0, 100, 100);
		RenderToCubeMapTool window = (RenderToCubeMapTool)EditorWindow.GetWindowWithRect (typeof(RenderToCubeMapTool), wr, false, "CubeMapTool");	
		window.Show ();
		
	}

	private Camera renderCamera;
	private Cubemap renderCubeMap;
	CubeMapFaces faces;
	private CubemapFace offcialFaces;

	void OnGUI ()
	{
		GUILayout.BeginVertical ();
		GUILayout.Space (10f);
		renderCamera = EditorGUILayout.ObjectField ("渲染相機", renderCamera, typeof(Camera), true) as Camera;
		GUILayout.Space (10f);
		renderCubeMap = EditorGUILayout.ObjectField ("CubeMap", renderCubeMap, typeof(Cubemap), false) as Cubemap;


		GUILayout.Space (10f);
		if (GUILayout.Button ("渲染") && CheckCamAndCubeMap ()) {

			if (renderCamera.RenderToCubemap (renderCubeMap)) {

			
		
				Debug.LogWarningFormat ("渲染完成!");
				CheckSingleCubeMapFaces ();

			} else {
				Debug.LogWarningFormat ("渲染失敗!");
			}
		}

		GUILayout.Space (10f);

		GUILayout.BeginHorizontal ();
		faces = (CubeMapFaces)EditorGUILayout.EnumPopup ("保存CubeMap某個面", faces);
	


		if (GUILayout.Button ("保存") && CheckCamAndCubeMap ()) {
		

			CheckSingleCubeMapFaces ();
			SaveSingelTexture ();

		}

		GUILayout.EndHorizontal ();
		GUILayout.Space (10f);
		if (GUILayout.Button ("全部保存")) {


			SaveMultiTexture ();
		}

		GUILayout.Space (10f);

		EditorGUILayout.HelpBox ("請務必確認要渲染的CubeMap可以讀寫!\n (屬性面板中的 Readable 勾上即可)", MessageType.Warning);


		GUILayout.EndVertical ();

	}

	bool CheckCamAndCubeMap ()
	{
		if (renderCamera == null || renderCubeMap == null) {
			Debug.LogError ("渲染相機和CubeMap不能為空!");
			return false;
		} else {
			return true;
		}
	}
	
	#region 檢測單張保存時對應cubemap面
	/// <summary>
	/// Checks the cube map faces.
	/// </summary>
	void CheckSingleCubeMapFaces ()
	{
		switch (faces) {
		case CubeMapFaces.right:
			offcialFaces = CubemapFace.PositiveX;
			break;
		case CubeMapFaces.left:
			offcialFaces = CubemapFace.NegativeX;
			break;
		case CubeMapFaces.top:
			offcialFaces = CubemapFace.PositiveY;
			break;
		case CubeMapFaces.bottom:
			offcialFaces = CubemapFace.NegativeY;
			break;
		case CubeMapFaces.front:
			offcialFaces = CubemapFace.PositiveZ;
			break;
		case CubeMapFaces.back:
			offcialFaces = CubemapFace.NegativeZ;
			break;
			
		}
	}
	#endregion

	#region 檢測多張保存時對應的cubemap面
	/// <summary>
	/// Checks the multi cube map faces.
	/// </summary>
	void CheckMultiCubeMapFaces (int index)
	{
		switch (index) {
		case (int)CubeMapFaces.right:
			offcialFaces = CubemapFace.PositiveX;
			break;
		case (int)CubeMapFaces.left:
			offcialFaces = CubemapFace.NegativeX;
			break;
		case (int)CubeMapFaces.top:
			offcialFaces = CubemapFace.PositiveY;
			break;
		case (int)CubeMapFaces.bottom:
			offcialFaces = CubemapFace.NegativeY;
			break;
		case (int)CubeMapFaces.front:
			offcialFaces = CubemapFace.PositiveZ;
			break;
		case (int)CubeMapFaces.back:
			offcialFaces = CubemapFace.NegativeZ;
			break;
			
		}
	}

	#endregion

	#region 由cubemap 朝向反推前后左右方向
	string CheckDir ()
	{
		string name = "TestTexture";
		switch (offcialFaces) {
		case CubemapFace.PositiveX:
			name = "right";
			break;
		case CubemapFace.NegativeX:
			name = "left";
			break;
		case CubemapFace.PositiveY:
			name = "top";
			break;
		case CubemapFace.NegativeY:
			name = "bottom";
			break;
		case CubemapFace.PositiveZ:
			name = "front";
			break;
		case CubemapFace.NegativeZ:
			name = "back";
			break;
			
		}
		return name;
	}

	#endregion
	
	#region 保存單張圖片
	/// <summary>
	///保存單張圖片 
	/// </summary>
	private void SaveSingelTexture ()
	{

		Texture2D screenShot = new Texture2D (renderCubeMap.width,
		                                     renderCubeMap.height,
		                                     TextureFormat.ARGB32,
		                                     false);
		for (int i = 0; i< renderCubeMap.width; i++) {
			for (int j = 0; j < renderCubeMap.height; j++) {
				screenShot.SetPixel (i, j, renderCubeMap.GetPixel (offcialFaces, renderCubeMap.width - i, renderCubeMap.height - j));
			}
		}

		screenShot.Apply ();
		byte[] bytes = screenShot.EncodeToPNG ();

		string path = EditorUtility.SaveFilePanel ("圖片保存", Application.dataPath, faces.ToString (), "png");

		System.IO.File.WriteAllBytes (path, bytes);

		AssetDatabase.Refresh ();  
	}
	#endregion

	#region 保存多張圖片
	/// <summary>
	///保存單張圖片 
	/// </summary>
	private void SaveMultiTexture ()
	{
		
		Texture2D screenShot;
		string path = Application.dataPath + "/" + "CubeMapTextures/";
		for (int k = 0; k< 6; k++) {
		
			screenShot = new Texture2D (renderCubeMap.width,
			                                      renderCubeMap.height,
			                                      TextureFormat.ARGB32,
			                                      false);
			CheckMultiCubeMapFaces (k);
			for (int i = 0; i< renderCubeMap.width; i++) {
				for (int j = 0; j < renderCubeMap.height; j++) {
					screenShot.SetPixel (i, j, renderCubeMap.GetPixel (offcialFaces, renderCubeMap.width - i, renderCubeMap.height - j));
				}
			}
		
			screenShot.Apply ();
			byte[] bytes = screenShot.EncodeToPNG ();

			if (!System.IO.Directory.Exists (path)) {
				System.IO.Directory.CreateDirectory (path);
			}
			System.IO.File.WriteAllBytes (path + CheckDir () + ".png", bytes);

		}

		AssetDatabase.Refresh ();  

		Debug.LogWarning ("六張圖片已經保存在 " + path + " 下!");

	}
	#endregion
	
	void OnInspectorUpdate ()
	{
		this.Repaint ();
	}

	void OnFocus ()
	{
		//Debug.Log("當窗口獲得焦點時調用一次");
	}
	
	void OnLostFocus ()
	{
		//Debug.Log("當窗口丟失焦點時調用一次");
		Caching.CleanCache ();  
	}
}

注意

1 cubemap 需保持可讀寫狀態(勾選readable)

2 cubemap尺寸較大時可能需要稍稍等待下(和mm喝咖啡的時間來了 ^^)  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM