新插件

This commit is contained in:
2025-06-04 09:09:39 +08:00
parent 83ced83b6b
commit d76b763fbf
1718 changed files with 1234489 additions and 1 deletions

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 258ca8cecfea442508f76db4b209cdb0
folderAsset: yes
timeCreated: 1573424538
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
{
"reference": "GUID:90ab0119788ed4ec6b8fe54dd44f01fa"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: cbe95de0d6ec2415ba85420f90c9668d
AssemblyDefinitionReferenceImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,214 @@
//////////////////////////////////////////////////////
// MicroSplat
// Copyright (c) Jason Booth
//////////////////////////////////////////////////////
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using JBooth.MicroSplat;
[CustomEditor(typeof(MicroSplatMeshTerrain))]
[CanEditMultipleObjects]
public partial class MicroSplatMeshTerrainEditor : Editor
{
#if __MICROSPLAT__
#if __MICROSPLAT_ALPHAHOLE__
static GUIContent clipMapOverride = new GUIContent("Clip Map Override", "Provide a unique clip map for each terrain");
#endif
static GUIContent CTemplateMaterial = new GUIContent("Template Material", "Material to use for this terrain");
static GUIContent CPerPixelNormal = new GUIContent ("Per Pixel Normal", "Normal map representing the terrain normals");
#if __MICROSPLAT_GLOBALTEXTURE__
static GUIContent geoTexOverride = new GUIContent ("Geo Texture Override", "If you want each terrain object to have it's own geo texture instead of the one defined in the material, add it here");
static GUIContent geoTintOverride = new GUIContent ("Tint Texture Override", "If you want each terrain object to have it's own global tint instead of the one defined in the material, add it here");
static GUIContent geoNormalOverride = new GUIContent ("Global Normal Override", "If you want each terrain object to have it's own global normal instead of the one defined in the material, add it here");
static GUIContent geoSAOMOverride = new GUIContent ("Global SOAM Override", "If you want each terrain to have it's own Smoothness(R), AO(G) and Metallic (B) map instead of the one defined in the material, add it here");
static GUIContent geoEmisOverride = new GUIContent ("Global Emissive Override", "If you want each terrain to have it's own Emissive map instead of the one defined in the material, set it here");
#endif
#if __MICROSPLAT_SCATTER__
static GUIContent scatterMapOverride = new GUIContent ("Scatter Map Override", "Scatter control map");
#endif
#if __MICROSPLAT_SNOW__
static GUIContent snowMaskOverride = new GUIContent ("Snow Mask Override", "If you want a unique snow mask on this terrain");
#endif
#if __MICROSPLAT_PROCTEX__
static GUIContent biomeOverride = new GUIContent("Biome Map Override", "Biome map for this terrain");
static GUIContent biomeOverride2 = new GUIContent ("Biome Map2 Override", "Biome map for this terrain");
static GUIContent CCavityMap = new GUIContent ("Cavity Map", "Cavity Map for procedural texturing based on flow and cavity");
#endif
#if (VEGETATION_STUDIO || VEGETATION_STUDIO_PRO)
static GUIContent CVSGrassMap = new GUIContent("Grass Map", "Grass Map from Vegetation Studio");
static GUIContent CVSShadowMap = new GUIContent("Shadow Map", "Shadow map texture from Vegetation Studio");
#endif
static GUIContent CBlendMat = new GUIContent("Blend Mat", "Blending material for terrain blending");
public string lastPath;
public MicroSplatCompressor.Options compressorOptions = new MicroSplatCompressor.Options ();
public override void OnInspectorGUI()
{
MicroSplatMeshTerrain msm = target as MicroSplatMeshTerrain;
EditorGUI.BeginChangeCheck();
msm.templateMaterial = EditorGUILayout.ObjectField(CTemplateMaterial, msm.templateMaterial, typeof(Material), false) as Material;
if (msm.propData == null)
{
msm.propData = MicroSplatShaderGUI.FindOrCreatePropTex(msm.templateMaterial);
EditorUtility.SetDirty(msm);
}
if (msm.keywordSO == null)
{
msm.keywordSO = MicroSplatUtilities.FindOrCreateKeywords(msm.templateMaterial);
EditorUtility.SetDirty(msm);
}
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(msm);
}
if (lastPath == null)
{
lastPath = Application.dataPath;
}
if (msm.templateMaterial != null && msm.propData == null)
{
msm.propData = MicroSplatShaderGUI.FindOrCreatePropTex(msm.templateMaterial);
}
EditorGUILayout.PropertyField(serializedObject.FindProperty("meshTerrains"), true);
EditorGUILayout.PropertyField(serializedObject.FindProperty("controlTextures"), true);
serializedObject.ApplyModifiedProperties();
#if __MICROSPLAT_PROCTEX__
if (msm.keywordSO != null && (msm.keywordSO.IsKeywordEnabled("_PROCEDURALTEXTURE") || msm.keywordSO.IsKeywordEnabled("_PCHEIGHTGRADIENT") || msm.keywordSO.IsKeywordEnabled("_PCHEIGHTHSV")))
{
var old = msm.procTexCfg;
msm.procTexCfg = MicroSplatProceduralTexture.FindOrCreateProceduralConfig(msm.templateMaterial);
if (old != msm.procTexCfg)
{
EditorUtility.SetDirty(msm);
}
}
#endif
#if __MICROSPLAT_TERRAINBLEND__ || __MICROSPLAT_STREAMS__
DoTerrainDescGUI();
#endif
EditorGUI.BeginChangeCheck ();
MicroSplatUtilities.DrawTextureField (msm, CPerPixelNormal, ref msm.perPixelNormal, "_PERPIXNORMAL");
#if __MICROSPLAT_GLOBALTEXTURE__
MicroSplatUtilities.DrawTextureField (msm, geoTexOverride, ref msm.geoTextureOverride, "_GEOMAP");
MicroSplatUtilities.DrawTextureField (msm, geoTintOverride, ref msm.tintMapOverride, "_GLOBALTINT");
MicroSplatUtilities.DrawTextureField (msm, geoNormalOverride, ref msm.globalNormalOverride, "_GLOBALNORMALS");
MicroSplatUtilities.DrawTextureField (msm, geoSAOMOverride, ref msm.globalSAOMOverride, "_GLOBALSMOOTHAOMETAL");
MicroSplatUtilities.DrawTextureField (msm, geoEmisOverride, ref msm.globalEmisOverride, "_GLOBALEMIS");
#endif
#if __MICROSPLAT_SCATTER__
MicroSplatUtilities.DrawTextureField (msm, scatterMapOverride, ref msm.scatterMapOverride, "_SCATTER");
#endif
#if __MICROSPLAT_SNOW__
MicroSplatUtilities.DrawTextureField (msm, snowMaskOverride, ref msm.snowMaskOverride, "_SNOWMASK");
#endif
#if __MICROSPLAT_ALPHAHOLE__
MicroSplatUtilities.DrawTextureField (msm, clipMapOverride, ref msm.clipMap, "_ALPHAHOLETEXTURE");
#endif
#if __MICROSPLAT_PROCTEX__
MicroSplatUtilities.DrawTextureField(msm, biomeOverride, ref msm.procBiomeMask, "_PCBIOMEMASK");
MicroSplatUtilities.DrawTextureField (msm, biomeOverride2, ref msm.procBiomeMask2, "_PCBIOMEMASK2");
MicroSplatUtilities.DrawTextureField(msm, CCavityMap, ref msm.cavityMap, "_PROCEDURALTEXTURE");
#endif
if (msm.propData == null && msm.templateMaterial != null)
{
msm.propData = MicroSplatShaderGUI.FindOrCreatePropTex (msm.templateMaterial);
if (msm.propData == null)
{
// this should really never happen, but users seem to have issues with unassigned propData's a lot. I think
// this is from external tools like MapMagic not creating it, but the above call should create it.
EditorGUILayout.HelpBox ("PropData is null, please assign", MessageType.Error);
msm.propData = EditorGUILayout.ObjectField("Per Texture Data", msm.propData, typeof(MicroSplatPropData), false) as MicroSplatPropData;
}
}
#if (VEGETATION_STUDIO || VEGETATION_STUDIO_PRO)
if (msm.keywordSO.IsKeywordEnabled("_VSGRASSMAP"))
{
EditorGUI.BeginChangeCheck();
msm.vsGrassMap = EditorGUILayout.ObjectField(CVSGrassMap, msm.vsGrassMap, typeof(Texture2D), false) as Texture2D;
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(msm);
}
}
if (msm.keywordSO.IsKeywordEnabled("_VSSHADOWMAP"))
{
EditorGUI.BeginChangeCheck();
msm.vsShadowMap = EditorGUILayout.ObjectField(CVSShadowMap, msm.vsShadowMap, typeof(Texture2D), false) as Texture2D;
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(msm);
}
}
#endif
MicroSplatCompressor.DrawGUI (msm, compressorOptions);
if (MicroSplatUtilities.DrawRollup("Debug", false, true))
{
EditorGUI.indentLevel += 2;
EditorGUILayout.HelpBox("These should not need to be edited unless something funky has happened. They are automatically managed by MicroSplat.", MessageType.Info);
msm.propData = EditorGUILayout.ObjectField("Per Texture Data", msm.propData, typeof(MicroSplatPropData), false) as MicroSplatPropData;
msm.keywordSO = EditorGUILayout.ObjectField("Keywords", msm.keywordSO, typeof(MicroSplatKeywords), false) as MicroSplatKeywords;
msm.blendMat = EditorGUILayout.ObjectField(CBlendMat, msm.blendMat, typeof(Material), false) as Material;
EditorGUI.indentLevel -= 2;
}
if (EditorGUI.EndChangeCheck ())
{
MicroSplatMeshTerrain.SyncAll();
}
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Sync"))
{
var mgr = target as MicroSplatMeshTerrain;
mgr.Sync();
}
if (GUILayout.Button("Sync All"))
{
MicroSplatMeshTerrain.SyncAll();
}
EditorGUILayout.EndHorizontal();
}
#endif
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2fb1ccb4a2e464252a9e9c781bbeea9b
timeCreated: 1573425373
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
//////////////////////////////////////////////////////
// MicroSplat
// Copyright (c) Jason Booth
//////////////////////////////////////////////////////
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using JBooth.MicroSplat;
#if __MICROSPLAT__
public partial class MicroSplatMeshTerrainEditor : Editor
{
public void DoTerrainDescGUI()
{
MicroSplatMeshTerrain bt = target as MicroSplatMeshTerrain;
if (bt.blendMat == null && bt.templateMaterial != null && bt.keywordSO != null && bt.keywordSO.IsKeywordEnabled("_TERRAINBLENDING"))
{
var path = AssetDatabase.GetAssetPath(bt.templateMaterial);
path = path.Replace(".mat", "_TerrainObjectBlend.mat");
bt.blendMat = AssetDatabase.LoadAssetAtPath<Material>(path);
if (bt.blendMat == null)
{
string shaderPath = path.Replace(".mat", ".shader");
Shader shader = AssetDatabase.LoadAssetAtPath<Shader>(shaderPath);
if (shader == null)
{
shaderPath = AssetDatabase.GetAssetPath(bt.templateMaterial.shader);
shaderPath = shaderPath.Replace(".shader", "_TerrainObjectBlend.shader");
shader = AssetDatabase.LoadAssetAtPath<Shader>(shaderPath);
}
if (shader != null)
{
Material mat = new Material(shader);
AssetDatabase.CreateAsset(mat, path);
AssetDatabase.SaveAssets();
MicroSplatMeshTerrain.SyncAll();
}
}
}
bt.terrainDescriptor.heightMap = (Texture2D)EditorGUILayout.ObjectField ("Height Map", bt.terrainDescriptor.heightMap, typeof (Texture2D), false);
}
}
#endif

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6d076c87e2e804d72b14df50fb81524f
timeCreated: 1573428307
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,123 @@
//////////////////////////////////////////////////////
// MicroSplat
// Copyright (c) Jason Booth
//////////////////////////////////////////////////////
using UnityEngine;
using System.Collections;
using UnityEditor;
using UnityEditor.Callbacks;
using System.Collections.Generic;
namespace JBooth.MicroSplat
{
#if __MICROSPLAT__
[InitializeOnLoad]
public class MicroSplatMeshTerrainModule : FeatureDescriptor
{
const string sDefine = "__MICROSPLAT_MESHTERRAIN__";
static MicroSplatMeshTerrainModule()
{
MicroSplatDefines.InitDefine(sDefine);
}
[PostProcessSceneAttribute (0)]
public static void OnPostprocessScene()
{
MicroSplatDefines.InitDefine(sDefine);
}
public override int DisplaySortOrder()
{
return -999;
}
public override string ModuleName()
{
return "MeshTerrain";
}
public enum DefineFeature
{
kNumFeatures,
}
public override bool HideModule ()
{
return true;
}
// Can we template these somehow?
public static string GetFeatureName(DefineFeature feature)
{
return System.Enum.GetName(typeof(DefineFeature), feature);
}
public static bool HasFeature(string[] keywords, DefineFeature feature)
{
string f = GetFeatureName(feature);
for (int i = 0; i < keywords.Length; ++i)
{
if (keywords[i] == f)
return true;
}
return false;
}
public override string GetVersion()
{
return "3.9";
}
public override void DrawFeatureGUI(MicroSplatKeywords keywords)
{
}
static TextAsset combinedFunc;
public override string[] Pack()
{
List<string> features = new List<string>();
return features.ToArray();
}
public override void Unpack(string[] keywords)
{
}
public override void InitCompiler(string[] paths)
{
}
public override void DrawShaderGUI(MicroSplatShaderGUI shaderGUI, MicroSplatKeywords keywords, Material mat, MaterialEditor materialEditor, MaterialProperty[] props)
{
}
public override void WriteProperties(string[] features, System.Text.StringBuilder sb)
{
}
public override void WriteFunctions(string [] features, System.Text.StringBuilder sb)
{
}
public override void ComputeSampleCounts(string[] features, ref int arraySampleCount, ref int textureSampleCount, ref int maxSamples, ref int tessellationSamples, ref int depTexReadLevel)
{
}
}
#endif
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 61bcbe87d80c049b4a2bef5b3def7799
timeCreated: 1573424615
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,472 @@
//////////////////////////////////////////////////////
// Terain To Mesh
// Copyright (c) Jason Booth
//////////////////////////////////////////////////////
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using JBooth.MicroSplat;
namespace JBooth.TerrainToMesh
{
#if __MICROSPLAT__ && __MICROSPLAT_MESHTERRAIN__
public class TerrainToMesh : EditorWindow
{
[MenuItem ("Window/MicroSplat/Terrain To Mesh")]
public static void ShowWindow ()
{
var window = GetWindow<JBooth.TerrainToMesh.TerrainToMesh> ();
if (window != null)
{
window.Show ();
window.Init ();
}
}
public List<Terrain> selectedTerrains = new List<Terrain> ();
void Init ()
{
Object [] objs = Selection.GetFiltered (typeof (Terrain), SelectionMode.Editable | SelectionMode.Deep);
selectedTerrains.Clear ();
for (int i = 0; i < objs.Length; ++i)
{
Terrain t = objs [i] as Terrain;
if (t == null)
continue;
selectedTerrains.Add (t);
}
}
void OnSelectionChange ()
{
Init ();
}
public class Settings
{
public int chunkDiv = 1;
public int subDiv = 64;
public bool convertMaterial = true;
public bool deleteTerrains = false;
public bool generateLowResShader = true;
public bool addColliders = false;
public string prefix = "";
public string postfix = "";
}
public Settings settings = new Settings ();
static GUIContent CChunkDiv = new GUIContent ("Chunks", "Number of objects to break terrains into per side");
static GUIContent CSubDiv = new GUIContent ("Sub Divisions", "Sub divisions per terrain chunk per side");
static GUIContent CAddColliders = new GUIContent ("Add Colliders", "Add colliders to terrain chunks. This is required for terrain blending");
void OnGUI ()
{
if (selectedTerrains.Count == 0)
{
EditorGUILayout.HelpBox ("Select terrains with MicroSplat on them to continue", MessageType.Info);
return;
}
for (int i = 0; i < selectedTerrains.Count; ++i)
{
if (selectedTerrains [0] == null || selectedTerrains [0].GetComponent<MicroSplatTerrain> () == null)
{
EditorGUILayout.HelpBox ("Terrain must be setup with MicroSplat to convert", MessageType.Error);
return;
}
}
settings.chunkDiv = EditorGUILayout.IntSlider (CChunkDiv, settings.chunkDiv, 1, 32);
settings.subDiv = EditorGUILayout.IntSlider (CSubDiv, settings.subDiv, 16, 170);
settings.addColliders = EditorGUILayout.Toggle (CAddColliders, settings.addColliders);
settings.convertMaterial = EditorGUILayout.Toggle ("Convert Material", settings.convertMaterial);
settings.generateLowResShader = EditorGUILayout.Toggle ("Generate Separate Shader", settings.generateLowResShader);
settings.deleteTerrains = EditorGUILayout.Toggle ("Delete Terrains", settings.deleteTerrains);
settings.prefix = EditorGUILayout.TextField ("Naming Prefix", settings.prefix);
settings.postfix = EditorGUILayout.TextField ("Naming Postfix", settings.postfix);
if (GUILayout.Button ("Convert"))
{
if (selectedTerrains [0] == null)
{
Debug.LogError ("Select a terrain with MicroSplat on it.");
return;
}
var mst = selectedTerrains [0].GetComponent<MicroSplatTerrain> ();
if (mst == null || mst.templateMaterial == null)
{
Debug.Log ("Did not find MicroSplatTerrain component and material template on terrain");
}
else
{
string baseDir = JBooth.MicroSplat.MicroSplatUtilities.RelativePathFromAsset (mst.templateMaterial);
if (settings.generateLowResShader)
{
baseDir += "/MeshTerrain/MicroSplatData";
if (!System.IO.Directory.Exists (baseDir))
{
System.IO.Directory.CreateDirectory (baseDir);
}
}
for (int i = 0; i < selectedTerrains.Count; ++i)
{
var meshPath = baseDir + "/" + selectedTerrains [i].name + "_meshes.asset";
Mesh root = new Mesh ();
root.name = "Meshes";
AssetDatabase.CreateAsset (root, meshPath);
Convert (selectedTerrains [i], baseDir, root, settings);
}
AssetDatabase.SaveAssets ();
AssetDatabase.Refresh();
MicroSplatObject.SyncAll();
}
}
}
static Mesh CreateSubChunk (Terrain t, Vector3 worldStart, Vector2 uvStart, int dx, int dy, int div, Settings s)
{
int chunkDiv = s.chunkDiv;
int subDiv = s.subDiv;
float size = t.terrainData.size.x;
float pSize = size * 0.5f;
pSize /= chunkDiv;
string meshName = div > 0 ? t.name + "_" + dx + "_" + dy : t.name;
Mesh mesh = new Mesh ();
mesh.name = meshName;
Vector3 [] vertices = new Vector3 [subDiv * subDiv];
Vector3 [] normals = new Vector3 [vertices.Length];
for (int z = 0; z < subDiv; z++)
{
float zPos = ((float)z / (subDiv - 1) - .5f) * pSize * 2;
for (int x = 0; x < subDiv; x++)
{
float xPos = ((float)x / (subDiv - 1) - .5f) * pSize * 2;
float uvX = (float)x / (float)(subDiv - 1);
float uvY = (float)z / (float)(subDiv - 1);
uvX /= (float)chunkDiv;
uvY /= (float)chunkDiv;
uvX += uvStart.x;
uvY += uvStart.y;
Vector3 worldPos = new Vector3 (xPos + pSize + worldStart.x, 0, zPos + pSize + worldStart.y);
worldPos += t.GetPosition ();
float yPos = t.SampleHeight (worldPos);
Vector3 nm = t.terrainData.GetInterpolatedNormal (xPos + pSize, zPos + pSize);
vertices [x + z * subDiv] = new Vector3 (xPos + pSize + worldStart.x, yPos, zPos + pSize + worldStart.y);
normals [x + z * subDiv] = new Vector3 (nm.x, nm.y, nm.z);
}
}
Vector2 [] uvs = new Vector2 [vertices.Length];
for (int v = 0; v < subDiv; v++)
{
for (int u = 0; u < subDiv; u++)
{
Vector2 uv = new Vector2 ((float)u / (subDiv - 1), (float)v / (subDiv - 1));
uv.x /= chunkDiv;
uv.y /= chunkDiv;
uv.x += uvStart.x;
uv.y += uvStart.y;
uvs [u + v * subDiv] = uv;
}
}
int nbFaces = (subDiv - 1) * (subDiv - 1);
int [] triangles = new int [nbFaces * 6];
int tidx = 0;
for (int face = 0; face < nbFaces; face++)
{
// Retrieve lower left corner from face ind
int i = face % (subDiv - 1) + (face / (subDiv - 1) * subDiv);
triangles [tidx++] = i + subDiv;
triangles [tidx++] = i + 1;
triangles [tidx++] = i;
triangles [tidx++] = i + subDiv;
triangles [tidx++] = i + subDiv + 1;
triangles [tidx++] = i + 1;
}
mesh.vertices = vertices;
mesh.normals = normals;
mesh.uv = uvs;
mesh.triangles = triangles;
mesh.RecalculateNormals ();
mesh.RecalculateTangents ();
mesh.RecalculateBounds ();
return mesh;
}
static Texture2D SaveHeightTexture (RenderTexture rt, string basePath)
{
Texture2D tex = new Texture2D (rt.width, rt.height, TextureFormat.R16, true, true);
var old = RenderTexture.active;
RenderTexture.active = rt;
tex.ReadPixels (new Rect (0, 0, tex.width, tex.height), 0, 0);
tex.Apply ();
RenderTexture.active = old;
JBooth.MicroSplat.HDTextureImporter.Write (tex, basePath + "_height", true, true);
AssetDatabase.Refresh ();
return AssetDatabase.LoadAssetAtPath<Texture2D> (basePath + "_height.hdtexture");
}
public static void Convert (Terrain t, string baseDir, Mesh root, Settings s)
{
int chunkDiv = s.chunkDiv;
var mst = t.GetComponent<MicroSplatTerrain> ();
if (mst == null)
{
Debug.LogError ("MicroSplat Terrain missing");
return;
}
var oldInstance = mst.terrain.drawInstanced;
mst.terrain.drawInstanced = false;
float chunkSkip = t.terrainData.size.x / (float)chunkDiv;
GameObject meshes = new GameObject (s.prefix + t.name + s.postfix);
meshes.transform.position = t.transform.position;
#if __MICROSPLAT_STREAMS__
var origst = mst.GetComponent<StreamManager> ();
if (origst != null)
{
var newst = meshes.AddComponent<StreamManager> ();
EditorUtility.CopySerialized (origst, newst);
}
#endif
MicroSplatMeshTerrain msm = meshes.AddComponent<MicroSplatMeshTerrain> ();
msm.perPixelNormal = mst.perPixelNormal;
msm.blendMat = mst.blendMat;
msm.propData = mst.propData;
msm.streamTexture = mst.streamTexture;
if (mst.keywordSO.IsKeywordEnabled("_DYNAMICFLOWS") || mst.keywordSO.IsKeywordEnabled("_TERRAINBLENDING"))
{
msm.terrainDescriptor.heightMap = SaveHeightTexture(mst.terrain.terrainData.heightmapTexture, baseDir + "/" + mst.name);
}
if (mst.keywordSO.IsKeywordEnabled("_PERPIXNORMAL") || mst.keywordSO.IsKeywordEnabled("_TERRAINBLENDING") || (mst.terrain != null && oldInstance))
{
msm.perPixelNormal = MicroSplatTerrainEditor.GenerateTerrainNormalMap(mst);
msm.terrainDescriptor.normalMap = msm.perPixelNormal;
}
#if (VEGETATION_STUDIO || VEGETATION_STUDIO_PRO)
msm.vsGrassMap = mst.vsGrassMap;
msm.vsShadowMap = mst.vsShadowMap;
#endif
#if __MICROSPLAT_ALPHAHOLE__
msm.clipMap = mst.clipMap;
#endif
#if __MICROSPLAT_PROCTEX__
msm.procBiomeMask = mst.procBiomeMask;
msm.procBiomeMask2 = mst.procBiomeMask2;
msm.procTexCfg = mst.procTexCfg;
msm.cavityMap = mst.cavityMap;
#endif
#if __MICROSPLAT_SCATTER__
msm.scatterMapOverride = mst.scatterMapOverride;
#endif
#if __MICROSPLAT_GLOBALTEXTURE__
msm.tintMapOverride = mst.tintMapOverride;
msm.geoTextureOverride = mst.geoTextureOverride;
msm.globalNormalOverride = mst.globalNormalOverride;
msm.globalEmisOverride = mst.globalEmisOverride;
msm.globalSAOMOverride = mst.globalSAOMOverride;
#endif
#if __MICROSPLAT_SNOW__
msm.snowMaskOverride = mst.snowMaskOverride;
#endif
if (s.convertMaterial)
{
if (s.generateLowResShader)
{
if (!System.IO.File.Exists (baseDir + "/MicroSplat.mat"))
{
System.IO.File.Copy(AssetDatabase.GetAssetPath(mst.templateMaterial), baseDir + "/MicroSplat.mat");
}
if (!System.IO.File.Exists (baseDir + "/MicroSplat_keywords.asset"))
{
System.IO.File.Copy(AssetDatabase.GetAssetPath (mst.keywordSO), baseDir + "/MicroSplat_keywords.asset");
}
if (!System.IO.File.Exists (baseDir + "/MicroSplat.shader"))
{
System.IO.File.Copy(AssetDatabase.GetAssetPath (mst.templateMaterial.shader), baseDir + "/MicroSplat.shader");
}
AssetDatabase.Refresh ();
msm.templateMaterial = AssetDatabase.LoadAssetAtPath<Material> (baseDir + "/MicroSplat.mat");
msm.templateMaterial.shader = AssetDatabase.LoadAssetAtPath<Shader> (baseDir + "/MicroSplat.shader");
msm.keywordSO = AssetDatabase.LoadAssetAtPath<MicroSplatKeywords> (baseDir + "/MicroSplat_keywords.asset");
msm.templateMaterial.CopyPropertiesFromMaterial (mst.templateMaterial);
if (!msm.keywordSO.IsKeywordEnabled ("_MICROMESHTERRAIN"))
{
msm.keywordSO.EnableKeyword ("_MICROMESHTERRAIN");
}
if (msm.keywordSO.IsKeywordEnabled ("_OUTPUTDIGGER"))
{
msm.keywordSO.DisableKeyword ("_OUTPUTDIGGER");
}
if (msm.keywordSO.IsKeywordEnabled ("_MICRODIGGERMESH"))
{
msm.keywordSO.DisableKeyword ("_MICRODIGGERMESH");
}
if (oldInstance)
{
msm.keywordSO.EnableKeyword ("_PERPIXNORMAL");
}
if (msm.keywordSO.IsKeywordEnabled("_MICROTERRAIN"))
{
msm.keywordSO.DisableKeyword("_MICROTERRAIN");
}
MicroSplatShaderGUI.MicroSplatCompiler c = new MicroSplatShaderGUI.MicroSplatCompiler ();
c.Compile (msm.templateMaterial);
}
}
// export splat textures
var textures = t.terrainData.alphamapTextures;
for (int i = 0; i < textures.Length; ++i)
{
var path = baseDir + "/splat_" + t.name + i.ToString ();
var bytes = textures [i].EncodeToTGA ();
System.IO.File.WriteAllBytes (path + ".tga", bytes);
AssetDatabase.Refresh ();
var ai = AssetImporter.GetAtPath (MicroSplat.MicroSplatUtilities.MakeRelativePath (path + ".tga"));
var ti = ai as TextureImporter;
if (ti != null)
{
var ps = ti.GetDefaultPlatformTextureSettings ();
if (ti.isReadable == true ||
ti.wrapMode != TextureWrapMode.Clamp || ps.format != TextureImporterFormat.RGBA32 ||
ps.textureCompression != TextureImporterCompression.Compressed ||
ps.overridden != true ||
ti.filterMode != FilterMode.Bilinear ||
ti.sRGBTexture != false)
{
ti.sRGBTexture = false;
ti.filterMode = FilterMode.Bilinear;
ti.mipmapEnabled = true;
ti.wrapMode = TextureWrapMode.Clamp;
ti.isReadable = false;
ps.format = TextureImporterFormat.Automatic;
ps.textureCompression = TextureImporterCompression.Compressed;
ps.overridden = false;
ti.SetPlatformTextureSettings (ps);
ti.SaveAndReimport ();
}
}
}
msm.controlTextures = new Texture2D [textures.Length];
for (int i = 0; i < textures.Length; ++i)
{
var p = MicroSplat.MicroSplatUtilities.MakeRelativePath (baseDir + "/splat_" + t.gameObject.name + i + ".tga");
Texture2D tex = AssetDatabase.LoadAssetAtPath<Texture2D> (p);
msm.controlTextures [i] = tex;
}
MeshRenderer [] rends = new MeshRenderer [chunkDiv * chunkDiv];
int chunkIdx = 0;
for (int chunkX = 0; chunkX < chunkDiv; ++chunkX)
{
for (int chunkY = 0; chunkY < chunkDiv; ++chunkY)
{
Vector2 worldStart = new Vector2 (chunkX * chunkSkip, chunkY * chunkSkip);
Vector2 uvStart = new Vector2 (worldStart.x / t.terrainData.size.x, worldStart.y / t.terrainData.size.x);
Mesh mesh = CreateSubChunk (t, worldStart, uvStart, chunkX, chunkY, chunkDiv, s);
AssetDatabase.AddObjectToAsset (mesh, root);
GameObject go = new GameObject (t.name + "_" + chunkX + "_" + chunkY);
MeshRenderer rend = go.AddComponent<MeshRenderer> ();
var filter = go.AddComponent<MeshFilter> ();
filter.sharedMesh = mesh;
if (s.addColliders)
{
var mc = go.AddComponent<MeshCollider> ();
mc.sharedMesh = mesh;
}
go.transform.position = t.GetPosition ();
go.transform.SetParent (meshes.transform);
rends [chunkIdx] = rend;
chunkIdx++;
}
}
msm.meshTerrains = rends;
if (chunkDiv == 1)
{
// remove parent object
var child = msm.transform.GetChild (0).gameObject;
var nm = child.AddComponent<MicroSplatMeshTerrain> ();
EditorUtility.CopySerialized (msm, nm);
child.transform.SetParent (null, true);
DestroyImmediate (meshes);
nm.Sync ();
}
else
{
MicroSplatObject.SyncAll();
}
mst.terrain.drawInstanced = oldInstance;
if (s.deleteTerrains)
{
DestroyImmediate (t);
}
}
}
#endif
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0a3637fb148b04f69a30393bc1a249b3
timeCreated: 1528167834
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
{
"reference": "GUID:4bdfb2239705740718731d0b4d54061d"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 83c40350f019d4882b37abe8e78b3b2a
AssemblyDefinitionReferenceImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,206 @@
//////////////////////////////////////////////////////
// MicroSplat
// Copyright (c) Jason Booth
//////////////////////////////////////////////////////
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using JBooth.MicroSplat;
[ExecuteInEditMode]
[DisallowMultipleComponent]
public class MicroSplatMeshTerrain : MicroSplatObject
{
public delegate void MaterialSyncAll();
public delegate void MaterialSync(Material m);
public static event MaterialSyncAll OnMaterialSyncAll;
public event MaterialSync OnMaterialSync;
static List<MicroSplatMeshTerrain> sInstances = new List<MicroSplatMeshTerrain>();
public MeshRenderer[] meshTerrains;
public Texture2D[] controlTextures;
[HideInInspector]
public Material meshBlendMat;
[HideInInspector]
public Material meshBlendMatInstance;
public TerrainDescriptor terrainDescriptor;
#if UNITY_EDITOR
void Awake()
{
Sync();
}
#endif
void OnEnable()
{
sInstances.Add(this);
#if UNITY_EDITOR
Sync();
#endif
}
public override TerrainDescriptor GetTerrainDescriptor ()
{
if (perPixelNormal != null)
{
terrainDescriptor.normalMap = perPixelNormal;
}
return terrainDescriptor;
}
#if !UNITY_EDITOR
void Start()
{
Sync();
}
#endif
void OnDisable()
{
sInstances.Remove(this);
Cleanup();
}
void Cleanup()
{
if (matInstance != null && matInstance != templateMaterial)
{
DestroyImmediate(matInstance);
}
}
void SyncMeshBlendMat()
{
if (meshBlendMatInstance != null && matInstance != null)
{
meshBlendMatInstance.CopyPropertiesFromMaterial(matInstance);
}
}
Material GetMeshBlendMatInstance()
{
if (meshBlendMat != null)
{
if (meshBlendMatInstance == null)
{
meshBlendMatInstance = new Material(meshBlendMat);
SyncMeshBlendMat();
}
if (meshBlendMatInstance.shader != meshBlendMat.shader)
{
meshBlendMatInstance.shader = meshBlendMat.shader;
SyncMeshBlendMat();
}
}
return meshBlendMatInstance;
}
void ApplyMeshBlendMap()
{
if (meshBlendMat != null)
{
if (meshBlendMatInstance == null)
{
meshBlendMatInstance = new Material(meshBlendMat);
}
SyncMeshBlendMat();
}
}
public void Sync()
{
if (templateMaterial == null)
return;
if (keywordSO == null)
{
RevisionFromMat();
}
if (keywordSO == null)
return;
if (meshTerrains == null || meshTerrains.Length == 0)
return;
ApplySharedData (templateMaterial);
if (matInstance == null)
{
matInstance = new Material (templateMaterial);
}
matInstance.CopyPropertiesFromMaterial (templateMaterial);
matInstance.hideFlags = HideFlags.HideAndDontSave;
ApplyMaps(matInstance);
if (controlTextures != null && controlTextures.Length > 0)
{
ApplyControlTextures(controlTextures, matInstance);
}
for (int i = 0; i < meshTerrains.Length; ++i)
{
var rend = meshTerrains [i];
if (rend == null)
continue;
rend.sharedMaterial = matInstance;
}
if (OnMaterialSync != null)
{
OnMaterialSync(matInstance);
}
ApplyBlendMap();
ApplyMeshBlendMap();
}
public override Bounds GetBounds()
{
Bounds b = new Bounds();
bool s = false;
for (int i = 0; i < meshTerrains.Length; ++i)
{
var rend = meshTerrains [i];
if (rend == null)
continue;
if (!s)
{
b = rend.bounds;
s = true;
}
else
{
b.Encapsulate (rend.bounds);
}
}
return b;
}
public static new void SyncAll()
{
for (int i = 0; i < sInstances.Count; ++i)
{
sInstances[i].Sync();
}
if (OnMaterialSyncAll != null)
{
OnMaterialSyncAll();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ed2b1cb282dfc488bacb79627bfa6e54
timeCreated: 1573424566
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: