Ejemplo n.º 1
0
        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);
        }