public void WriteShaderHeader(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader) { sb.AppendLine(" SubShader {"); sb.Append(" Tags{\"RenderPipeline\"=\"HDRenderPipeline\" \"RenderType\" = \"HDLitShader\" \"Queue\" = \"Geometry+100\" "); if (features.Contains("_MAX4TEXTURES")) { sb.Append("\"SplatCount\" = \"4\""); } else if (features.Contains("_MAX8TEXTURES")) { sb.Append("\"SplatCount\" = \"8\""); } else if (features.Contains("_MAX12TEXTURES")) { sb.Append("\"SplatCount\" = \"12\""); } else if (features.Contains("_MAX20TEXTURES")) { sb.Append("\"SplatCount\" = \"20\""); } else if (features.Contains("_MAX24TEXTURES")) { sb.Append("\"SplatCount\" = \"24\""); } else if (features.Contains("_MAX28TEXTURES")) { sb.Append("\"SplatCount\" = \"28\""); } else if (features.Contains("_MAX32TEXTURES")) { sb.Append("\"SplatCount\" = \"32\""); } else { sb.Append("\"SplatCount\" = \"16\""); } sb.AppendLine("}"); }
public void WriteShaderFooter(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader, string baseName) { if (auxShader != null && !string.IsNullOrEmpty(auxShader.customEditor)) { sb.AppendLine(" CustomEditor \"" + auxShader.customEditor + "\""); } else if (auxShader != null) { } else if (baseName != null) { if (features.Contains("_MICROTERRAIN")) { sb.AppendLine(" Dependency \"BaseMapShader\" = \"" + baseName + "\""); } sb.AppendLine(" CustomEditor \"MicroSplatShaderGUI\""); } sb.AppendLine(" Fallback \"Nature/Terrain/Diffuse\""); sb.Append("}"); }
static Material SetupMaterial(Material mat, MicroSplatBaseFeatures.DebugOutput debugOutput) { MicroSplatShaderGUI.MicroSplatCompiler comp = new MicroSplatShaderGUI.MicroSplatCompiler(); List <string> keywords = new List <string>(mat.shaderKeywords); RemoveKeyword(keywords, "_SNOW"); RemoveKeyword(keywords, "_TESSDISTANCE"); RemoveKeyword(keywords, "_WINDPARTICULATE"); RemoveKeyword(keywords, "_SNOWPARTICULATE"); RemoveKeyword(keywords, "_GLITTER"); RemoveKeyword(keywords, "_SNOWGLITTER"); keywords.Add(FeatureFromOutput(debugOutput).ToString()); string shader = comp.Compile(keywords.ToArray(), "RenderBake_" + debugOutput.ToString()); Shader s = ShaderUtil.CreateShaderAsset(shader); Material renderMat = new Material(mat); renderMat.shader = s; return(renderMat); }
public void WriteShaderHeader(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, bool blend) { sb.AppendLine(); sb.AppendLine(" CGINCLUDE"); if (features.Contains <string>("_BDRF1") || features.Contains <string>("_BDRF2") || features.Contains <string>("_BDRF3")) { if (features.Contains <string>("_BDRF1")) { sb.AppendLine(" #define UNITY_BRDF_PBS BRDF1_Unity_PBS"); } else if (features.Contains <string>("_BDRF2")) { sb.AppendLine(" #define UNITY_BRDF_PBS BRDF2_Unity_PBS"); } else if (features.Contains <string>("_BDRF3")) { sb.AppendLine(" #define UNITY_BRDF_PBS BRDF3_Unity_PBS"); } } sb.AppendLine(" ENDCG"); sb.AppendLine(); sb.AppendLine(" SubShader {"); sb.AppendLine(" Tags{ \"RenderType\" = \"Opaque\" \"Queue\" = \"Geometry+100\" }"); sb.AppendLine(" Cull Back"); sb.AppendLine(" ZTest LEqual"); if (blend) { sb.AppendLine(" BLEND ONE ONE"); } #if UNITY_2018_3_OR_NEWER sb.AppendLine(" UsePass \"Hidden/Nature/Terrain/Utilities/PICKING\""); sb.AppendLine(" UsePass \"Hidden/Nature/Terrain/Utilities/SELECTION\""); #endif sb.AppendLine(" CGPROGRAM"); }
public void WriteShaderFooter(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, bool blend, string baseName) { if (blend) { sb.AppendLine(" CustomEditor \"MicroSplatBlendableMaterialEditor\""); } else if (baseName != null) { sb.AppendLine(" Dependency \"AddPassShader\" = \"Hidden/MicroSplat/AddPass\""); // for 2018 basemap gen string depName = baseName; if (depName.Contains("Hidden/MicroSplat")) { depName = depName.Substring(depName.IndexOf("Hidden/MicroSplat") + 17); } sb.AppendLine(" Dependency \"BaseMapGenShader\" = \"" + depName + "\""); sb.AppendLine(" Dependency \"BaseMapShader\" = \"" + baseName + "\""); sb.AppendLine(" CustomEditor \"MicroSplatShaderGUI\""); } sb.AppendLine(" Fallback \"Nature/Terrain/Diffuse\""); sb.Append("}"); }
static Material SetupMaterial(MicroSplatKeywords kwds, Material mat, MicroSplatBaseFeatures.DebugOutput debugOutput, bool useDebugTopo) { MicroSplatShaderGUI.MicroSplatCompiler comp = new MicroSplatShaderGUI.MicroSplatCompiler(); List <string> keywords = new List <string>(kwds.keywords); RemoveKeyword(keywords, "_SNOW"); RemoveKeyword(keywords, "_TESSDISTANCE"); RemoveKeyword(keywords, "_WINDPARTICULATE"); RemoveKeyword(keywords, "_SNOWPARTICULATE"); RemoveKeyword(keywords, "_GLITTER"); RemoveKeyword(keywords, "_SNOWGLITTER"); RemoveKeyword(keywords, "_SPECULARFROMMETALLIC"); RemoveKeyword(keywords, "_USESPECULARWORKFLOW"); RemoveKeyword(keywords, "_BDRFLAMBERT"); RemoveKeyword(keywords, "_BDRF1"); RemoveKeyword(keywords, "_BDRF2"); RemoveKeyword(keywords, "_BDRF3"); keywords.Add(FeatureFromOutput(debugOutput).ToString()); if (useDebugTopo) { keywords.Add("_DEBUG_USE_TOPOLOGY"); } keywords.Add("_RENDERBAKE"); string shader = comp.Compile(keywords.ToArray(), "RenderBake_" + debugOutput.ToString()); Shader s = ShaderUtil.CreateShaderAsset(shader); Material renderMat = new Material(mat); renderMat.shader = s; renderMat.CopyPropertiesFromMaterial(mat); // because the constructor doesn't do it right in URP renderMat.enableInstancing = false; // for some reason instance drawing breaks in URP return(renderMat); }
public void WritePassHeader(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, int pass, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader) { }
public void WriteShaderHeader(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, bool blend) { sb.AppendLine(); sb.AppendLine(" CGINCLUDE"); if (!features.Contains <string>("_DEBUG_USE_TOPOLOGY") && (features.Contains <string>("_BDRF1") || features.Contains <string>("_BDRF2") || features.Contains <string>("_BDRF3"))) { if (features.Contains <string>("_BDRF1")) { sb.AppendLine(" #define UNITY_BRDF_PBS BRDF1_Unity_PBS"); } else if (features.Contains <string>("_BDRF2")) { sb.AppendLine(" #define UNITY_BRDF_PBS BRDF2_Unity_PBS"); } else if (features.Contains <string>("_BDRF3")) { sb.AppendLine(" #define UNITY_BRDF_PBS BRDF3_Unity_PBS"); } } sb.AppendLine(" ENDCG"); sb.AppendLine(); sb.AppendLine(" SubShader {"); sb.Append(" Tags{ \"RenderType\" = \"Opaque\" \"Queue\" = \"Geometry+100\" "); // on 2018+, this removes the multipass.. if (features.Contains("_MAX4TEXTURES")) { sb.Append("\"SplatCount\" = \"4\""); } else if (features.Contains("_MAX8TEXTURES")) { sb.Append("\"SplatCount\" = \"8\""); } else if (features.Contains("_MAX12TEXTURES")) { sb.Append("\"SplatCount\" = \"12\""); } else if (features.Contains("_MAX16TEXTURES")) { sb.Append("\"SplatCount\" = \"16\""); } else if (features.Contains("_MAX20TEXTURES")) { sb.Append("\"SplatCount\" = \"20\""); } else if (features.Contains("_MAX24TEXTURES")) { sb.Append("\"SplatCount\" = \"24\""); } else if (features.Contains("_MAX28TEXTURES")) { sb.Append("\"SplatCount\" = \"28\""); } else if (features.Contains("_MAX32TEXTURES")) { sb.Append("\"SplatCount\" = \"32\""); } sb.AppendLine("}"); sb.AppendLine(" Cull Back"); sb.AppendLine(" ZTest LEqual"); if (blend) { sb.AppendLine(" BLEND ONE ONE"); } #if UNITY_2018_3_OR_NEWER sb.AppendLine(" UsePass \"Hidden/Nature/Terrain/Utilities/PICKING\""); sb.AppendLine(" UsePass \"Hidden/Nature/Terrain/Utilities/SELECTION\""); #endif sb.AppendLine(" CGPROGRAM"); }
public void WriteSharedCode(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, int pass, bool blend) { sb.AppendLine(sharedInc.text); }
public void WritePassHeader(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, int pass, bool blend) { sb.AppendLine(" #pragma exclude_renderers d3d9"); sb.AppendLine(" #include \"UnityCG.cginc\""); sb.AppendLine(" #include \"AutoLight.cginc\""); sb.AppendLine(" #include \"Lighting.cginc\""); if (features.Contains <string>("_BDRFNOSPECMIN")) { sb.AppendLine(" #include \"Assets/MicroSplat/Core/Scripts/MicroSplatPBSLighting.cginc\""); } else { sb.AppendLine(" #include \"UnityPBSLighting.cginc\""); } sb.AppendLine(" #include \"UnityStandardBRDF.cginc\""); sb.AppendLine(); string pragma = ""; if (blend) { if (features.Contains("_MESHOVERLAYSPLATS")) { pragma = declareMeshBlend; } else { pragma = declareBlend; } } else if (!features.Contains <string>("_TESSDISTANCE")) { if (MicroSplatShaderGUI.MicroSplatCompiler.HasDebugFeature(features)) { pragma = declareTerrainDebug; if (features.Contains("_ALPHAHOLE") || features.Contains("_ALPHABELOWHEIGHT")) { // generate a shadow pass so we clip that too.. pragma += (" addshadow"); } } else { pragma = declareTerrain; } } else { pragma = declareTerrainTess; } if (!features.Contains("_DEBUG_USE_TOPOLOGY") && features.Contains("_BDRFLAMBERT")) { pragma = pragma.Replace("Standard", "Lambert"); } else if (features.Contains("_USESPECULARWORKFLOW")) { pragma = pragma.Replace("Standard", "StandardSpecular"); } sb.Append(pragma); if (!blend) { if (features.Contains <string>("_BDRF1") || features.Contains <string>("_BDRF2") || features.Contains <string>("_BDRF3")) { sb.Append(" exclude_path:deferred"); } } // allow for custom functions in lighting when this keyword is enabled if (!blend && features.Contains("_MSCUSTOMLIGHTING")) { sb.Replace("surf Standard", "customLightingSurf CustomLighting"); } // don't remove sb.AppendLine(); sb.AppendLine(); sb.AppendLine(); // for 2018.. #if UNITY_2018_3_OR_NEWER sb.AppendLine(" #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap forwardadd"); #endif sb.AppendLine(" #pragma target " + compiler.GetShaderModel(features)); // 2019.3 holes sb.AppendLine(" #pragma multi_compile_local __ _ALPHATEST_ON"); }
bool DoConvertGUI(MicroSplatTerrain t) { if (t.templateMaterial == null) { InitConvertConfigs(); using (new GUILayout.VerticalScope(GUI.skin.box)) { EditorGUILayout.LabelField("Select a Template:"); EditorGUILayout.BeginHorizontal(); for (int i = 0; i < convertConfigs.Count; ++i) { var c = convertConfigs [i]; if (DrawConvertButton(c, i == selectedConvertConfig)) { selectedConvertConfig = i; } } EditorGUILayout.EndHorizontal(); var selectedConfig = convertConfigs [selectedConvertConfig]; if (selectedConfig.missingModules.Count > 0) { EditorGUILayout.HelpBox("You are missing some MicroSplat modules needed by this template. The preset may still be used but some features will not be enabled. Missing modules are listed below:", MessageType.Warning); for (int i = 0; i < selectedConfig.missingModules.Count; ++i) { var m = selectedConfig.missingModules [i]; DrawMissingModule(m); } } EditorGUILayout.LabelField("Select any integrations you want to add:"); // integrations for (int i = 0; i < integrationConfigs.Count; ++i) { var ic = integrationConfigs [i]; if (!ic.assetInstalled) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(ic.name, GUILayout.Width(120)); EditorGUILayout.LabelField("Not Installed", GUILayout.Width(120)); if (GUILayout.Button("Link", GUILayout.Width(120))) { Application.OpenURL(ic.assetLink); } EditorGUILayout.EndHorizontal(); } else { EditorGUILayout.BeginHorizontal(); ic.include = EditorGUILayout.Toggle(ic.include, GUILayout.Width(20)); EditorGUILayout.LabelField(ic.name); EditorGUILayout.EndHorizontal(); if (ic.include && ic.missingModules.Count > 0) { using (new GUILayout.VerticalScope(GUI.skin.box)) { EditorGUILayout.HelpBox("Some MicroSplat modules requested by this module are not installed. Some or all features of the integration will not be active.", MessageType.Warning); for (int j = 0; j < ic.missingModules.Count; ++j) { var m = ic.missingModules [j]; DrawMissingModule(m); } } } } } if (GUILayout.Button("Convert to MicroSplat")) { // get all terrains in selection, not just this one, and treat as one giant terrain var objs = Selection.gameObjects; List <Terrain> terrains = new List <Terrain> (); for (int i = 0; i < objs.Length; ++i) { Terrain ter = objs [i].GetComponent <Terrain> (); if (ter != null) { terrains.Add(ter); } Terrain [] trs = objs [i].GetComponentsInChildren <Terrain> (); for (int x = 0; x < trs.Length; ++x) { if (!terrains.Contains(trs [x])) { terrains.Add(trs [x]); } } } Terrain terrain = t.GetComponent <Terrain> (); int texcount = 16; #if UNITY_2018_3_OR_NEWER texcount = terrain.terrainData.terrainLayers.Length; #else texcount = terrain.terrainData.splatPrototypes.Length; #endif List <string> keywords = new List <string> (selectedConfig.keywords); if (texcount <= 4) { keywords.Add("_MAX4TEXTURES"); } else if (texcount <= 8) { keywords.Add("_MAX8TEXTURES"); } else if (texcount <= 12) { keywords.Add("_MAX12TEXTURES"); } else if (texcount <= 20) { keywords.Add("_MAX20TEXTURES"); } else if (texcount <= 24) { keywords.Add("_MAX24TEXTURES"); } else if (texcount <= 28) { keywords.Add("_MAX28TEXTURES"); } else if (texcount > 28) { keywords.Add("_MAX32TEXTURES"); } for (int i = 0; i < integrationConfigs.Count; ++i) { var ic = integrationConfigs [i]; if (ic.include) { keywords.AddRange(ic.keywords); } } // setup this terrain t.templateMaterial = MicroSplatShaderGUI.NewShaderAndMaterial(terrain, keywords.ToArray()); var config = TextureArrayConfigEditor.CreateConfig(terrain); t.templateMaterial.SetTexture("_Diffuse", config.diffuseArray); t.templateMaterial.SetTexture("_NormalSAO", config.normalSAOArray); t.propData = MicroSplatShaderGUI.FindOrCreatePropTex(t.templateMaterial); #if UNITY_2018_3_OR_NEWER if (terrain.terrainData.terrainLayers.Length > 0) { var uvScale = terrain.terrainData.terrainLayers[0].tileSize; var uvOffset = terrain.terrainData.terrainLayers[0].tileOffset; uvScale = MicroSplatRuntimeUtil.UnityUVScaleToUVScale(uvScale, terrain); uvOffset.x = uvScale.x / terrain.terrainData.size.x * 0.5f * uvOffset.x; uvOffset.y = uvScale.y / terrain.terrainData.size.x * 0.5f * uvOffset.y; Vector4 scaleOffset = new Vector4(uvScale.x, uvScale.y, uvOffset.x, uvOffset.y); t.templateMaterial.SetVector("_UVScale", scaleOffset); } #else if (terrain.terrainData.splatPrototypes.Length > 0) { var uvScale = terrain.terrainData.splatPrototypes [0].tileSize; var uvOffset = terrain.terrainData.splatPrototypes [0].tileOffset; uvScale = MicroSplatRuntimeUtil.UnityUVScaleToUVScale(uvScale, terrain); uvOffset.x = uvScale.x / terrain.terrainData.size.x * 0.5f * uvOffset.x; uvOffset.y = uvScale.y / terrain.terrainData.size.x * 0.5f * uvOffset.y; Vector4 scaleOffset = new Vector4(uvScale.x, uvScale.y, uvOffset.x, uvOffset.y); t.templateMaterial.SetVector("_UVScale", scaleOffset); } #endif // we need to set a few things on the material if certain features are enabled. // Test for property existence as module might not be installed and feature was culled. if (System.Array.Exists(selectedConfig.keywords, x => x == "_TRIPLANAR")) { if (t.templateMaterial.HasProperty("_TriplanarUVScale")) { t.templateMaterial.SetVector("_TriplanarUVScale", new Vector4(0.25f, 0.25f, 0, 0)); } } if (System.Array.Exists(selectedConfig.keywords, x => x == "_NORMALNOISE")) { if (t.templateMaterial.HasProperty("_NormalNoise")) { t.templateMaterial.SetTexture("_NormalNoise", MicroSplatUtilities.GetAutoTexture("microsplat_def_detail_normal_01")); } } // now make sure others all have the same settings as well. for (int i = 0; i < terrains.Count; ++i) { var nt = terrains [i]; var mgr = nt.GetComponent <MicroSplatTerrain> (); if (mgr == null) { mgr = nt.gameObject.AddComponent <MicroSplatTerrain> (); } mgr.templateMaterial = t.templateMaterial; if (mgr.propData == null) { mgr.propData = MicroSplatShaderGUI.FindOrCreatePropTex(mgr.templateMaterial); } } Selection.SetActiveObjectWithContext(config, config); t.keywordSO = MicroSplatUtilities.FindOrCreateKeywords(t.templateMaterial); t.keywordSO.keywords.Clear(); t.keywordSO.keywords = new List <string> (keywords); // force recompile, so that basemap shader name gets reset correctly.. MicroSplatShaderGUI.MicroSplatCompiler comp = new MicroSplatShaderGUI.MicroSplatCompiler(); comp.Compile(t.templateMaterial); MicroSplatTerrain.SyncAll(); // trun on draw instanced if enabled and tessellation is disabled, unless render loop is LWRP/URP in which case it does work.. #if UNITY_2018_3_OR_NEWER if (t.keywordSO != null && (!t.keywordSO.IsKeywordEnabled("_TESSDISTANCE") || t.keywordSO.IsKeywordEnabled("_MSRENDERLOOP_UNITYLD"))) { for (int i = 0; i < terrains.Count; ++i) { var nt = terrains [i]; var mgr = nt.GetComponent <MicroSplatTerrain> (); if (mgr != null && mgr.keywordSO != null && !mgr.keywordSO.IsKeywordEnabled("_MSRENDERLOOP_UNITYLD")) { nt.drawInstanced = true; } } } #endif return(true); } } } return(false); }
/// <summary> /// Attempt to recompile MicroSplat shader, ensuring the name matches the landscape name /// USAGE: /// bool isSuccessful = MicroSplatCompileShader(landscape, customTerrainMaterial, true); /// </summary> /// <param name="landscape"></param> /// <param name="terrainMat"></param> /// <param name="showErrors"></param> /// <returns></returns> public static bool MicroSplatCompileShader(LBLandscape landscape, Material terrainMat, bool showErrors) { bool isSuccessful = false; string methodName = "LBEditorIntegration.MicroSplatCompileShader"; //System.Type MicroSplatShaderGUIType = null; try { if (landscape == null) { if (showErrors) { Debug.LogWarning("ERROR: " + methodName + " landscape is null. Please Report"); } } else if (terrainMat == null) { if (showErrors) { Debug.LogWarning("ERROR: " + methodName + " terrainMat is null. Please Report"); } } else { Shader shader = terrainMat.shader; if (shader == null) { if (showErrors) { Debug.LogWarning(methodName + " - could not find MicroSplat shader. Please Report."); } } else if (!shader.name.Contains("MicroSplat")) { if (showErrors) { Debug.LogWarning(methodName + " - terrain material is not using a MicroSplat shader. [" + shader.name + "]. Please Report"); } } else { // Create a new instance of the compiler class MicroSplatShaderGUI.MicroSplatCompiler microSplatCompiler = new MicroSplatShaderGUI.MicroSplatCompiler(); string shaderPath = AssetDatabase.GetAssetPath(shader); string shaderBasePath = shaderPath.Replace(".shader", "_Base.shader"); if (microSplatCompiler == null) { if (showErrors) { Debug.LogWarning(methodName + " - could not create MicroSplatCompiler instance. Please Report."); } } else { microSplatCompiler.Init(); string[] shaderFeatures = terrainMat.shaderKeywords; // Ensure shader names match the landscape name string baseName = "Hidden/MicroSplat/" + landscape.name + "_Base"; string baseShaderOutput = microSplatCompiler.Compile(shaderFeatures, baseName); string regularShaderOutput = microSplatCompiler.Compile(shaderFeatures, "MicroSplat/" + landscape.name, baseName); //Debug.Log("[DEBUG] regularShaderOutput: " + regularShaderOutput); // Copy the output back to the shader files in the project folder. System.IO.File.WriteAllText(shaderPath, regularShaderOutput); System.IO.File.WriteAllText(shaderBasePath, baseShaderOutput); // Currently we don't use this but we "might" in the future if (shaderFeatures.Contains("_MESHOVERLAYSPLATS")) { string meshOverlayShader = microSplatCompiler.Compile(shaderFeatures, "MicroSplat/" + landscape.name, null, true); System.IO.File.WriteAllText(shaderPath.Replace(".shader", "_MeshOverlay.shader"), meshOverlayShader); } AssetDatabase.Refresh(); isSuccessful = !string.IsNullOrEmpty(baseShaderOutput) && !string.IsNullOrEmpty(regularShaderOutput); } } } } catch (System.Exception ex) { if (showErrors) { Debug.LogWarning("LBIntegration.MegaSplatCompileShader something has gone wrong. Please report. " + ex.Message); } } return(isSuccessful); }
void WriteOptions(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader, string baseName) { if (features.Contains("_TESSDISTANCE")) { sb.AppendLine("Tessellation \"Distance\""); } sb.Append(" Tags {\"RenderType\" = \"Opaque\" \"Queue\" = \"Geometry+100\" \"IgnoreProjector\" = \"False\" "); if (features.Contains("_MAX4TEXTURES")) { sb.Append("\"SplatCount\" = \"4\""); } else if (features.Contains("_MAX8TEXTURES")) { sb.Append("\"SplatCount\" = \"8\""); } else if (features.Contains("_MAX12TEXTURES")) { sb.Append("\"SplatCount\" = \"12\""); } else if (features.Contains("_MAX20TEXTURES")) { sb.Append("\"SplatCount\" = \"20\""); } else if (features.Contains("_MAX24TEXTURES")) { sb.Append("\"SplatCount\" = \"24\""); } else if (features.Contains("_MAX28TEXTURES")) { sb.Append("\"SplatCount\" = \"28\""); } else if (features.Contains("_MAX32TEXTURES")) { sb.Append("\"SplatCount\" = \"32\""); } else { sb.Append("\"SplatCount\" = \"16\""); } sb.AppendLine("}"); if (features.Contains("_MESHOVERLAYSPLATS")) { sb.AppendLine(" Alpha \"Blend\""); } if (auxShader != null && !string.IsNullOrEmpty(auxShader.customEditor)) { sb.AppendLine(" CustomEditor \"" + auxShader.customEditor + "\""); } if (auxShader != null && !string.IsNullOrEmpty(auxShader.options)) { sb.AppendLine(auxShader.options); } else if (auxShader != null) { sb.AppendLine(" CustomEditor \"MicroSplatShaderGUI\""); } else if (baseName == null) { sb.AppendLine(" CustomEditor \"MicroSplatShaderGUI\""); } else if (baseName != null) { if (features.Contains("_MICROTERRAIN") && !features.Contains("_TERRAINBLENDABLESHADER")) { sb.AppendLine(" Dependency {\"BaseMapShader\" = \"" + baseName + "\"}"); } sb.AppendLine(" CustomEditor \"MicroSplatShaderGUI\""); } sb.AppendLine(" Fallback \"Nature/Terrain/Diffuse\""); }
public Blocks GetShaderBlocks(string[] features, MicroSplatShaderGUI.MicroSplatCompiler compiler, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader) { StringBuilder defines = new StringBuilder(); compiler.WriteDefines(features, defines); if (auxShader != null && auxShader.trigger == "_TERRAINBLENDING") { defines.AppendLine(" #define _SRPTERRAINBLEND 1"); } if (features.Contains("_USESPECULARWORKFLOW")) { defines.AppendLine(" #define _SPECULAR_SETUP"); } if (features.Contains("_MICROTERRAIN") && !features.Contains("_TERRAINBLENDABLESHADER")) // digger? mesh terrain? { defines.AppendLine("#pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap forwardadd"); } StringBuilder cbuffer = new StringBuilder(); compiler.WritePerMaterialCBuffer(features, cbuffer); if (auxShader != null && auxShader.trigger == "_TERRAINBLENDING") { cbuffer.AppendLine(terrainBlendCBuffer.text); } StringBuilder options = new StringBuilder(); WriteOptions(features, options, compiler, auxShader, null); StringBuilder properties = new StringBuilder(); compiler.WriteProperties(features, properties, auxShader); StringBuilder ext = new StringBuilder(); compiler.WriteExtensions(features, ext); StringBuilder afterVertex = new StringBuilder(); foreach (var e in compiler.extensions) { e.WriteAfterVetrexFunctions(afterVertex); } StringBuilder code = new StringBuilder(100000); code.AppendLine(adapter.text); code.AppendLine(sharedInc.text); code.AppendLine(StripVertexWorkflow(features)); code.AppendLine((StripMegaSplat(features))); if (features.Contains("_PLANETVECTORS") && planetData != null) { code.AppendLine(planetData.text); } code.AppendLine(sharedHD.text); code.AppendLine(ext.ToString()); code.AppendLine(terrainBody.text); code.AppendLine(vertex.text); if (auxShader != null && auxShader.trigger == "_TERRAINBLENDING") { code.AppendLine(terrainBlendBody.text); } code.AppendLine(mainFunc.text); code.AppendLine(afterVertex.ToString()); Blocks b = new Blocks(); b.code = code.ToString(); b.cbuffer = cbuffer.ToString(); b.properties = properties.ToString(); b.defines = defines.ToString(); b.options = options.ToString(); return(b); }
public void PostProcessShader(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader) { }
public void WriteVertexFunction(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, int pass, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader) { }
bool DoConvertGUI(MicroSplatTerrain t) { if (t.templateMaterial == null) { InitConvertConfigs(); using (new GUILayout.VerticalScope(GUI.skin.box)) { EditorGUILayout.LabelField("Select any integrations you want to add:"); // integrations for (int i = 0; i < integrationConfigs.Count; ++i) { var ic = integrationConfigs [i]; if (!ic.assetInstalled) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(ic.name, GUILayout.Width(120)); EditorGUILayout.LabelField("Not Installed", GUILayout.Width(120)); if (GUILayout.Button("Link", GUILayout.Width(120))) { Application.OpenURL(ic.assetLink); } EditorGUILayout.EndHorizontal(); } else { EditorGUILayout.BeginHorizontal(); ic.include = EditorGUILayout.Toggle(ic.include, GUILayout.Width(20)); EditorGUILayout.LabelField(ic.name); EditorGUILayout.EndHorizontal(); if (ic.include && ic.missingModules.Count > 0) { using (new GUILayout.VerticalScope(GUI.skin.box)) { EditorGUILayout.HelpBox("Some MicroSplat modules requested by this module are not installed. Some or all features of the integration will not be active.", MessageType.Warning); for (int j = 0; j < ic.missingModules.Count; ++j) { var m = ic.missingModules [j]; DrawMissingModule(m); } } } } } if (GUILayout.Button("Convert to MicroSplat")) { // get all terrains in selection, not just this one, and treat as one giant terrain var objs = Selection.gameObjects; List <Terrain> terrains = new List <Terrain> (); for (int i = 0; i < objs.Length; ++i) { Terrain ter = objs [i].GetComponent <Terrain> (); if (ter != null) { terrains.Add(ter); } Terrain [] trs = objs [i].GetComponentsInChildren <Terrain> (); for (int x = 0; x < trs.Length; ++x) { if (!terrains.Contains(trs [x])) { terrains.Add(trs [x]); } } } Terrain terrain = t.GetComponent <Terrain> (); int texcount = terrain.terrainData.terrainLayers.Length; List <string> keywords = new List <string> (defaultKeywords); // set initial render pipleine var pipeline = MicroSplatUtilities.DetectPipeline(); if (pipeline == MicroSplatUtilities.PipelineType.HDPipeline) { keywords.Add("_MSRENDERLOOP_UNITYHD"); } else if (pipeline == MicroSplatUtilities.PipelineType.UniversalPipeline) { keywords.Add("_MSRENDERLOOP_UNITYLD"); } // Because new users won't read the manual or read settings before they act, we don't clamp the texture count // down for maximum performance. Way to many support requests complaining of black terrain after adding textures because // they didn't realize they needed to up the max texture count. So now, 16 minimum. This is why we can't have nice things. /* * if (texcount <= 4) * { * keywords.Add ("_MAX4TEXTURES"); * } * else if (texcount <= 8) * { * keywords.Add ("_MAX8TEXTURES"); * } * else if (texcount <= 12) * { * keywords.Add ("_MAX12TEXTURES"); * } */ if (texcount > 16 && texcount <= 20) { keywords.Add("_MAX20TEXTURES"); } else if (texcount <= 24) { keywords.Add("_MAX24TEXTURES"); } else if (texcount <= 28) { keywords.Add("_MAX28TEXTURES"); } else if (texcount > 28) { keywords.Add("_MAX32TEXTURES"); } for (int i = 0; i < integrationConfigs.Count; ++i) { var ic = integrationConfigs [i]; if (ic.include) { keywords.AddRange(ic.keywords); } } // setup this terrain t.templateMaterial = MicroSplatShaderGUI.NewShaderAndMaterial(terrain, keywords.ToArray()); var config = TextureArrayConfigEditor.CreateConfig(terrain); t.templateMaterial.SetTexture("_Diffuse", config.diffuseArray); t.templateMaterial.SetTexture("_NormalSAO", config.normalSAOArray); t.propData = MicroSplatShaderGUI.FindOrCreatePropTex(t.templateMaterial); EditorUtility.SetDirty(t); if (terrain.terrainData.terrainLayers != null) { if (terrain.terrainData.terrainLayers.Length > 0) { Vector2 min = new Vector2(99999, 99999); Vector2 max = Vector2.zero; for (int x = 0; x < terrain.terrainData.terrainLayers.Length; ++x) { var uv = terrain.terrainData.terrainLayers [x].tileSize; if (min.x > uv.x) { min.x = uv.x; } if (min.y > uv.y) { min.y = uv.y; } if (max.x < uv.x) { max.x = uv.x; } if (max.y < uv.y) { max.y = uv.y; } } Vector2 average = Vector2.Lerp(min, max, 0.5f); // use per texture UVs instead.. float diff = Vector2.Distance(min, max); if (diff > 0.1) { keywords.Add("_PERTEXUVSCALEOFFSET"); // if the user has widely different UVs, use the LOD sampler. This is because the gradient mode blends between mip levels, // which looks bad with hugely different UVs. I still don't understand why people do this kind of crap though, ideally // your UVs should not differ per texture, and if so, not by much.. if (diff > 10) { Debug.LogWarning("Terrain has wildly varing UV scales, it's best to keep consistent texture resolution. "); } if (!keywords.Contains("_USEGRADMIP")) { keywords.Add("_USEGRADMIP"); } Vector4 scaleOffset = new Vector4(1, 1, 0, 0); t.templateMaterial.SetVector("_UVScale", scaleOffset); var propData = MicroSplatShaderGUI.FindOrCreatePropTex(t.templateMaterial); for (int x = 0; x < terrain.terrainData.terrainLayers.Length; ++x) { var uvScale = terrain.terrainData.terrainLayers [x].tileSize; var uvOffset = terrain.terrainData.terrainLayers [x].tileOffset; uvScale = MicroSplatRuntimeUtil.UnityUVScaleToUVScale(uvScale, terrain); uvScale.x = Mathf.RoundToInt(uvScale.x); uvScale.y = Mathf.RoundToInt(uvScale.y); propData.SetValue(x, MicroSplatPropData.PerTexVector2.SplatUVScale, uvScale); propData.SetValue(x, MicroSplatPropData.PerTexVector2.SplatUVOffset, Vector2.zero); } for (int x = terrain.terrainData.terrainLayers.Length; x < 32; ++x) { propData.SetValue(x, MicroSplatPropData.PerTexVector2.SplatUVScale, average); propData.SetValue(x, MicroSplatPropData.PerTexVector2.SplatUVOffset, Vector2.zero); } // must init the data, or the editor will write over it. propData.SetValue(0, 15, Color.white); EditorUtility.SetDirty(propData); t.templateMaterial.SetVector("_TriplanarUVScale", new Vector4( 10.0f / t.terrain.terrainData.size.x, 10.0f / t.terrain.terrainData.size.x, 0, 0)); } else { var uvScale = terrain.terrainData.terrainLayers [0].tileSize; var uvOffset = terrain.terrainData.terrainLayers [0].tileOffset; uvScale = MicroSplatRuntimeUtil.UnityUVScaleToUVScale(uvScale, terrain); uvOffset.x = uvScale.x / terrain.terrainData.size.x * 0.5f * uvOffset.x; uvOffset.y = uvScale.y / terrain.terrainData.size.x * 0.5f * uvOffset.y; Vector4 scaleOffset = new Vector4(uvScale.x, uvScale.y, uvOffset.x, uvOffset.y); t.templateMaterial.SetVector("_UVScale", scaleOffset); t.templateMaterial.SetVector("_TriplanarUVScale", new Vector4( 10.0f / t.terrain.terrainData.size.x, 10.0f / t.terrain.terrainData.size.x, 0, 0)); } } } // now make sure others all have the same settings as well. for (int i = 0; i < terrains.Count; ++i) { var nt = terrains [i]; var mgr = nt.GetComponent <MicroSplatTerrain> (); if (mgr == null) { mgr = nt.gameObject.AddComponent <MicroSplatTerrain> (); } mgr.templateMaterial = t.templateMaterial; if (mgr.propData == null) { mgr.propData = MicroSplatShaderGUI.FindOrCreatePropTex(mgr.templateMaterial); } } Selection.SetActiveObjectWithContext(config, config); t.keywordSO = MicroSplatUtilities.FindOrCreateKeywords(t.templateMaterial); t.keywordSO.keywords.Clear(); t.keywordSO.keywords = new List <string> (keywords); // force recompile, so that basemap shader name gets reset correctly.. MicroSplatShaderGUI.MicroSplatCompiler comp = new MicroSplatShaderGUI.MicroSplatCompiler(); comp.Compile(t.templateMaterial); // for some reason, often when people create terrains with Gaia but this is unconfirmed, // if instancing is set, the terrain will not draw until a shader feature is toggled. // So for now, turn off instancing when doing conversion. for (int i = 0; i < terrains.Count; ++i) { var nt = terrains [i]; nt.drawInstanced = false; } MicroSplatTerrain.SyncAll(); /* * // turn on draw instanced if enabled and tessellation is disabled, unless render loop is LWRP/URP in which case it does work.. * if (t.keywordSO != null && (!t.keywordSO.IsKeywordEnabled("_TESSDISTANCE") || t.keywordSO.IsKeywordEnabled("_MSRENDERLOOP_UNITYLD"))) * { * for (int i = 0; i < terrains.Count; ++i) * { * var nt = terrains [i]; * var mgr = nt.GetComponent<MicroSplatTerrain> (); * if (mgr != null && mgr.keywordSO != null && !mgr.keywordSO.IsKeywordEnabled("_MSRENDERLOOP_UNITYLD")) * { * nt.drawInstanced = true; * } * } * } */ return(true); } } } return(false); }
public StringBuilder WriteShader(string[] features, MicroSplatShaderGUI.MicroSplatCompiler compiler, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader, string name, string baseName) { StringBuilder defines = new StringBuilder(); var blocks = gen.GetShaderBlocks(features, compiler, auxShader); var shader = BuildTemplate(blocks, baseName); defines.AppendLine(blocks.defines); defines.AppendLine("\n #define _STANDARD 1"); string shaderTarget = "3.0"; if (features.Contains("_TESSDISTANCE") || features.Contains("_FORCEMODEL46")) { shaderTarget = "4.6"; } else if (features.Contains("_FORCEMODEL50")) { shaderTarget = "5.0"; } if (features.Contains("_TESSDISTANCE")) { defines.AppendLine("\n #define _TESSELLATION_ON 1"); shader = shader.Replace("%TESSELLATION%", templateTess.text); shader = shader.Replace("%PRAGMAS%", " #pragma hull Hull\n #pragma domain Domain\n #pragma vertex TessVert\n #pragma fragment Frag\n #pragma require tesshw\n"); } else { shader = shader.Replace("%PRAGMAS%", " #pragma vertex Vert\n #pragma fragment Frag"); shader = shader.Replace("%TESSELLATION%", ""); } shader = shader.Replace("%SHADERTARGET%", shaderTarget); if (features.Contains("_USESPECULARWORKFLOW")) { defines.AppendLine("\n#define _USESPECULAR 1"); defines.AppendLine("#define _MATERIAL_FEATURE_SPECULAR_COLOR 1"); } defines.AppendLine(); defines.AppendLine(templateCommonHLSL.text); string shaderDesk = templateShaderDesc.text; shaderDesk += templateChain.text; shader = shader.Replace("%SHADERDESC%", shaderDesk); shader = shader.Replace("%SHADERNAME%", name); shader = shader.Replace("%PROPERTIES%", blocks.properties); shader = shader.Replace("%CODE%", blocks.code); shader = shader.Replace("%DEFINES%", defines.ToString()); shader = shader.Replace("%CBUFFER%", blocks.cbuffer); string codeNoComments = blocks.code.StripComments(); shader = Strip(codeNoComments, shader); return(shader); }
public void WriteVertexFunction(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, int pass, bool blend) { sb.AppendLine(vertexFunc.text); }
void CompressTerrainSplats(MicroSplatTerrain t) { int splatCount = t.terrain.terrainData.alphamapTextureCount; // write out for (int i = 0; i < splatCount; ++i) { var tex = t.terrain.terrainData.GetAlphamapTexture(i); var path = MicroSplatUtilities.RelativePathFromAsset(t); path += "/" + t.name + "_splat" + i + ".tga"; System.IO.File.WriteAllBytes(path, tex.EncodeToTGA()); } AssetDatabase.Refresh(); // load and adjust importer for (int i = 0; i < splatCount; ++i) { var path = MicroSplatUtilities.RelativePathFromAsset(t); path += "/" + t.name + "_splat" + i + ".tga"; var tex = CompressTexture(path, false); if (i == 0) { t.customControl0 = tex; } else if (i == 1) { t.customControl1 = tex; } else if (i == 2) { t.customControl2 = tex; } else if (i == 3) { t.customControl3 = tex; } else if (i == 4) { t.customControl4 = tex; } else if (i == 5) { t.customControl5 = tex; } else if (i == 6) { t.customControl6 = tex; } else if (i == 7) { t.customControl7 = tex; } } EditorUtility.SetDirty(t); MicroSplatKeywords keywords = MicroSplatUtilities.FindOrCreateKeywords(t.templateMaterial); if (!keywords.IsKeywordEnabled("_CUSTOMSPLATTEXTURES")) { keywords.EnableKeyword("_CUSTOMSPLATTEXTURES"); MicroSplatShaderGUI.MicroSplatCompiler compiler = new MicroSplatShaderGUI.MicroSplatCompiler(); compiler.Compile(t.templateMaterial); MicroSplatTerrain.SyncAll(); } // destructive operation t.terrain.terrainData.alphamapResolution = 16; }
public void PostProcessShader(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, bool blend) { }
public void WritePassHeader(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, int pass, bool blend) { sb.AppendLine(" #pragma exclude_renderers d3d9"); sb.AppendLine(" #include \"UnityCG.cginc\""); sb.AppendLine(" #include \"AutoLight.cginc\""); sb.AppendLine(" #include \"Lighting.cginc\""); sb.AppendLine(" #include \"UnityPBSLighting.cginc\""); sb.AppendLine(" #include \"UnityStandardBRDF.cginc\""); string pragma = ""; if (blend) { if (features.Contains("_MESHOVERLAYSPLATS")) { pragma = declareMeshBlend; } else { pragma = declareBlend; } } else if (!features.Contains <string>("_TESSDISTANCE")) { if (MicroSplatShaderGUI.MicroSplatCompiler.HasDebugFeature(features)) { pragma = declareTerrainDebug; if (features.Contains("_ALPHAHOLE") || features.Contains("_ALPHABELOWHEIGHT")) { // generate a shadow pass so we clip that too.. pragma += (" addshadow"); } } else { pragma = declareTerrain; } } else { pragma = declareTerrainTess; } if (features.Contains("_BDRFLAMBERT")) { pragma = pragma.Replace("Standard", "Lambert"); } sb.Append(pragma); if (!blend) { if (features.Contains <string>("_BDRF1") || features.Contains <string>("_BDRF2") || features.Contains <string>("_BDRF3")) { sb.Append(" exclude_path:deferred"); } } // don't remove sb.AppendLine(); sb.AppendLine(); sb.AppendLine(" #pragma target " + compiler.GetShaderModel(features)); }
public void WriteTerrainBody(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, int pass, bool blend) { sb.AppendLine(terrainBody.text); }
public void PostProcessShader(string[] features, StringBuilder sb, MicroSplatShaderGUI.MicroSplatCompiler compiler, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader) { StringBuilder temp = new StringBuilder(); compiler.WriteFeatures(features, temp); if (auxShader != null && auxShader.trigger == "_TERRAINBLENDING") { temp.AppendLine(" #define _SRPTERRAINBLEND 1"); } StringBuilder cbuffer = new StringBuilder(); compiler.WritePerMaterialCBuffer(features, cbuffer); if (auxShader != null && auxShader.trigger == "_TERRAINBLENDING") { cbuffer.AppendLine(terrainBlendCBuffer.text); } sb = sb.Replace("//MS_DEFINES", temp.ToString()); sb = sb.Replace("//MS_ADAPTER", adapter.ToString()); sb = sb.Replace("//MS_SHARED_INC", sharedInc.text); sb = sb.Replace("//MS_SHARED_HD", sharedHD.text); sb = sb.Replace("//MS_TERRAIN_BODY", terrainBody.text); sb = sb.Replace("//MS_VERTEXMOD", vertex.text); sb = sb.Replace("//MS_MAINFUNC", mainFunc.text); sb = sb.Replace("//MS_CBUFFER", cbuffer.ToString()); sb = sb.Replace("//MS_PASS_DEPTHONLY", vertMesh.text + "\n" + pass_depthonly.text); sb = sb.Replace("//MS_PASS_GBUFFER", vertMesh.text + "\n" + pass_gbuffer.text); sb = sb.Replace("//MS_PASS_FORWARD", vertMesh.text + "\n" + pass_forward.text); sb = sb.Replace("//MS_PASS_LIGHTTRANSPORT", vertMesh.text + "\n" + pass_lighttransport.text); sb = sb.Replace("//MS_PASS_DECAL", vertMesh.text + "\n" + pass_decal.text); if (auxShader != null && auxShader.trigger == "_TERRAINBLENDING") { sb = sb.Replace("//MS_BLENDABLE", terrainBlendBody.text); sb = sb.Replace("Blend [_SrcBlend] [_DstBlend], [_AlphaSrcBlend] [_AlphaDstBlend]", "Blend SrcAlpha OneMinusSrcAlpha"); } // extentions StringBuilder ext = new StringBuilder(); compiler.WriteExtensions(features, ext); sb = sb.Replace("//MS_EXTENSIONS", ext.ToString()); ext = new StringBuilder(); foreach (var e in compiler.extensions) { e.WriteAfterVetrexFunctions(ext); } sb = sb.Replace("//MS_AFTERVERTEX", ext.ToString()); // HD fixup sb = sb.Replace("fixed", "half"); sb = sb.Replace("unity_ObjectToWorld", "GetObjectToWorldMatrix()"); sb = sb.Replace("unity_WorldToObject", "GetWorldToObjectMatrix()"); sb = sb.Replace("_ObjectToWorld", "GetObjectToWorldMatrix()"); sb = sb.Replace("_WorldToObject", "GetWorldToObjectMatrix()"); sb = sb.Replace("UNITY_MATRIX_M", "GetObjectToWorldMatrix()"); sb = sb.Replace("UNITY_MATRIX_I_M", "GetWorldToObjectMatrix()"); sb = sb.Replace("UNITY_MATRIX_VP", "GetWorldToHClipMatrix()"); sb = sb.Replace("UNITY_MATRIX_V", "GetWorldToViewMatrix()"); sb = sb.Replace("UNITY_MATRIX_P", "GetViewToHClipMatrix()"); if (features.Contains("_USESPECULARWORKFLOW")) { sb = sb.Replace("// #define _MATERIAL_FEATURE_SPECULAR_COLOR 1", "#define _MATERIAL_FEATURE_SPECULAR_COLOR 1"); } if (features.Contains("_TESSDISTANCE")) { sb = sb.Replace("#pragma vertex Vert", "#pragma hull hull\n#pragma domain domain\n#pragma vertex tessvert\n#pragma require tessellation tessHW\n"); } }
public StringBuilder WriteShader(string[] features, MicroSplatShaderGUI.MicroSplatCompiler compiler, MicroSplatShaderGUI.MicroSplatCompiler.AuxShader auxShader, string name, string baseName) { StringBuilder defines = new StringBuilder(); var blocks = gen.GetShaderBlocks(features, compiler, auxShader); var shader = BuildTemplate(blocks, baseName); defines.AppendLine(blocks.defines); defines.AppendLine("\n #define _HDRP 1"); string shaderTarget = "4.6"; if (features.Contains("_FORCEMODEL50")) { shaderTarget = "5.0"; } if (features.Contains("_TESSDISTANCE")) { defines.AppendLine("\n #define _TESSELLATION_ON 1"); shader = shader.Replace("%TESSELLATION%", templateTess.text); shader = shader.Replace("%PRAGMAS%", " #pragma hull Hull\n #pragma domain Domain\n #pragma vertex TessVert\n #pragma fragment Frag\n #pragma require tesshw\n"); } else { shader = shader.Replace("%PRAGMAS%", " #pragma vertex Vert\n #pragma fragment Frag"); shader = shader.Replace("%TESSELLATION%", ""); } shader = shader.Replace("%SHADERTARGET%", shaderTarget); if (features.Contains("_USESPECULARWORKFLOW")) { defines.AppendLine("\n#define _USESPECULAR 1"); defines.AppendLine("#define _MATERIAL_FEATURE_SPECULAR_COLOR 1"); } defines.AppendLine(); shader = shader.Replace("%SHADERNAME%", name); shader = shader.Replace("%PROPERTIES%", blocks.properties); shader = shader.Replace("%CODE%", blocks.code); shader = shader.Replace("%DEFINES%", defines.ToString()); shader = shader.Replace("%CBUFFER%", blocks.cbuffer); string codeNoComments = blocks.code.StripComments(); shader = SurfaceShaderRenderLoopAdapter.Strip(codeNoComments, shader); // standard pipeline stuff shader = shader.Replace("fixed", "half"); shader = shader.Replace("unity_ObjectToWorld", "GetObjectToWorldMatrix()"); shader = shader.Replace("unity_WorldToObject", "GetWorldToObjectMatrix()"); //shader = shader.Replace("UNITY_MATRIX_M", "GetObjectToWorldMatrix()"); //shader = shader.Replace("UNITY_MATRIX_I_M", "GetWorldToObjectMatrix()"); //shader = shader.Replace("UNITY_MATRIX_VP", "GetWorldToHClipMatrix()"); //shader = shader.Replace("UNITY_MATRIX_V", "GetWorldToViewMatrix()"); //shader = shader.Replace("UNITY_MATRIX_P", "GetViewToHClipMatrix()"); return(shader); }
void DrawScatterGUI() { if (MicroSplatUtilities.DrawRollup("Brush Settings")) { brushSize = EditorGUILayout.Slider("Brush Size", brushSize, 0.01f, 30.0f); brushFlow = EditorGUILayout.Slider("Brush Flow", brushFlow, 0.1f, 128.0f); brushFalloff = EditorGUILayout.Slider("Brush Falloff", brushFalloff, 0.1f, 3.5f); Material tempMat = null; for (int i = 0; i < rawTerrains.Count; ++i) { Terrain t = rawTerrains [i]; MicroSplatTerrain mst = t.GetComponent <MicroSplatTerrain> (); if (mst != null) { if (mst.templateMaterial != null && mst.templateMaterial.HasProperty("_ScatterDiffuse")) { Texture2DArray diff = mst.templateMaterial.GetTexture("_ScatterDiffuse") as Texture2DArray; scatterIndex = MicroSplatUtilities.DrawTextureSelector(scatterIndex, diff, false); tempMat = mst.templateMaterial; } else { scatterIndex = EditorGUILayout.IntField("Scatter Index", scatterIndex); } } else { scatterIndex = EditorGUILayout.IntField("Scatter Index", scatterIndex); } } //EditorGUILayout.MinMaxSlider (CSlopeRange, ref slopeRange.x, ref slopeRange.y, 0.0f, 1.0f); paintValue = EditorGUILayout.Slider("Target Opacity", paintValue, 0.0f, 1.0f); #if __MICROSPLAT_SCATTER__ if (tempMat != null) { scatterLayer = (ScatterLayer)EditorGUILayout.EnumPopup(CScatterLayer, scatterLayer); EditorGUILayout.Separator(); using (new GUILayout.VerticalScope(GUI.skin.box)) { EditorGUI.BeginChangeCheck(); EditorGUILayout.LabelField("Per Texture Properties"); bool changed = MicroSplatScatter.DrawPerTexExternal(tempMat, scatterIndex); EditorGUILayout.Separator(); // sync compile changes if (changed) { MicroSplatShaderGUI.MicroSplatCompiler comp = new MicroSplatShaderGUI.MicroSplatCompiler(); comp.Init(); comp.Compile(tempMat); } // sync property changes if (EditorGUI.EndChangeCheck()) { MicroSplatObject.SyncAll(); } } } #endif GUILayout.Box("", new GUILayoutOption [] { GUILayout.ExpandWidth(true), GUILayout.Height(1) }); EditorGUILayout.Separator(); } DrawFillGUI(); }