private static string GetShaderName(ShaderGeneratorDescriptor generatorDesc, FractalTypeDescriptor fractalDesc) { string shaderStr = string.Format("{0}/{1}{2}", generatorDesc.shaderCategory, generatorDesc.name, fractalDesc.name); return(shaderStr); }
/// <summary> /// Forces the generation of any shaders that make use of generated noise header files. Gathers all /// the NoiseShaderGenerators and generates shaders based on the ".noisehlsltemplate" file /// provided by that particular NoiseShaderGenerator implementation /// </summary> public static void GenerateShaders() { System.Globalization.CultureInfo prevCultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture; System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; GatherGenerators(); IFractalType[] fractalTypes = s_fractalTypes; INoiseType[] noiseTypes = s_noiseTypes; Dictionary <Type, INoiseShaderGenerator> generators = s_generators; StringBuilder shaderSB = new StringBuilder(); StringBuilder passesSB = new StringBuilder(); foreach (KeyValuePair <Type, INoiseShaderGenerator> pair in generators) { shaderSB.Clear(); passesSB.Clear(); string shaderTemplateStr = null; INoiseShaderGenerator generator = pair.Value; ShaderGeneratorDescriptor generatorDesc = generator.GetDescription(); if (!File.Exists(generatorDesc.templatePath)) { Debug.LogError("Could not find specified template file for noise shader generator: " + generator); continue; } // load contents of shader template using (StreamReader sr = new StreamReader(generatorDesc.templatePath)) { shaderTemplateStr = sr.ReadToEnd(); } // find the pass template using regex matching Match passTemplateMatch = Regex.Match(shaderTemplateStr, Strings.k_regexPassTemplate1); if (!passTemplateMatch.Success) { Debug.LogError($"Could not find pass template in {generatorDesc.templatePath}. Skipping noise shader generation for this generator type!!"); continue; } string passTemplateStr = passTemplateMatch.Value; // generate shaders for each fractal type foreach (IFractalType fractal in fractalTypes) { FractalTypeDescriptor fractalDesc = fractal.GetDescription(); string fullShaderCategory = GetShaderName(generatorDesc, fractalDesc); shaderSB.Append(NoiseLib.Strings.k_warningHeader); shaderSB.Append(shaderTemplateStr); shaderSB.Replace(NoiseLib.Strings.k_tagShaderCategory, $"\"{fullShaderCategory}\""); // add passes for each noise type foreach (INoiseType noise in noiseTypes) { GeneratedShaderInfo info = new GeneratedShaderInfo(fractal, noise); // add to passes string builer passesSB.Append(passTemplateStr); passesSB.AppendLine(); passesSB.Replace(NoiseLib.Strings.k_tagIncludes, string.Format("#include \"{0}\"", info.generatedIncludePath)); info.ReplaceTags(passesSB); } // replace template with generated passes string newContents = Regex.Replace(shaderSB.ToString(), Strings.k_regexPassTemplate2, passesSB.ToString()); newContents = newContents.Replace(NoiseLib.Strings.k_tagFractalName, fractalDesc.name); // load shader contents from disk if it exists string fileName = string.Format("{0}{1}.shader", generatorDesc.name, fractalDesc.name); string filePath = string.Format("{0}/{1}", generatorDesc.outputDir, fileName); if (!Directory.Exists(generatorDesc.outputDir)) { Directory.CreateDirectory(generatorDesc.outputDir); } string currentContents = null; FileInfo fi = new FileInfo(filePath); if (File.Exists(filePath)) { using (StreamReader sr = new StreamReader(filePath)) { currentContents = sr.ReadToEnd(); currentContents = NormalizeLineEndings(currentContents); } } // do some code cleanup newContents = Regex.Replace(newContents, NoiseLib.Strings.k_regexDupCommas, ", "); newContents = Regex.Replace(newContents, NoiseLib.Strings.k_emptyArgsRight, " )"); newContents = Regex.Replace(newContents, NoiseLib.Strings.k_emptyArgsLeft, "( "); newContents = NormalizeLineEndings(newContents); // only write to file if it is not read-only, ie. if it is one of the generated // shader files that we ship with the TerrainTools package if (!fi.IsReadOnly) { if (currentContents == null || currentContents.CompareTo(newContents) != 0) { try { using (StreamWriter sw = new StreamWriter(filePath)) { sw.Write(newContents); } } catch (Exception) { // restore previous cultureinfo System.Threading.Thread.CurrentThread.CurrentCulture = prevCultureInfo; } } } shaderSB.Clear(); passesSB.Clear(); } } // restore previous cultureinfo System.Threading.Thread.CurrentThread.CurrentCulture = prevCultureInfo; UnityEditor.AssetDatabase.Refresh(); }