static void bakeShaderLayerSubAssets(ShaderLayer shaderLayer, TextureRecipe recipe, List <string> subAssetPaths) { var shader = ShaderGenerator.bakeShader(shaderLayer, recipe); if (null == shader) { UnityEngine.Debug.LogError("Failed to load shader " + shaderLayer.name); return; } subAssetPaths.Add(shader.name); foreach (var node in shaderLayer.nodes) { if (!node.assetsDirty) { continue; } var nodeAssetGenerator = GeneratorFactory.getAssetGenerator(node); if (null != nodeAssetGenerator) { var newAssetPaths = nodeAssetGenerator.generateAssets(node); if (newAssetPaths.Count > 0) { subAssetPaths.AddRange(newAssetPaths); } node.assetsDirty = false; } } }
public void renderRecipeInternal() { foreach (var obj in renderObjectList) { obj.SetActive(true); } foreach (var layer in recipe.layerList) { //TODO: layer abstraction if (layer is ShaderLayer) { ShaderLayer shaderLayer = (ShaderLayer)layer; shaderLayer.root.setParameters(renderMaterials[shaderLayer]); } else if (layer is TextLayer) { TextLayer textLayer = (TextLayer)layer; textLayer.preRender(textObjects[textLayer]); } } RenderTexture.active = renderTexture; renderCamera.targetTexture = renderTexture; renderCamera.Render(); renderCamera.targetTexture = null; foreach (var obj in renderObjectList) { obj.SetActive(false); } }
private static string getCalls(ShaderLayer shaderLayer) { Dictionary <string, string> outputVariableNames = new Dictionary <string, string>(); string nodeCalls = ""; var rootInput = shaderLayer.getRoot().inputs[0]; if (rootInput.inputNode != null) { nodeCalls += GeneratorFactory.getShaderGenerator(rootInput.inputNode).getCallStr(rootInput, outputVariableNames); nodeCalls += "col = out" + rootInput.inputNode.GetType().Name + rootInput.inputNode.getNodeID() + "_" + rootInput.outputIndex + ";"; } return(nodeCalls); }
private static List <string> getNodeStrings(ShaderLayer shaderLayer, NodeGenDelegate genDelegate) { List <string> nodeInputs = new List <string>(); var rootInputs = shaderLayer.getRoot().inputs; if ((rootInputs.Count == 0) || (rootInputs[0].inputNode == null)) { return(nodeInputs); } List <BaseNode.NodeInput> nodeList = new List <BaseNode.NodeInput>(); Queue <BaseNode.NodeInput> nodeStack = new Queue <BaseNode.NodeInput>(); nodeStack.Enqueue(shaderLayer.getRoot().inputs[0]); while (nodeStack.Count > 0) { BaseNode.NodeInput node = nodeStack.Dequeue(); if (!nodeList.Contains(node)) { nodeList.Add(node); int numInputs = node.inputNode.inputs.Count; for (int i = 0; i < numInputs; i++) { var nodeInput = node.inputNode.inputs[i]; if (nodeInput.inputNode != null) { nodeStack.Enqueue(nodeInput); } } nodeInputs.Add(genDelegate(node)); } } return(nodeInputs); }
public static string getShaderName(TextureRecipe recipe, ShaderLayer shaderLayer) { return(recipe.unique_id + "-" + recipe.name + "-" + shaderLayer.layerName); }
public static string getShaderPath(TextureRecipe recipe, ShaderLayer shaderLayer) { return("TextureKit/" + getShaderName(recipe, shaderLayer)); }
private static List <string> getInputs(ShaderLayer shaderLayer) { return(getNodeStrings(shaderLayer, getNodeInputStr)); }
private static List <string> getProperties(ShaderLayer shaderLayer) { return(getNodeStrings(shaderLayer, getNodePropertyStr)); }
private static List <string> getFunctions(ShaderLayer shaderLayer) { return(getNodeStrings(shaderLayer, getNodeFunctionStr)); }
public static Shader bakeShader(ShaderLayer shaderLayer, TextureRecipe recipe) { TextAsset shaderBaseText = (TextAsset)Resources.Load("template.shader"); if (shaderBaseText == null) { Debug.LogError("Failed to template shader"); return(null); } string shaderName = ShaderLayer.getShaderName(recipe, shaderLayer); string shaderPath = ShaderLayer.getShaderPath(recipe, shaderLayer); string shaderText = shaderBaseText.text; List <string> lines = shaderText.Split('\n').ToList <string>(); int numLines = lines.Count; for (int i = 0; i < numLines; i++) { string line = lines[i]; if (line.Contains("$$")) { if (line.Contains("$$ASSETNAME")) { line = line.Replace("$$ASSETNAME", shaderPath); lines[i] = line; } else if (line.Contains("$$STARTFUNCS")) { var funcs = getFunctions(shaderLayer); lines.InsertRange(i + 1, funcs); i += funcs.Count; numLines = lines.Count; } else if (line.Contains("$$STARTPROPS")) { var props = getProperties(shaderLayer); lines.InsertRange(i + 1, props); i += props.Count; numLines = lines.Count; } else if (line.Contains("$$STARTINPUTS")) { var inputs = getInputs(shaderLayer); lines.InsertRange(i + 1, inputs); i += inputs.Count; numLines = lines.Count; } else if (line.Contains("$$STARTSHADER")) { lines.Insert(i + 1, getCalls(shaderLayer)); numLines = lines.Count; i++; } } } string baseAssetPath = "Assets/TextureRecipes/Resources/"; string shaderAssetPath = baseAssetPath + shaderName + ".shader"; //Can't do this because we want to overwrite an existing asset! shaderPath = AssetDatabase.GenerateUniqueAssetPath(shaderPath); //Generating the text for the shader is a very fast operation. Rather than trying to figure out which changes //would have altered the shader, we simply generate the shader as a byproduct of every change, and then see //if it has changed since the last time we output it. The really expensive part is outputting the shader and //triggering the Unity shader post-process and compilation steps (we're talking >1.5s vs 3ms). string[] existingLines = null; existingShaderLines.TryGetValue(shaderPath, out existingLines); string[] newLines = lines.ToArray(); if (existingLines != null) { if (existingLines.Length == newLines.Length) { bool allMatch = true; for (int i = 0; allMatch && (i < newLines.Length); i++) { if (existingLines[i] != newLines[i]) { allMatch = false; } } if (allMatch) { return(Shader.Find(shaderPath)); } } } //File.WriteAllLines(shaderAssetPath, newLines); using (StreamWriter writer = new StreamWriter(shaderAssetPath, false)) { writer.NewLine = "\n"; foreach (string str in newLines) { writer.WriteLine(str); } } existingShaderLines[shaderPath] = newLines; AssetDatabase.Refresh(); return(Shader.Find(shaderPath)); }
public void renderSetup(Texture2D textureTarget = null) { renderMaterials.Clear(); textObjects.Clear(); renderOffsetX += 10.0f; renderTextureTarget = textureTarget; if (textureTarget != null) { renderTexture = new RenderTexture(textureTarget.width, textureTarget.height, 0); } else { renderTexture = new RenderTexture(recipe.TextureWidth, recipe.TextureHeight, 0); } GameObject renderCameraObject = new GameObject(); renderCamera = renderCameraObject.AddComponent <Camera>(); renderCamera.backgroundColor = Color.black; renderCamera.orthographic = true; renderCamera.orthographicSize = 5; renderCamera.transform.localPosition = new Vector3(renderOffsetX, 0, 0); renderCamera.transform.localRotation = Quaternion.Euler(new Vector3(90.0f, 0.0f, 0.0f)); renderCamera.cullingMask = 1 << recipe.RenderLayer; renderCameraObject.layer = recipe.RenderLayer; renderObjectList.Add(renderCameraObject); foreach (var layer in recipe.layerList) { //TODO: layer abstraction if (layer is ShaderLayer) { ShaderLayer shaderLayer = (ShaderLayer)layer; GameObject renderPlane = GameObject.CreatePrimitive(PrimitiveType.Plane); renderPlane.transform.localPosition = new Vector3(renderOffsetX, -10, 0); renderPlane.transform.localRotation = Quaternion.Euler(new Vector3(0, 180, 0)); renderPlane.layer = recipe.RenderLayer; renderObjectList.Add(renderPlane); string shaderPath = ShaderLayer.getShaderPath(recipe, shaderLayer); Shader shaderAsset = Shader.Find(shaderPath); if (null == shaderAsset) { Debug.LogError("Failed to get shader at " + shaderPath); continue; } Material layerMaterial = new Material(shaderAsset); renderMaterials[shaderLayer] = layerMaterial; renderPlane.GetComponent <MeshRenderer>().material = layerMaterial; } else if (layer is TextLayer) { var textLayer = (TextLayer)layer; GameObject txtObject = new GameObject(); txtObject.transform.localPosition = new Vector3(textLayer.position.x + renderOffsetX, -5, textLayer.position.y); txtObject.transform.localRotation = Quaternion.Euler(new Vector3(90, 0, 0)); txtObject.layer = recipe.RenderLayer; renderObjectList.Add(txtObject); var textMesh = txtObject.AddComponent <TextMesh>(); textMesh.font = textLayer.font; textMesh.text = textLayer.text; textMesh.color = textLayer.textColor; textMesh.fontSize = textLayer.fontSize; textMesh.characterSize = textLayer.characterSize; textMesh.anchor = textLayer.anchor; textObjects[textLayer] = txtObject; //If the material isn't set the text won't appear MeshRenderer rend = txtObject.GetComponentInChildren <MeshRenderer>(); rend.material = textMesh.font.material; } } }