MaterialGraphPreviewGenerator.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. using System;
  2. using UnityEditor.SceneManagement;
  3. using UnityEngine;
  4. using UnityEngine.Rendering;
  5. using UnityEngine.SceneManagement;
  6. namespace UnityEditor.ShaderGraph.Drawing
  7. {
  8. class MaterialGraphPreviewGenerator : IDisposable
  9. {
  10. private readonly Scene m_Scene;
  11. static Mesh s_Quad;
  12. private Camera m_Camera;
  13. private Light Light0 { get; set; }
  14. private Light Light1 { get; set; }
  15. private Material m_CheckerboardMaterial;
  16. private static readonly Mesh[] s_Meshes = { null, null, null, null, null };
  17. private static readonly GUIContent[] s_MeshIcons = { null, null, null, null, null };
  18. private static readonly GUIContent[] s_LightIcons = { null, null };
  19. private static readonly GUIContent[] s_TimeIcons = { null, null };
  20. protected static GameObject CreateLight()
  21. {
  22. GameObject lightGO = EditorUtility.CreateGameObjectWithHideFlags("PreRenderLight", HideFlags.HideAndDontSave, typeof(Light));
  23. var light = lightGO.GetComponent<Light>();
  24. light.type = LightType.Directional;
  25. light.intensity = 1.0f;
  26. light.enabled = false;
  27. return lightGO;
  28. }
  29. public MaterialGraphPreviewGenerator()
  30. {
  31. m_Scene = EditorSceneManager.NewPreviewScene();
  32. var camGO = EditorUtility.CreateGameObjectWithHideFlags("Preview Scene Camera", HideFlags.HideAndDontSave, typeof(Camera));
  33. SceneManager.MoveGameObjectToScene(camGO, m_Scene);
  34. m_Camera = camGO.GetComponent<Camera>();
  35. EditorUtility.SetCameraAnimateMaterials(m_Camera, true);
  36. m_Camera.cameraType = CameraType.Preview;
  37. m_Camera.enabled = false;
  38. m_Camera.clearFlags = CameraClearFlags.Depth;
  39. m_Camera.fieldOfView = 15;
  40. m_Camera.farClipPlane = 10.0f;
  41. m_Camera.nearClipPlane = 2.0f;
  42. m_Camera.backgroundColor = new Color(49.0f / 255.0f, 49.0f / 255.0f, 49.0f / 255.0f, 1.0f);
  43. // Explicitly use forward rendering for all previews
  44. // (deferred fails when generating some static previews at editor launch; and we never want
  45. // vertex lit previews if that is chosen in the player settings)
  46. m_Camera.renderingPath = RenderingPath.Forward;
  47. m_Camera.useOcclusionCulling = false;
  48. m_Camera.scene = m_Scene;
  49. var l0 = CreateLight();
  50. SceneManager.MoveGameObjectToScene(l0, m_Scene);
  51. //previewScene.AddGameObject(l0);
  52. Light0 = l0.GetComponent<Light>();
  53. var l1 = CreateLight();
  54. SceneManager.MoveGameObjectToScene(l1, m_Scene);
  55. //previewScene.AddGameObject(l1);
  56. Light1 = l1.GetComponent<Light>();
  57. Light0.color = new Color(0.769f, 0.769f, 0.769f, 1); // SceneView.kSceneViewFrontLight
  58. Light1.transform.rotation = Quaternion.Euler(340, 218, 177);
  59. Light1.color = new Color(.4f, .4f, .45f, 0f) * .7f;
  60. m_CheckerboardMaterial = new Material(Shader.Find("Hidden/Checkerboard"));
  61. m_CheckerboardMaterial.shader.hideFlags = HideFlags.HideAndDontSave;
  62. m_CheckerboardMaterial.hideFlags = HideFlags.HideAndDontSave;
  63. if (s_Meshes[0] == null)
  64. {
  65. var handleGo = (GameObject)EditorGUIUtility.LoadRequired("Previews/PreviewMaterials.fbx");
  66. // @TODO: temp workaround to make it not render in the scene
  67. handleGo.SetActive(false);
  68. foreach (Transform t in handleGo.transform)
  69. {
  70. var meshFilter = t.GetComponent<MeshFilter>();
  71. switch (t.name)
  72. {
  73. case "sphere":
  74. s_Meshes[0] = meshFilter.sharedMesh;
  75. break;
  76. case "cube":
  77. s_Meshes[1] = meshFilter.sharedMesh;
  78. break;
  79. case "cylinder":
  80. s_Meshes[2] = meshFilter.sharedMesh;
  81. break;
  82. case "torus":
  83. s_Meshes[3] = meshFilter.sharedMesh;
  84. break;
  85. default:
  86. Debug.LogWarning("Something is wrong, weird object found: " + t.name);
  87. break;
  88. }
  89. }
  90. s_MeshIcons[0] = EditorGUIUtility.IconContent("PreMatSphere");
  91. s_MeshIcons[1] = EditorGUIUtility.IconContent("PreMatCube");
  92. s_MeshIcons[2] = EditorGUIUtility.IconContent("PreMatCylinder");
  93. s_MeshIcons[3] = EditorGUIUtility.IconContent("PreMatTorus");
  94. s_MeshIcons[4] = EditorGUIUtility.IconContent("PreMatQuad");
  95. s_LightIcons[0] = EditorGUIUtility.IconContent("PreMatLight0");
  96. s_LightIcons[1] = EditorGUIUtility.IconContent("PreMatLight1");
  97. s_TimeIcons[0] = EditorGUIUtility.IconContent("PlayButton");
  98. s_TimeIcons[1] = EditorGUIUtility.IconContent("PauseButton");
  99. Mesh quadMesh = Resources.GetBuiltinResource(typeof(Mesh), "Quad.fbx") as Mesh;
  100. s_Meshes[4] = quadMesh;
  101. }
  102. }
  103. public static Mesh quad
  104. {
  105. get
  106. {
  107. if (s_Quad != null)
  108. return s_Quad;
  109. var vertices = new[]
  110. {
  111. new Vector3(-1f, -1f, 0f),
  112. new Vector3(1f, 1f, 0f),
  113. new Vector3(1f, -1f, 0f),
  114. new Vector3(-1f, 1f, 0f)
  115. };
  116. var uvs = new[]
  117. {
  118. new Vector2(0f, 0f),
  119. new Vector2(1f, 1f),
  120. new Vector2(1f, 0f),
  121. new Vector2(0f, 1f)
  122. };
  123. var indices = new[] { 0, 1, 2, 1, 0, 3 };
  124. s_Quad = new Mesh
  125. {
  126. vertices = vertices,
  127. uv = uvs,
  128. triangles = indices
  129. };
  130. s_Quad.RecalculateNormals();
  131. s_Quad.RecalculateBounds();
  132. return s_Quad;
  133. }
  134. }
  135. public void DoRenderPreview(RenderTexture renderTexture, Material mat, Mesh mesh, PreviewMode mode, bool allowSRP, float time, MaterialPropertyBlock properties = null)
  136. {
  137. if (mat == null || mat.shader == null)
  138. return;
  139. m_Camera.targetTexture = renderTexture;
  140. if (mode == PreviewMode.Preview3D)
  141. {
  142. m_Camera.transform.position = -Vector3.forward * 5;
  143. m_Camera.transform.rotation = Quaternion.identity;
  144. m_Camera.orthographic = false;
  145. }
  146. else
  147. {
  148. m_Camera.transform.position = -Vector3.forward * 2;
  149. m_Camera.transform.rotation = Quaternion.identity;
  150. m_Camera.orthographicSize = 1;
  151. m_Camera.orthographic = true;
  152. }
  153. m_Camera.targetTexture = renderTexture;
  154. var previousRenderTexure = RenderTexture.active;
  155. RenderTexture.active = renderTexture;
  156. GL.Clear(true, true, Color.black);
  157. Graphics.Blit(Texture2D.whiteTexture, renderTexture, m_CheckerboardMaterial);
  158. EditorUtility.SetCameraAnimateMaterialsTime(m_Camera, time);
  159. Light0.enabled = true;
  160. Light0.intensity = 1.0f;
  161. Light0.transform.rotation = Quaternion.Euler(50f, 50f, 0);
  162. Light1.enabled = true;
  163. Light1.intensity = 1.0f;
  164. m_Camera.clearFlags = CameraClearFlags.Depth;
  165. Mesh previewMesh = mesh == null ? s_Meshes[0] : mesh;
  166. Graphics.DrawMesh(
  167. mode == PreviewMode.Preview3D ? previewMesh : quad,
  168. mode == PreviewMode.Preview3D ? Matrix4x4.TRS(-previewMesh.bounds.center, Quaternion.identity, Vector3.one) : Matrix4x4.identity,
  169. mat,
  170. 1,
  171. m_Camera,
  172. 0,
  173. properties,
  174. ShadowCastingMode.Off,
  175. false,
  176. null,
  177. false);
  178. var oldAllowPipes = Unsupported.useScriptableRenderPipeline;
  179. Unsupported.useScriptableRenderPipeline = allowSRP;
  180. m_Camera.Render();
  181. Unsupported.useScriptableRenderPipeline = oldAllowPipes;
  182. RenderTexture.active = previousRenderTexure;
  183. Light0.enabled = false;
  184. Light1.enabled = false;
  185. }
  186. public void Dispose()
  187. {
  188. if (Light0 != null)
  189. {
  190. UnityEngine.Object.DestroyImmediate(Light0.gameObject);
  191. Light0 = null;
  192. }
  193. if (Light1 != null)
  194. {
  195. UnityEngine.Object.DestroyImmediate(Light1.gameObject);
  196. Light1 = null;
  197. }
  198. if (m_Camera != null)
  199. {
  200. UnityEngine.Object.DestroyImmediate(m_Camera.gameObject);
  201. m_Camera = null;
  202. }
  203. if (m_CheckerboardMaterial != null)
  204. {
  205. UnityEngine.Object.DestroyImmediate(m_CheckerboardMaterial);
  206. m_CheckerboardMaterial = null;
  207. }
  208. EditorSceneManager.ClosePreviewScene(m_Scene);
  209. }
  210. }
  211. }