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; } } }