/// <summary> /// Convertes all UMAMaterial channel Material Property names if they match. /// </summary> /// <param name="From"></param> /// <param name="To"></param> /// <returns></returns> static bool ConvertUMAMaterials(string From, string To) { string[] guids = AssetDatabase.FindAssets("t:UMAMaterial"); int dirtycount = 0; foreach (string guid in guids) { bool matModified = false; string path = AssetDatabase.GUIDToAssetPath(guid); UMAMaterial umat = AssetDatabase.LoadAssetAtPath <UMAMaterial>(path); if (umat.material.shader.name.ToLower().StartsWith("standard") || umat.material.shader.name.ToLower().Contains("lit")) { for (int i = 0; i < umat.channels.Length; i++) { if (umat.channels[i].materialPropertyName == From) { umat.channels[i].materialPropertyName = To; matModified = true; } } } if (matModified) { dirtycount++; EditorUtility.SetDirty(umat); } } if (dirtycount > 0) { AssetDatabase.SaveAssets(); return(true); } return(false); }
void OnGUI() { GUILayout.Label("UMA Slot Builder"); GUILayout.Space(20); normalReferenceMesh = EditorGUILayout.ObjectField("Seams Mesh (Optional)", normalReferenceMesh, typeof(SkinnedMeshRenderer), false) as SkinnedMeshRenderer; slotMesh = EditorGUILayout.ObjectField("Slot Mesh", slotMesh, typeof(SkinnedMeshRenderer), false) as SkinnedMeshRenderer; slotMaterial = EditorGUILayout.ObjectField("UMAMaterial", slotMaterial, typeof(UMAMaterial), false) as UMAMaterial; slotFolder = EditorGUILayout.ObjectField("Slot Destination Folder", slotFolder, typeof(UnityEngine.Object), false) as UnityEngine.Object; EnforceFolder(ref slotFolder); slotName = EditorGUILayout.TextField("Element Name", slotName); if (GUILayout.Button("Create Slot")) { Debug.Log("Processing..."); if (CreateSlot() != null) { Debug.Log("Success."); } } GUILayout.Label("", EditorStyles.boldLabel); Rect dropArea = GUILayoutUtility.GetRect(0.0f, 50.0f, GUILayout.ExpandWidth(true)); GUI.Box(dropArea, "Drag meshes here"); GUILayout.Label("Automatic Drag and Drop processing", EditorStyles.boldLabel); relativeFolder = EditorGUILayout.ObjectField("Relative Folder", relativeFolder, typeof(UnityEngine.Object), false) as UnityEngine.Object; EnforceFolder(ref relativeFolder); DropAreaGUI(dropArea); }
private UMAData.GeneratedMaterial FindOrCreateGeneratedMaterial(UMAMaterial umaMaterial, UMARendererAsset renderer = null) { if (umaMaterial.materialType == UMAMaterial.MaterialType.Atlas) { foreach (var atlassedMaterial in atlassedMaterials) { if (atlassedMaterial.umaMaterial == umaMaterial && atlassedMaterial.rendererAsset == renderer) { return(atlassedMaterial); } else { if (atlassedMaterial.umaMaterial.Equals(umaMaterial) && atlassedMaterial.rendererAsset == renderer) { return(atlassedMaterial); } } } } var res = new UMAData.GeneratedMaterial(); res.rendererAsset = renderer; res.umaMaterial = umaMaterial; res.material = UnityEngine.Object.Instantiate(umaMaterial.material) as Material; res.material.name = umaMaterial.material.name; #if UNITY_WEBGL res.material.shader = Shader.Find(res.material.shader.name); #endif res.material.CopyPropertiesFromMaterial(umaMaterial.material); atlassedMaterials.Add(res); generatedMaterials.Add(res); return(res); }
private UMAData.GeneratedMaterial FindOrCreateGeneratedMaterial(UMAMaterial umaMaterial) { if (umaMaterial.materialType == UMAMaterial.MaterialType.Atlas) { foreach (var atlassedMaterial in atlassedMaterials) { if (atlassedMaterial.umaMaterial == umaMaterial) { return(atlassedMaterial); } else { if (atlassedMaterial.umaMaterial.Equals(umaMaterial)) { return(atlassedMaterial); } } } } var res = new UMAData.GeneratedMaterial(); if (umaMaterial.RequireSeperateRenderer) { res.renderer = rendererCount++; } res.umaMaterial = umaMaterial; res.material = UnityEngine.Object.Instantiate(umaMaterial.material) as Material; res.material.name = umaMaterial.material.name; atlassedMaterials.Add(res); generatedMaterials.Add(res); return(res); }
private UMAData.GeneratedMaterial FindOrCreateGeneratedMaterial(UMAMaterial umaMaterial) { if (umaMaterial.materialType != UMAMaterial.MaterialType.Atlas) { var res = new UMAData.GeneratedMaterial(); res.umaMaterial = umaMaterial; res.material = UnityEngine.Object.Instantiate(umaMaterial.material) as Material; res.material.name = umaMaterial.material.name; generatedMaterials.Add(res); return(res); } else { foreach (var atlassedMaterial in atlassedMaterials) { if (atlassedMaterial.umaMaterial == umaMaterial) { return(atlassedMaterial); } } var res = new UMAData.GeneratedMaterial(); res.umaMaterial = umaMaterial; res.material = UnityEngine.Object.Instantiate(umaMaterial.material) as Material; res.material.name = umaMaterial.material.name; atlassedMaterials.Add(res); generatedMaterials.Add(res); return(res); } }
public void Assign(SlotDataAsset source) { slotName = source.slotName; nameHash = source.nameHash; material = source.material; overlayScale = source.overlayScale; animatedBoneNames = source.animatedBoneNames; animatedBoneHashes = source.animatedBoneHashes; meshData = source.meshData; subMeshIndex = source.subMeshIndex; slotGroup = source.slotGroup; tags = source.tags; }
/// <summary> /// Checks if UMAMaterials are effectively equal. /// Useful when comparing materials from asset bundles, that would otherwise say they are different to ones in the binary /// And procedural materials which can be output compatible even if they are generated from different sources /// </summary> /// <param name="material">The material to compare</param> /// <returns></returns> public bool Equals(UMAMaterial material) { if (this.GetInstanceID() == material.GetInstanceID()) { return(true); } else { if (this.material.name != material.material.name) { return(false); } if (this.material.shader != material.material.shader) { return(false); } if (this.material.renderQueue != material.material.renderQueue) { return(false); } if (this.materialType != material.materialType) { return(false); } if (this.channels.Length != material.channels.Length) { return(false); } for (int i = 0; i < this.channels.Length; i++) { MaterialChannel thisChannel = this.channels[i]; MaterialChannel otherChannel = material.channels[i]; if (thisChannel.channelType != otherChannel.channelType) { return(false); } if (thisChannel.materialPropertyName != otherChannel.materialPropertyName) { return(false); } } return(true); } }
/// <summary> /// Checks if UMAMaterials are effectively equal. /// Useful when comparing materials from asset bundles, that would otherwise say they are different to ones in the binary /// And procedural materials which can be output compatible even if they are generated from different sources /// </summary> /// <param name="material">The material to compare</param> /// <returns></returns> public bool Equals(UMAMaterial material) { if (this.name == material.name) { return(true); } else { return(false); } /* * if (this.GetInstanceID() == material.GetInstanceID()) * { * return true; * } * else * { * if (this.material.name != material.material.name) * return false; * //if (this.material.shader != material.material.shader) * // return false; * if (this.material.renderQueue != material.material.renderQueue) * return false; * if (this.materialType != material.materialType) * return false; * if (this.channels.Length != material.channels.Length) * return false; * for (int i = 0; i < this.channels.Length; i++) * { * MaterialChannel thisChannel = this.channels[i]; * MaterialChannel otherChannel = material.channels[i]; * if (thisChannel.channelType != otherChannel.channelType) * return false; * if (thisChannel.materialPropertyName != otherChannel.materialPropertyName) * return false; * } * * return true; * } */ }
/// <summary> /// Checks if UMAMaterials are effectively equal. Useful when comparing materials from asset bundles, that would otherwise say they are different to ones in the binary /// </summary> /// <param name="material">The material to compare</param> /// <returns></returns> public bool Equals(UMAMaterial material) { if (this.GetInstanceID() == material.GetInstanceID()) { return true; } else { if (this.name == material.name && this.material.name == material.material.name && this.materialType == material.materialType && this.channels.Length == material.channels.Length) { return true; } else { return false; } } }
/// <summary> /// Checks if UMAMaterials are effectively equal. Useful when comparing materials from asset bundles, that would otherwise say they are different to ones in the binary /// </summary> /// <param name="material">The material to compare</param> /// <returns></returns> public bool Equals(UMAMaterial material) { if (this.GetInstanceID() == material.GetInstanceID()) { return(true); } else { if (this.name == material.name && this.material.name == material.material.name && this.materialType == material.materialType && this.channels.Length == material.channels.Length) { return(true); } else { return(false); } } }
/// <summary> /// Setup data for atlas building. /// </summary> /// <param name="_umaData">UMA data.</param> /// <param name="_umaGenerator">UMA generator.</param> public void ProcessTexture(UMAData _umaData, UMAGeneratorBase _umaGenerator) { umaData = _umaData; umaGenerator = _umaGenerator; if (umaGenerator is UMAGenerator) { fastPath = (umaGenerator as UMAGenerator).fastGeneration; } if (umaData.atlasResolutionScale <= 0) { umaData.atlasResolutionScale = 1f; } var textureMerge = umaGenerator.textureMerge; textureMerge.RefreshMaterials(); if (textureMerge == null) { if (Debug.isDebugBuild) { Debug.LogError("TextureMerge is null!"); } // yield return null; } try { for (int atlasIndex = umaData.generatedMaterials.materials.Count - 1; atlasIndex >= 0; atlasIndex--) { var generatedMaterial = umaData.generatedMaterials.materials[atlasIndex]; //Rendering Atlas int moduleCount = 0; //Process all necessary TextureModules for (int i = 0; i < generatedMaterial.materialFragments.Count; i++) { if (!generatedMaterial.materialFragments[i].isRectShared && !generatedMaterial.materialFragments[i].isNoTextures) { moduleCount++; moduleCount = moduleCount + generatedMaterial.materialFragments[i].overlays.Length; } } textureMerge.EnsureCapacity(moduleCount); var slotData = generatedMaterial.materialFragments[0].slotData; resultingTextures = new Texture[slotData.material.channels.Length]; for (int textureType = slotData.material.channels.Length - 1; textureType >= 0; textureType--) { switch (slotData.material.channels[textureType].channelType) { case UMAMaterial.ChannelType.Texture: case UMAMaterial.ChannelType.DiffuseTexture: case UMAMaterial.ChannelType.NormalMap: case UMAMaterial.ChannelType.DetailNormalMap: { textureMerge.Reset(); for (int i = 0; i < generatedMaterial.materialFragments.Count; i++) { textureMerge.SetupModule(generatedMaterial, i, textureType); } //last element for this textureType moduleCount = 0; int width = Mathf.FloorToInt(generatedMaterial.cropResolution.x); int height = Mathf.FloorToInt(generatedMaterial.cropResolution.y); if (width == 0 || height == 0) { continue; } //this should be restricted to >= 1 but 0 was allowed before and projects may have the umaMaterial value serialized to 0. float downSample = (slotData.material.channels[textureType].DownSample == 0) ? 1f : (1f / slotData.material.channels[textureType].DownSample); destinationTexture = new RenderTexture(Mathf.FloorToInt(generatedMaterial.cropResolution.x * umaData.atlasResolutionScale * downSample), Mathf.FloorToInt(generatedMaterial.cropResolution.y * umaData.atlasResolutionScale * downSample), 0, slotData.material.channels[textureType].textureFormat, RenderTextureReadWrite.Linear); destinationTexture.filterMode = FilterMode.Point; destinationTexture.useMipMap = umaGenerator.convertMipMaps && !umaGenerator.convertRenderTexture; destinationTexture.name = slotData.material.name + " Chan " + textureType + " frame: " + Time.frameCount; //Draw all the Rects here Color backgroundColor; UMAMaterial.ChannelType channelType = slotData.material.channels[textureType].channelType; if (slotData.material.MaskWithCurrentColor && (channelType == UMAMaterial.ChannelType.DiffuseTexture || channelType == UMAMaterial.ChannelType.Texture || channelType == UMAMaterial.ChannelType.TintedTexture)) { backgroundColor = slotData.material.maskMultiplier * textureMerge.camBackgroundColor; } else { backgroundColor = UMAMaterial.GetBackgroundColor(slotData.material.channels[textureType].channelType); } textureMerge.DrawAllRects(destinationTexture, width, height, backgroundColor, umaGenerator.SharperFitTextures); //PostProcess textureMerge.PostProcess(destinationTexture, slotData.material.channels[textureType].channelType); if (umaGenerator.convertRenderTexture || slotData.material.channels[textureType].ConvertRenderTexture) { #region Convert Render Textures // if (!fastPath) yield return 25; Texture2D tempTexture; tempTexture = new Texture2D(destinationTexture.width, destinationTexture.height, TextureFormat.ARGB32, umaGenerator.convertMipMaps, true); int xblocks = destinationTexture.width / 512; int yblocks = destinationTexture.height / 512; if (xblocks == 0 || yblocks == 0 || fastPath) { RenderTexture.active = destinationTexture; //Debug.Log("CVT-FP Activated " + destinationTexture.name); tempTexture.ReadPixels(new Rect(0, 0, destinationTexture.width, destinationTexture.height), 0, 0, umaGenerator.convertMipMaps); // Debug.Log("CVT-FP Cleared " + destinationTexture.name); } else { // figures that ReadPixels works differently on OpenGL and DirectX, someday this code will break because Unity fixes this bug! if (IsOpenGL()) { for (int x = 0; x < xblocks; x++) { for (int y = 0; y < yblocks; y++) { RenderTexture.active = destinationTexture; // Debug.Log("CVT-SP OGL Activated " + destinationTexture.name+" "+x+" "+y); tempTexture.ReadPixels(new Rect(x * 512, y * 512, 512, 512), x * 512, y * 512, umaGenerator.convertMipMaps); // Debug.Log("CVT-SP OGL Cleared " + destinationTexture.name + " " + x + " " + y); // yield return 8; } } } else { for (int x = 0; x < xblocks; x++) { for (int y = 0; y < yblocks; y++) { // Debug.Log("CVT-SP NOTOGL Activated " + destinationTexture.name + " " + x + " " + y); RenderTexture.active = destinationTexture; tempTexture.ReadPixels(new Rect(x * 512, destinationTexture.height - 512 - y * 512, 512, 512), x * 512, y * 512, umaGenerator.convertMipMaps); // Debug.Log("CVT-SP NOTOGL Cleared " + destinationTexture.name + " " + x + " " + y); // yield return 8; } } } } resultingTextures[textureType] = tempTexture as Texture; destinationTexture.Release(); UnityEngine.GameObject.DestroyImmediate(destinationTexture); // if (!fastPath) yield return 6; tempTexture = resultingTextures[textureType] as Texture2D; tempTexture.Apply(); tempTexture.wrapMode = TextureWrapMode.Repeat; tempTexture.anisoLevel = slotData.material.AnisoLevel; tempTexture.mipMapBias = slotData.material.MipMapBias; tempTexture.filterMode = slotData.material.MatFilterMode; //if (slotData.asset.material.channels[textureType].Compression != UMAMaterial.CompressionSettings.None) //{ // tempTexture.Compress(slotData.asset.material.channels[textureType].Compression == UMAMaterial.CompressionSettings.HighQuality); // } resultingTextures[textureType] = tempTexture; if (!slotData.material.channels[textureType].NonShaderTexture) { generatedMaterial.material.SetTexture(slotData.material.channels[textureType].materialPropertyName, tempTexture); } #endregion } else { destinationTexture.anisoLevel = slotData.material.AnisoLevel; destinationTexture.mipMapBias = slotData.material.MipMapBias; destinationTexture.filterMode = slotData.material.MatFilterMode; destinationTexture.wrapMode = TextureWrapMode.Repeat; resultingTextures[textureType] = destinationTexture; if (!slotData.material.channels[textureType].NonShaderTexture) { generatedMaterial.material.SetTexture(slotData.material.channels[textureType].materialPropertyName, destinationTexture); } } break; } case UMAMaterial.ChannelType.MaterialColor: { if (slotData.material.channels[textureType].NonShaderTexture) { break; } generatedMaterial.material.SetColor(slotData.material.channels[textureType].materialPropertyName, generatedMaterial.materialFragments[0].baseColor); break; } case UMAMaterial.ChannelType.TintedTexture: { for (int i = 0; i < generatedMaterial.materialFragments.Count; i++) { var fragment = generatedMaterial.materialFragments[i]; if (fragment.isRectShared) { continue; } for (int j = 0; j < fragment.baseOverlay.textureList.Length; j++) { if (fragment.baseOverlay.textureList[j] != null) { if (!slotData.material.channels[textureType].NonShaderTexture) { generatedMaterial.material.SetTexture(slotData.material.channels[j].materialPropertyName, fragment.baseOverlay.textureList[j]); } if (j == 0) { generatedMaterial.material.color = fragment.baseColor; } } } foreach (var overlay in fragment.overlays) { if (generatedMaterial.textureNameList == null) { for (int j = 0; j < overlay.textureList.Length; j++) { if (overlay.textureList[j] != null) { if (!slotData.material.channels[textureType].NonShaderTexture) { generatedMaterial.material.SetTexture(slotData.material.channels[j].materialPropertyName, overlay.textureList[j]); } } } } } } break; } } } generatedMaterial.resultingAtlasList = resultingTextures; } } finally { RenderTexture.active = null; } }
public void LoadFromIndex() { material = UMAAssetIndexer.Instance.GetAsset <UMAMaterial>(materialName); }
public static bool MaterialIsValid(UMAMaterial material) { return(material != null && !string.IsNullOrEmpty(material.name)); }
/// <summary> /// Validate the OverlayData against the requirements of a particular UMAMaterial. /// </summary> /// <param name="targetMaterial">UMAMaterial to try and match.</param> /// <param name="isBaseOverlay">Is this the first overlay being applied?</param> internal bool Validate(UMAMaterial targetMaterial, bool isBaseOverlay) { bool valid = true; if (asset.material != targetMaterial) { if (!asset.material.Equals(targetMaterial)) { Debug.LogError(string.Format("Overlay '{0}' doesn't have the expected UMA Material: '{1}'", asset.overlayName, targetMaterial.name)); valid = false; } } if (asset.textureCount != targetMaterial.channels.Length) { Debug.LogError(string.Format("Overlay '{0}' doesn't have the right number of channels", asset.overlayName)); valid = false; } else { // HACK - Assume that procedural materials can always generate all channels if (this.isProcedural) { } // All channels must be initialized by the base overlay, only channel 0 in others else { for (int i = 0; i < targetMaterial.channels.Length; i++) { if ((asset.textureList[i] == null) && (targetMaterial.channels[i].channelType != UMAMaterial.ChannelType.MaterialColor)) { Debug.LogError(string.Format("Overlay '{0}' missing required texture in channel {1}", asset.overlayName, i)); valid = false; } if (!isBaseOverlay) { break; } } } } if (colorData.channelMask.Length < targetMaterial.channels.Length) { // Fixup colorData if moving from Legacy to PBR materials int oldsize = colorData.channelMask.Length; System.Array.Resize(ref colorData.channelMask, targetMaterial.channels.Length); System.Array.Resize(ref colorData.channelAdditiveMask, targetMaterial.channels.Length); for (int i = oldsize; i > targetMaterial.channels.Length; i++) { colorData.channelMask[i] = Color.white; colorData.channelAdditiveMask[i] = Color.black; } Debug.LogWarning(string.Format("Overlay '{0}' missing required color data. Resizing and adding defaults", asset.overlayName)); } return(valid); }
protected override IEnumerator workerMethod() { var textureMerge = umaGenerator.textureMerge; if (textureMerge == null) { if (Debug.isDebugBuild) { Debug.LogError("TextureMerge is null!"); } yield return(null); } for (int atlasIndex = umaData.generatedMaterials.materials.Count - 1; atlasIndex >= 0; atlasIndex--) { var atlas = umaData.generatedMaterials.materials[atlasIndex]; //Rendering Atlas int moduleCount = 0; //Process all necessary TextureModules for (int i = 0; i < atlas.materialFragments.Count; i++) { if (!atlas.materialFragments[i].isRectShared) { moduleCount++; moduleCount = moduleCount + atlas.materialFragments[i].overlays.Length; } } textureMerge.EnsureCapacity(moduleCount); var slotData = atlas.materialFragments[0].slotData; resultingTextures = new Texture[slotData.asset.material.channels.Length]; for (int textureType = slotData.asset.material.channels.Length - 1; textureType >= 0; textureType--) { switch (slotData.asset.material.channels[textureType].channelType) { case UMAMaterial.ChannelType.Texture: case UMAMaterial.ChannelType.DiffuseTexture: case UMAMaterial.ChannelType.NormalMap: case UMAMaterial.ChannelType.DetailNormalMap: { textureMerge.Reset(); for (int i = 0; i < atlas.materialFragments.Count; i++) { textureMerge.SetupModule(atlas, i, textureType); } //last element for this textureType moduleCount = 0; int width = Mathf.FloorToInt(atlas.cropResolution.x); int height = Mathf.FloorToInt(atlas.cropResolution.y); if (width == 0 || height == 0) { continue; } destinationTexture = new RenderTexture(Mathf.FloorToInt(atlas.cropResolution.x * umaData.atlasResolutionScale), Mathf.FloorToInt(atlas.cropResolution.y * umaData.atlasResolutionScale), 0, slotData.asset.material.channels[textureType].textureFormat, RenderTextureReadWrite.Linear); destinationTexture.filterMode = FilterMode.Point; destinationTexture.useMipMap = umaGenerator.convertMipMaps && !umaGenerator.convertRenderTexture; //Draw all the Rects here Color backgroundColor; UMAMaterial.ChannelType channelType = slotData.asset.material.channels[textureType].channelType; if (slotData.asset.material.MaskWithCurrentColor && (channelType == UMAMaterial.ChannelType.DiffuseTexture || channelType == UMAMaterial.ChannelType.Texture || channelType == UMAMaterial.ChannelType.TintedTexture)) { backgroundColor = slotData.asset.material.maskMultiplier * textureMerge.camBackgroundColor; } else { backgroundColor = UMAMaterial.GetBackgroundColor(slotData.asset.material.channels[textureType].channelType); } textureMerge.DrawAllRects(destinationTexture, width, height, backgroundColor); //PostProcess textureMerge.PostProcess(destinationTexture, slotData.asset.material.channels[textureType].channelType); int DownSample = slotData.asset.material.channels[textureType].DownSample; if (DownSample != 0) { int newW = width >> DownSample; int newH = height >> DownSample; RenderTexture rt = ResizeRenderTexture(destinationTexture, newW, newH, FilterMode.Bilinear); destinationTexture.Release(); destinationTexture = rt; } if (umaGenerator.convertRenderTexture || slotData.asset.material.channels[textureType].ConvertRenderTexture) { #region Convert Render Textures if (!fastPath) { yield return(25); } Texture2D tempTexture; tempTexture = new Texture2D(destinationTexture.width, destinationTexture.height, TextureFormat.ARGB32, umaGenerator.convertMipMaps, true); int xblocks = destinationTexture.width / 512; int yblocks = destinationTexture.height / 512; if (xblocks == 0 || yblocks == 0 || fastPath) { RenderTexture.active = destinationTexture; tempTexture.ReadPixels(new Rect(0, 0, destinationTexture.width, destinationTexture.height), 0, 0, umaGenerator.convertMipMaps); RenderTexture.active = null; } else { // figures that ReadPixels works differently on OpenGL and DirectX, someday this code will break because Unity fixes this bug! if (IsOpenGL()) { for (int x = 0; x < xblocks; x++) { for (int y = 0; y < yblocks; y++) { RenderTexture.active = destinationTexture; tempTexture.ReadPixels(new Rect(x * 512, y * 512, 512, 512), x * 512, y * 512, umaGenerator.convertMipMaps); RenderTexture.active = null; yield return(8); } } } else { for (int x = 0; x < xblocks; x++) { for (int y = 0; y < yblocks; y++) { RenderTexture.active = destinationTexture; tempTexture.ReadPixels(new Rect(x * 512, destinationTexture.height - 512 - y * 512, 512, 512), x * 512, y * 512, umaGenerator.convertMipMaps); RenderTexture.active = null; yield return(8); } } } } resultingTextures[textureType] = tempTexture as Texture; RenderTexture.active = null; destinationTexture.Release(); UnityEngine.GameObject.DestroyImmediate(destinationTexture); if (!fastPath) { yield return(6); } tempTexture = resultingTextures[textureType] as Texture2D; tempTexture.Apply(); tempTexture.wrapMode = TextureWrapMode.Repeat; tempTexture.anisoLevel = slotData.asset.material.AnisoLevel; tempTexture.mipMapBias = slotData.asset.material.MipMapBias; tempTexture.filterMode = slotData.asset.material.MatFilterMode; if (slotData.asset.material.channels[textureType].Compression != UMAMaterial.CompressionSettings.None) { tempTexture.Compress(slotData.asset.material.channels[textureType].Compression == UMAMaterial.CompressionSettings.HighQuality); } resultingTextures[textureType] = tempTexture; if (!slotData.asset.material.channels[textureType].NonShaderTexture) { atlas.material.SetTexture(slotData.asset.material.channels[textureType].materialPropertyName, tempTexture); } #endregion } else { destinationTexture.anisoLevel = slotData.asset.material.AnisoLevel; destinationTexture.mipMapBias = slotData.asset.material.MipMapBias; destinationTexture.filterMode = slotData.asset.material.MatFilterMode; destinationTexture.wrapMode = TextureWrapMode.Repeat; resultingTextures[textureType] = destinationTexture; if (!slotData.asset.material.channels[textureType].NonShaderTexture) { atlas.material.SetTexture(slotData.asset.material.channels[textureType].materialPropertyName, destinationTexture); } } break; } case UMAMaterial.ChannelType.MaterialColor: { if (slotData.asset.material.channels[textureType].NonShaderTexture) { break; } atlas.material.SetColor(slotData.asset.material.channels[textureType].materialPropertyName, atlas.materialFragments[0].baseColor); break; } case UMAMaterial.ChannelType.TintedTexture: { for (int i = 0; i < atlas.materialFragments.Count; i++) { var fragment = atlas.materialFragments[i]; if (fragment.isRectShared) { continue; } for (int j = 0; j < fragment.baseOverlay.textureList.Length; j++) { if (fragment.baseOverlay.textureList[j] != null) { if (!slotData.asset.material.channels[textureType].NonShaderTexture) { atlas.material.SetTexture(slotData.asset.material.channels[j].materialPropertyName, fragment.baseOverlay.textureList[j]); } if (j == 0) { atlas.material.color = fragment.baseColor; } } } foreach (var overlay in fragment.overlays) { for (int j = 0; j < overlay.textureList.Length; j++) { if (overlay.textureList[j] != null) { if (!slotData.asset.material.channels[textureType].NonShaderTexture) { atlas.material.SetTexture(slotData.asset.material.channels[j].materialPropertyName, overlay.textureList[j]); } } } } } break; } } } atlas.resultingAtlasList = resultingTextures; } }
/// <summary> /// Validate the OverlayData against the requirements of a particular UMAMaterial. /// </summary> /// <param name="targetMaterial">UMAMaterial to try and match.</param> /// <param name="isBaseOverlay">Is this the first overlay being applied?</param> internal bool Validate(UMAMaterial targetMaterial, bool isBaseOverlay) { bool valid = true; Validate(); if (asset.material == null) { #if UNITY_EDITOR Debug.LogError(string.Format("Overlay '{0}' doesn't have a UMA Material assigned. {1}", asset.overlayName, UnityEditor.AssetDatabase.GetAssetPath(asset))); #endif return(false); } if ((asset.material != null) && (asset.material.name != targetMaterial.name)) { if (asset.material != targetMaterial) { if (!asset.material.Equals(targetMaterial)) { #if UNITY_EDITOR Debug.LogError(string.Format("Overlay '{0}' doesn't have the expected UMA Material: '{1}'!\nCurrently it has '{2}' at '{3}'", asset.overlayName, targetMaterial.name, asset.material, UnityEditor.AssetDatabase.GetAssetPath(asset))); #endif valid = false; } } } if (isEmpty) { return(true); } if (asset.textureCount != targetMaterial.channels.Length) { if (Debug.isDebugBuild) { Debug.LogError(string.Format("Overlay '{0}' doesn't have the right number of channels", asset.overlayName)); } valid = false; } else { // HACK - Assume that procedural materials can always generate all channels if (this.isProcedural) { } // All channels must be initialized by the base overlay, only channel 0 in others else { for (int i = 0; i < targetMaterial.channels.Length; i++) { if ((asset.textureList[i] == null) && (targetMaterial.channels[i].channelType != UMAMaterial.ChannelType.MaterialColor)) { if (Debug.isDebugBuild) { Debug.LogError(string.Format("Overlay '{0}' missing required texture in channel {1}", asset.overlayName, i)); } valid = false; } if (!isBaseOverlay) { break; } } } } if (colorData.channelMask.Length < targetMaterial.channels.Length) { // Fixup colorData if moving from Legacy to PBR materials int oldsize = colorData.channelMask.Length; System.Array.Resize(ref colorData.channelMask, targetMaterial.channels.Length); System.Array.Resize(ref colorData.channelAdditiveMask, targetMaterial.channels.Length); for (int i = oldsize; i < targetMaterial.channels.Length; i++) { colorData.channelMask[i] = Color.white; colorData.channelAdditiveMask[i] = new Color32(0, 0, 0, 0); } } return(valid); }
public static SlotDataAsset CreateSlotData(string slotFolder, string assetFolder, string assetName, SkinnedMeshRenderer mesh, UMAMaterial material, SkinnedMeshRenderer prefabMesh) { if (!System.IO.Directory.Exists(slotFolder + '/' + assetFolder)) { System.IO.Directory.CreateDirectory(slotFolder + '/' + assetFolder); } if (!System.IO.Directory.Exists(slotFolder + '/' + assetName)) { System.IO.Directory.CreateDirectory(slotFolder + '/' + assetName); } GameObject tempGameObject = UnityEngine.Object.Instantiate(mesh.transform.parent.gameObject) as GameObject; PrefabUtility.DisconnectPrefabInstance(tempGameObject); var resultingSkinnedMeshes = tempGameObject.GetComponentsInChildren<SkinnedMeshRenderer>(); SkinnedMeshRenderer resultingSkinnedMesh = null; foreach (var skinnedMesh in resultingSkinnedMeshes) { if (skinnedMesh.name == mesh.name) { resultingSkinnedMesh = skinnedMesh; } } Mesh resultingMesh; if (prefabMesh != null) { resultingMesh = SeamRemoval.PerformSeamRemoval(resultingSkinnedMesh, prefabMesh, 0.0001f); resultingSkinnedMesh.sharedMesh = resultingMesh; SkinnedMeshAligner.AlignBindPose(prefabMesh, resultingSkinnedMesh); } else { resultingMesh = (Mesh)GameObject.Instantiate(resultingSkinnedMesh.sharedMesh); } var usedBonesDictionary = CompileUsedBonesDictionary(resultingMesh); if (usedBonesDictionary.Count != resultingSkinnedMesh.bones.Length) { resultingMesh = BuildNewReduceBonesMesh(resultingMesh, usedBonesDictionary); } AssetDatabase.CreateAsset(resultingMesh, slotFolder + '/' + assetName + '/' + mesh.name + ".asset"); tempGameObject.name = mesh.transform.parent.gameObject.name; Transform[] transformList = tempGameObject.GetComponentsInChildren<Transform>(); GameObject newObject = new GameObject(); for (int i = 0; i < transformList.Length; i++) { if (transformList[i].name == "Global") { transformList[i].parent = newObject.transform; } else if (transformList[i].name == mesh.name) { transformList[i].parent = newObject.transform; } } GameObject.DestroyImmediate(tempGameObject); resultingSkinnedMesh = newObject.GetComponentInChildren<SkinnedMeshRenderer>(); if (resultingSkinnedMesh) { if (usedBonesDictionary.Count != resultingSkinnedMesh.bones.Length) { resultingSkinnedMesh.bones = BuildNewReducedBonesList(resultingSkinnedMesh.bones, usedBonesDictionary); } resultingSkinnedMesh.sharedMesh = resultingMesh; } var skinnedResult = UnityEditor.PrefabUtility.CreatePrefab(slotFolder + '/' + assetName + '/' + assetName + "_Skinned.prefab", newObject); GameObject.DestroyImmediate(newObject); var meshgo = skinnedResult.transform.Find(mesh.name); var finalMeshRenderer = meshgo.GetComponent<SkinnedMeshRenderer>(); var slot = ScriptableObject.CreateInstance<SlotDataAsset>(); slot.slotName = assetName; slot.material = material; slot.UpdateMeshData(finalMeshRenderer); AssetDatabase.CreateAsset(slot, slotFolder + '/' + assetName + '/' + assetName + "_Slot.asset"); AssetDatabase.SaveAssets(); return slot; }
/// <summary> /// Setup data for atlas building. /// </summary> /// <param name="_umaData">UMA data.</param> /// <param name="_umaGenerator">UMA generator.</param> public void ProcessTexture(UMAData _umaData, UMAGeneratorBase _umaGenerator) { umaData = _umaData; umaGenerator = _umaGenerator; if (umaGenerator is UMAGenerator) { fastPath = (umaGenerator as UMAGenerator).fastGeneration; } if (umaData.atlasResolutionScale <= 0) umaData.atlasResolutionScale = 1f; var textureMerge = umaGenerator.textureMerge; textureMerge.RefreshMaterials(); if (textureMerge == null) { if (Debug.isDebugBuild) Debug.LogError("TextureMerge is null!"); // yield return null; } try { for (int atlasIndex = umaData.generatedMaterials.materials.Count - 1; atlasIndex >= 0; atlasIndex--) { var generatedMaterial = umaData.generatedMaterials.materials[atlasIndex]; //Rendering Atlas int moduleCount = 0; //Process all necessary TextureModules for (int i = 0; i < generatedMaterial.materialFragments.Count; i++) { if (!generatedMaterial.materialFragments[i].isRectShared && !generatedMaterial.materialFragments[i].isNoTextures) { moduleCount++; moduleCount = moduleCount + generatedMaterial.materialFragments[i].overlays.Length; } } textureMerge.EnsureCapacity(moduleCount); var slotData = generatedMaterial.materialFragments[0].slotData; resultingTextures = new Texture[slotData.material.channels.Length]; for (int textureType = slotData.material.channels.Length - 1; textureType >= 0; textureType--) { switch (slotData.material.channels[textureType].channelType) { case UMAMaterial.ChannelType.Texture: case UMAMaterial.ChannelType.DiffuseTexture: case UMAMaterial.ChannelType.NormalMap: case UMAMaterial.ChannelType.DetailNormalMap: { bool CopyRTtoTex = SupportsRTToTexture2D && fastPath; textureMerge.Reset(); for (int i = 0; i < generatedMaterial.materialFragments.Count; i++) { textureMerge.SetupModule(generatedMaterial, i, textureType); } //last element for this textureType moduleCount = 0; int width = Mathf.FloorToInt(generatedMaterial.cropResolution.x); int height = Mathf.FloorToInt(generatedMaterial.cropResolution.y); if (width == 0 || height == 0) { continue; } //this should be restricted to >= 1 but 0 was allowed before and projects may have the umaMaterial value serialized to 0. float downSample = (slotData.material.channels[textureType].DownSample == 0) ? 1f : (1f / slotData.material.channels[textureType].DownSample); destinationTexture = new RenderTexture(Mathf.FloorToInt(generatedMaterial.cropResolution.x * umaData.atlasResolutionScale * downSample), Mathf.FloorToInt(generatedMaterial.cropResolution.y * umaData.atlasResolutionScale * downSample), 0, slotData.material.channels[textureType].textureFormat, RenderTextureReadWrite.Linear); destinationTexture.filterMode = FilterMode.Point; destinationTexture.useMipMap = umaGenerator.convertMipMaps && CopyRTtoTex;// && !umaGenerator.convertRenderTexture; destinationTexture.name = slotData.material.name + " Chan " + textureType + " frame: " + Time.frameCount; //Draw all the Rects here Color backgroundColor; UMAMaterial.ChannelType channelType = slotData.material.channels[textureType].channelType; if (slotData.material.MaskWithCurrentColor && (channelType == UMAMaterial.ChannelType.DiffuseTexture || channelType == UMAMaterial.ChannelType.Texture || channelType == UMAMaterial.ChannelType.TintedTexture)) { backgroundColor = slotData.material.maskMultiplier * textureMerge.camBackgroundColor; } else { backgroundColor = UMAMaterial.GetBackgroundColor(slotData.material.channels[textureType].channelType); } textureMerge.DrawAllRects(destinationTexture, width, height, backgroundColor, umaGenerator.SharperFitTextures); //PostProcess textureMerge.PostProcess(destinationTexture, slotData.material.channels[textureType].channelType); if (umaGenerator.convertRenderTexture || slotData.material.channels[textureType].ConvertRenderTexture) { #region Convert Render Textures if(CopyRTtoTex) { // copy the texture with mips to the Texture2D Texture2D tempTexture; tempTexture = new Texture2D(destinationTexture.width, destinationTexture.height, TextureFormat.ARGB32, umaGenerator.convertMipMaps, true); Graphics.CopyTexture(destinationTexture, tempTexture); destinationTexture.Release(); UnityEngine.GameObject.DestroyImmediate(destinationTexture); tempTexture.wrapMode = TextureWrapMode.Repeat; tempTexture.anisoLevel = slotData.material.AnisoLevel; tempTexture.mipMapBias = slotData.material.MipMapBias; tempTexture.filterMode = slotData.material.MatFilterMode; resultingTextures[textureType] = tempTexture as Texture; if(!slotData.material.channels[textureType].NonShaderTexture) { if (generatedMaterial.umaMaterial.translateSRP) { generatedMaterial.material.SetTexture(UMAUtils.TranslatedSRPTextureName(slotData.material.channels[textureType].materialPropertyName), tempTexture); } else { generatedMaterial.material.SetTexture(slotData.material.channels[textureType].materialPropertyName, tempTexture); } } } else { #if USE_ASYNC_GPU_READBACK // Todo: use AsyncGPUReadback to get the texture if possible. // // material == generatedMaterial.material // umaData == ; // slotData == ; // propname == slotData.material.channels[textureType].materialPropertyName // mipcount // mipsconverted[] // Data. //for (int i=0;i< destinationTexture.mipmapCount;i++) //{ // //} #else Texture2D tempTexture; tempTexture = new Texture2D(destinationTexture.width, destinationTexture.height, TextureFormat.ARGB32, umaGenerator.convertMipMaps, true); RenderTexture.active = destinationTexture; tempTexture.ReadPixels(new Rect(0, 0, destinationTexture.width, destinationTexture.height), 0, 0, umaGenerator.convertMipMaps); //resultingTextures[textureType] = tempTexture as Texture; RenderTexture.active = null; destinationTexture.Release(); UnityEngine.GameObject.DestroyImmediate(destinationTexture); // if (!fastPath) yield return 6; //tempTexture = resultingTextures[textureType] as Texture2D; tempTexture.Apply(); tempTexture.wrapMode = TextureWrapMode.Repeat; tempTexture.anisoLevel = slotData.material.AnisoLevel; tempTexture.mipMapBias = slotData.material.MipMapBias; tempTexture.filterMode = slotData.material.MatFilterMode; //if (slotData.asset.material.channels[textureType].Compression != UMAMaterial.CompressionSettings.None) //{ // tempTexture.Compress(slotData.asset.material.channels[textureType].Compression == UMAMaterial.CompressionSettings.HighQuality); // } resultingTextures[textureType] = tempTexture; if(!slotData.material.channels[textureType].NonShaderTexture) { if (generatedMaterial.umaMaterial.translateSRP) { generatedMaterial.material.SetTexture(UMAUtils.TranslatedSRPTextureName(slotData.material.channels[textureType].materialPropertyName), tempTexture); } else { generatedMaterial.material.SetTexture(slotData.material.channels[textureType].materialPropertyName, tempTexture); } generatedMaterial.material.SetTexture(UMAUtils.TranslatedSRPTextureName(slotData.material.channels[textureType].materialPropertyName), tempTexture); } } #endif #endregion } else { destinationTexture.anisoLevel = slotData.material.AnisoLevel; destinationTexture.mipMapBias = slotData.material.MipMapBias; destinationTexture.filterMode = slotData.material.MatFilterMode; destinationTexture.wrapMode = TextureWrapMode.Repeat; resultingTextures[textureType] = destinationTexture; if (!slotData.material.channels[textureType].NonShaderTexture) { if (generatedMaterial.umaMaterial.translateSRP) { generatedMaterial.material.SetTexture(UMAUtils.TranslatedSRPTextureName(slotData.material.channels[textureType].materialPropertyName), destinationTexture); } else { generatedMaterial.material.SetTexture(slotData.material.channels[textureType].materialPropertyName, destinationTexture); } } } break; } case UMAMaterial.ChannelType.MaterialColor: { if (slotData.material.channels[textureType].NonShaderTexture) break; generatedMaterial.material.SetColor(slotData.material.channels[textureType].materialPropertyName, generatedMaterial.materialFragments[0].baseColor); break; } case UMAMaterial.ChannelType.TintedTexture: { for (int i = 0; i < generatedMaterial.materialFragments.Count; i++) { var fragment = generatedMaterial.materialFragments[i]; if (fragment.isRectShared) continue; for (int j = 0; j < fragment.baseOverlay.textureList.Length; j++) { if (fragment.baseOverlay.textureList[j] != null) { if (!slotData.material.channels[textureType].NonShaderTexture) { if (generatedMaterial.umaMaterial.translateSRP) { generatedMaterial.material.SetTexture(UMAUtils.TranslatedSRPTextureName(slotData.material.channels[j].materialPropertyName), fragment.baseOverlay.textureList[j]); } else { generatedMaterial.material.SetTexture(slotData.material.channels[j].materialPropertyName, fragment.baseOverlay.textureList[j]); } } if (j == 0) { generatedMaterial.material.color = fragment.baseColor; } } } foreach (var overlay in fragment.overlays) { if (generatedMaterial.textureNameList == null) for (int j = 0; j < overlay.textureList.Length; j++) { if (overlay.textureList[j] != null) { if (!slotData.material.channels[textureType].NonShaderTexture) { if (generatedMaterial.umaMaterial.translateSRP) { generatedMaterial.material.SetTexture(UMAUtils.TranslatedSRPTextureName(slotData.material.channels[j].materialPropertyName), overlay.textureList[j]); } else { generatedMaterial.material.SetTexture(slotData.material.channels[j].materialPropertyName, overlay.textureList[j]); } } } } } } break; } } } generatedMaterial.resultingAtlasList = resultingTextures; } } finally { RenderTexture.active = null; } }