RenderCloudCubemapEditor.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. using System.IO;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.SceneManagement;
  6. using UnityEditor;
  7. namespace Funly.SkyStudio
  8. {
  9. [CustomEditor(typeof(RenderCloudCubemap))]
  10. public class RenderCloudCubemapEditor : Editor
  11. {
  12. private struct CubeFaceData
  13. {
  14. public CubemapFace face;
  15. public Vector2 offset;
  16. public CubeFaceData(CubemapFace face, Vector2 offset)
  17. {
  18. this.face = face;
  19. this.offset = offset;
  20. }
  21. }
  22. public override void OnInspectorGUI()
  23. {
  24. RenderCloudCubemap settings = this.target as RenderCloudCubemap;
  25. Camera cam = settings.GetComponent<Camera>();
  26. cam.gameObject.transform.position = Vector3.zero;
  27. cam.gameObject.transform.rotation = Quaternion.identity;
  28. EditorGUILayout.BeginVertical();
  29. EditorGUILayout.PropertyField(this.serializedObject.FindProperty("filenamePrefix"));
  30. EditorGUILayout.PropertyField(this.serializedObject.FindProperty("faceWidth"));
  31. EditorGUILayout.PropertyField(this.serializedObject.FindProperty("textureFormat"));
  32. EditorGUILayout.PropertyField(this.serializedObject.FindProperty("exportFaces"));
  33. if (settings.filenamePrefix == null || settings.filenamePrefix.Length <= 0) {
  34. settings.filenamePrefix = RenderCloudCubemap.kDefaultFilenamePrefix;
  35. }
  36. // Stamp the texture format so it's easier for user to select Sky Studio cloud type later.
  37. string scenePath = Path.GetDirectoryName(SceneManager.GetActiveScene().path);
  38. string filenamePrefix = scenePath + "/" + settings.filenamePrefix + "-" + settings.textureFormat;
  39. if (GUILayout.Button("Render Cubemap")) {
  40. if (settings.textureFormat == RenderCloudCubemap.CubemapTextureFormat.RGBColor) {
  41. Debug.Log("Rendering RGB color cubemap (additive texture)...");
  42. Cubemap cubemap = RenderRGBColor(settings, cam);
  43. RenderCubemapToTexture(cubemap, settings.faceWidth, Color.black, TextureFormat.RGB24,
  44. settings.exportFaces, filenamePrefix, false);
  45. } else if (settings.textureFormat == RenderCloudCubemap.CubemapTextureFormat.RGBAColor) {
  46. Debug.Log("Rendering RGBA color cubemap (alpha texture)...");
  47. Cubemap cubemap = RenderRGBAColor(settings, cam);
  48. RenderCubemapToTexture(cubemap, settings.faceWidth, Color.clear, TextureFormat.RGBA32,
  49. settings.exportFaces, filenamePrefix, true);
  50. } else if (settings.textureFormat == RenderCloudCubemap.CubemapTextureFormat.RGBALit) {
  51. Debug.Log("Rendering RGBA normal lit cubemap (normals encoded)...");
  52. Cubemap cubemap = RenderRGBANormal(settings, cam);
  53. RenderCubemapToTexture(cubemap, settings.faceWidth, Color.clear, TextureFormat.RGBA32,
  54. settings.exportFaces, filenamePrefix, false);
  55. } else {
  56. Debug.LogError("Invalid texture format, can't render cubemap.");
  57. return;
  58. }
  59. }
  60. EditorGUILayout.EndVertical();
  61. this.serializedObject.ApplyModifiedProperties();
  62. }
  63. private Cubemap RenderRGBColor(RenderCloudCubemap settings, Camera cam)
  64. {
  65. Cubemap cubemap = new Cubemap(settings.faceWidth, TextureFormat.RGB24, false);
  66. cam.ResetReplacementShader();
  67. cam.backgroundColor = Color.black;
  68. cam.RenderToCubemap(cubemap);
  69. cam.targetTexture = null;
  70. return cubemap;
  71. }
  72. private Cubemap RenderRGBAColor(RenderCloudCubemap settings, Camera cam)
  73. {
  74. Cubemap cubemap = new Cubemap(settings.faceWidth, TextureFormat.RGBA32, false);
  75. cam.ResetReplacementShader();
  76. cam.backgroundColor = Color.clear;
  77. cam.RenderToCubemap(cubemap);
  78. cam.targetTexture = null;
  79. return cubemap;
  80. }
  81. private Cubemap RenderRGBANormal(RenderCloudCubemap settings, Camera cam)
  82. {
  83. Cubemap cubemap = new Cubemap(settings.faceWidth, TextureFormat.RGBA32, false);
  84. Shader normalShader = Shader.Find("Funly/Sky Studio/Utility/World Normal");
  85. cam.backgroundColor = Color.clear;
  86. cam.SetReplacementShader(normalShader, "");
  87. cam.RenderToCubemap(cubemap);
  88. cam.ResetReplacementShader();
  89. cam.targetTexture = null;
  90. return cubemap;
  91. }
  92. private Texture RenderCubemapToTexture(Cubemap cubemap, int faceSize, Color clearColor,
  93. TextureFormat textureFormat, bool exportFaces, string assetPathPrefix, bool alphaIsTransparency)
  94. {
  95. CubeFaceData[] faces = {
  96. new CubeFaceData(CubemapFace.NegativeX, new Vector2(0, faceSize)),
  97. new CubeFaceData(CubemapFace.PositiveX, new Vector2(faceSize * 2, faceSize)),
  98. new CubeFaceData(CubemapFace.PositiveY, new Vector2(faceSize, faceSize * 2)),
  99. new CubeFaceData(CubemapFace.NegativeY, new Vector2(faceSize, 0)),
  100. new CubeFaceData(CubemapFace.PositiveZ, new Vector2(faceSize, faceSize)),
  101. new CubeFaceData(CubemapFace.NegativeZ, new Vector2(faceSize * 3, faceSize))
  102. };
  103. RenderTexture oldRt = RenderTexture.active;
  104. Texture2D faceTex = new Texture2D(faceSize, faceSize, TextureFormat.RGBA32, false);
  105. RenderTexture faceRenderTex = new RenderTexture(faceSize, faceSize, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
  106. faceRenderTex.Create();
  107. RenderTexture flatCubeTex = new RenderTexture(faceSize * 4, faceSize * 3, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
  108. flatCubeTex.Create();
  109. Material flipMat = new Material(Shader.Find("Funly/Sky Studio/Utility/Flip Image"));
  110. Material blitMat = new Material(Shader.Find("Unlit/Transparent"));
  111. RenderTexture.active = flatCubeTex;
  112. GL.PushMatrix();
  113. GL.LoadPixelMatrix(0, flatCubeTex.width, flatCubeTex.height, 0);
  114. GL.Clear(true, true, new Color(0.0f, 0.0f, 0.0f, 0.0f));
  115. GL.PopMatrix();
  116. RenderTexture.active = null;
  117. for (int i = 0; i < faces.Length; i++) {
  118. CubeFaceData data = faces[i];
  119. // Pull a face texture out of the cubemap.
  120. Color[] pixels = cubemap.GetPixels(data.face);
  121. faceTex.SetPixels(pixels);
  122. faceTex.Apply();
  123. // Flip the image.
  124. RenderTexture.active = faceRenderTex;
  125. GL.PushMatrix();
  126. GL.LoadPixelMatrix(0, faceRenderTex.width, flatCubeTex.height, 0);
  127. Graphics.Blit(faceTex, faceRenderTex, flipMat, 0);
  128. GL.PopMatrix();
  129. if (exportFaces) {
  130. string path = assetPathPrefix + data.face.ToString() + ".png";
  131. SkyEditorUtility.WriteTextureToFile(faceRenderTex, path, textureFormat);
  132. RenderTexture.active = null;
  133. AssetDatabase.ImportAsset(path);
  134. }
  135. RenderTexture.active = null;
  136. // Target our cubemap, and render the flipped face into it.
  137. RenderTexture.active = flatCubeTex;
  138. GL.PushMatrix();
  139. GL.LoadPixelMatrix(0, flatCubeTex.width, flatCubeTex.height, 0);
  140. Graphics.DrawTexture(new Rect(data.offset.x, data.offset.y, faceSize, faceSize), faceRenderTex, blitMat);
  141. // Write the final texture on last face.
  142. if (i == faces.Length - 1) {
  143. string path = assetPathPrefix + ".png";
  144. Debug.Log("Exporting cubemap to compressed texture at path: " + path);
  145. SkyEditorUtility.WriteTextureToFile(flatCubeTex, path, textureFormat);
  146. RenderTexture.active = null;
  147. AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
  148. // Adjust texture settings.
  149. TextureImporter importer = TextureImporter.GetAtPath(path) as TextureImporter;
  150. importer.textureShape = TextureImporterShape.TextureCube;
  151. importer.alphaIsTransparency = alphaIsTransparency;
  152. AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
  153. }
  154. GL.PopMatrix();
  155. RenderTexture.active = null;
  156. }
  157. RenderTexture.active = oldRt;
  158. return flatCubeTex;
  159. }
  160. }
  161. }