internal void OnBakeTexture() { var graph = owner as GraphData; if (graph == null) { Debug.LogError("BakeTextureNode's owner isn't a AbstractMaterialGraph, how is it possible ?"); } // from https://github.com/Unity-Technologies/ScriptableRenderPipeline/commit/3b28421204badded8c0d14315f10c256de3345a0#diff-52bd31870846010ea070163214aac090 graph.GetShader(this, GenerationMode.Preview, "hidden/preview"); BakeShaderData shaderData = new BakeShaderData(); shaderData.ShaderString = graph.GetPreviewShader(this).shader; shaderData.Shader = ShaderUtil.CreateShaderAsset(shaderData.ShaderString); shaderData.Node = this; shaderData.Graph = graph; shaderData.HasError = false; // TODO handle shader errors shaderData.OutputIdName = "Out"; BakeTextureManager.BakeShaderIntoTexture(shaderData); }
internal static void BakeShaderIntoTexture(BakeShaderData shaderData) { var node = shaderData.Node; var renderTexture = new RenderTexture(node.Width, node.Height, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default) { hideFlags = HideFlags.HideAndDontSave }; renderTexture.Create(); // setup mesh Mesh quadMesh = Resources.GetBuiltinResource(typeof(Mesh), "Quad.fbx") as Mesh; Material bakeMaterial = new Material(shaderData.Shader); // setup camera GameObject cameraGo = new GameObject(); var camera = cameraGo.AddComponent <Camera>(); camera.cameraType = CameraType.Preview; camera.enabled = false; camera.clearFlags = CameraClearFlags.Depth; camera.fieldOfView = 15; camera.farClipPlane = 10.0f; camera.nearClipPlane = 2.0f; camera.backgroundColor = new Color(49.0f / 255.0f, 49.0f / 255.0f, 49.0f / 255.0f, 1.0f); camera.renderingPath = RenderingPath.Forward; camera.useOcclusionCulling = false; camera.clearFlags = CameraClearFlags.Depth; camera.transform.position = -Vector3.forward * 2; camera.transform.rotation = Quaternion.identity; camera.orthographicSize = 0.5f; camera.orthographic = true; camera.targetTexture = renderTexture; // setup material and fill properties from all the previous nodes HashSet <Identifier> propertyNodes = new HashSet <Identifier> { node.tempId }; PropagateNodeSet(propertyNodes, new List <Identifier> { node.tempId }, shaderData.Graph); MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock(); materialPropertyBlock.SetFloat(shaderData.OutputIdName, node.tempId.index); List <PreviewProperty> previewProperties = new List <PreviewProperty>(); node.CollectPreviewMaterialProperties(previewProperties); foreach (var id in propertyNodes) { var tempNode = shaderData.Graph.GetNodeFromTempId(id) as AbstractMaterialNode; if (tempNode == null) { continue; } tempNode.CollectPreviewMaterialProperties(previewProperties); foreach (var prop in shaderData.Graph.properties) { previewProperties.Add(prop.GetPreviewMaterialProperty()); } foreach (var previewProperty in previewProperties) { // from https://github.com/Unity-Technologies/ScriptableRenderPipeline/commit/3b28421204badded8c0d14315f10c256de3345a0#diff-52bd31870846010ea070163214aac090 bakeMaterial.SetPreviewProperty(previewProperty); } previewProperties.Clear(); } // draw the quad into the camera's render texture Graphics.DrawMesh(quadMesh, Matrix4x4.identity, bakeMaterial, 1, camera, 0, materialPropertyBlock, ShadowCastingMode.Off, false, null, false); camera.Render(); // get the render texture from GPU to CPU and save it as an asset Texture2D texture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGB24, false); RenderTexture.active = renderTexture; texture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0); texture.Apply(); var textureBytes = texture.EncodeToPNG(); string path = ""; bool textureFound = false; if (node.OutputTexture != null && AssetDatabase.Contains(node.OutputTexture)) { try { path = AssetDatabase.GetAssetPath(node.OutputTexture); System.IO.File.WriteAllBytes(path, textureBytes); AssetDatabase.ImportAsset(path); textureFound = true; } catch (Exception e) { Debug.LogException(e); } } if (!textureFound) { path = Application.dataPath + "/" + DefaultPath; System.IO.File.WriteAllBytes(path, textureBytes); path = "Assets/" + DefaultPath; AssetDatabase.ImportAsset(path); Debug.LogWarning("No previous baked texture was found so a new one was created at Assets/" + DefaultPath + ". Please rename or move the texture as this specific texture path might be overriden."); } node.OutputTexture = (Texture2D)AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)); // cleanup RenderTexture.active = null; UnityEngine.Object.DestroyImmediate(cameraGo); UnityEngine.Object.DestroyImmediate(bakeMaterial); }