using UnityEngine; using System.Linq; using System.Collections.Generic; using System.Collections; using System.IO; using System; using DepthFirstScheduler; #if UNITY_EDITOR using UnityEditor; #endif namespace UniGLTF { public class TextureItem { private int m_textureIndex; public Texture2D Texture { get { return m_textureLoader.Texture; } } #region Texture converter private Dictionary m_converts = new Dictionary(); public Dictionary Converts { get { return m_converts; } } public Texture2D ConvertTexture(string prop) { var convertedTexture = Converts.FirstOrDefault(x => x.Key == prop); if (convertedTexture.Value != null) return convertedTexture.Value; if (prop == "_BumpMap") { if (Application.isPlaying) { var converted = new NormalConverter().GetImportTexture(Texture); m_converts.Add(prop, converted); return converted; } else { #if UNITY_EDITOR var textureAssetPath = AssetDatabase.GetAssetPath(Texture); if (!string.IsNullOrEmpty(textureAssetPath)) { TextureIO.MarkTextureAssetAsNormalMap(textureAssetPath); } else { Debug.LogWarningFormat("no asset for {0}", Texture); } #endif return Texture; } } if (prop == "_MetallicGlossMap") { var converted = new MetallicRoughnessConverter().GetImportTexture(Texture); m_converts.Add(prop, converted); return converted; } if (prop == "_OcclusionMap") { var converted = new OcclusionConverter().GetImportTexture(Texture); m_converts.Add(prop, converted); return converted; } return null; } #endregion public bool IsAsset { private set; get; } public IEnumerable GetTexturesForSaveAssets() { if (!IsAsset) { yield return Texture; } if (m_converts.Any()) { foreach (var texture in m_converts) { yield return texture.Value; } } } /// /// Texture from buffer /// /// public TextureItem(int index) { m_textureIndex = index; #if UNIGLTF_USE_WEBREQUEST_TEXTURELOADER m_textureLoader = new UnityWebRequestTextureLoader(m_textureIndex); #else m_textureLoader = new TextureLoader(m_textureIndex); #endif } #if UNITY_EDITOR /// /// Texture from asset /// /// /// /// public TextureItem(int index, UnityPath assetPath, string textureName) { m_textureIndex = index; IsAsset = true; m_textureLoader = new AssetTextureLoader(assetPath, textureName); } #endif #region Process ITextureLoader m_textureLoader; public void Process(glTF gltf, IStorage storage) { ProcessOnAnyThread(gltf, storage); ProcessOnMainThreadCoroutine(gltf).CoroutinetoEnd(); } public IEnumerator ProcessCoroutine(glTF gltf, IStorage storage) { ProcessOnAnyThread(gltf, storage); yield return ProcessOnMainThreadCoroutine(gltf); } public void ProcessOnAnyThread(glTF gltf, IStorage storage) { m_textureLoader.ProcessOnAnyThread(gltf, storage); } public IEnumerator ProcessOnMainThreadCoroutine(glTF gltf) { using (m_textureLoader) { var textureType = TextureIO.GetglTFTextureType(gltf, m_textureIndex); var colorSpace = TextureIO.GetColorSpace(textureType); var isLinear = colorSpace == RenderTextureReadWrite.Linear; yield return m_textureLoader.ProcessOnMainThread(isLinear); TextureSamplerUtil.SetSampler(Texture, gltf.GetSamplerFromTextureIndex(m_textureIndex)); } } #endregion struct ColorSpaceScope : IDisposable { bool m_sRGBWrite; public ColorSpaceScope(RenderTextureReadWrite colorSpace) { m_sRGBWrite = GL.sRGBWrite; switch (colorSpace) { case RenderTextureReadWrite.Linear: GL.sRGBWrite = false; break; case RenderTextureReadWrite.sRGB: default: GL.sRGBWrite = true; break; } } public ColorSpaceScope(bool sRGBWrite) { m_sRGBWrite = GL.sRGBWrite; GL.sRGBWrite = sRGBWrite; } public void Dispose() { GL.sRGBWrite = m_sRGBWrite; } } #if UNITY_EDITOR && VRM_DEVELOP [MenuItem("Assets/CopySRGBWrite", true)] static bool CopySRGBWriteIsEnable() { return Selection.activeObject is Texture; } [MenuItem("Assets/CopySRGBWrite")] static void CopySRGBWrite() { CopySRGBWrite(true); } [MenuItem("Assets/CopyNotSRGBWrite", true)] static bool CopyNotSRGBWriteIsEnable() { return Selection.activeObject is Texture; } [MenuItem("Assets/CopyNotSRGBWrite")] static void CopyNotSRGBWrite() { CopySRGBWrite(false); } static string AddPath(string path, string add) { return string.Format("{0}/{1}{2}{3}", Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path), add, Path.GetExtension(path)); } static void CopySRGBWrite(bool isSRGB) { var src = Selection.activeObject as Texture; var texturePath = UnityPath.FromAsset(src); var path = EditorUtility.SaveFilePanel("save prefab", "Assets", Path.GetFileNameWithoutExtension(AddPath(texturePath.FullPath, ".sRGB")), "prefab"); var assetPath = UnityPath.FromFullpath(path); if (!assetPath.IsUnderAssetsFolder) { return; } Debug.LogFormat("[CopySRGBWrite] {0} => {1}", texturePath, assetPath); var renderTexture = new RenderTexture(src.width, src.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB); using (var scope = new ColorSpaceScope(isSRGB)) { Graphics.Blit(src, renderTexture); } var dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, RenderTextureReadWrite.sRGB == RenderTextureReadWrite.Linear); dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0); dst.Apply(); RenderTexture.active = null; assetPath.CreateAsset(dst); GameObject.DestroyImmediate(renderTexture); } #endif public static Texture2D CopyTexture(Texture src, RenderTextureReadWrite colorSpace, Material material) { Texture2D dst = null; var renderTexture = new RenderTexture(src.width, src.height, 0, RenderTextureFormat.ARGB32, colorSpace); using (var scope = new ColorSpaceScope(colorSpace)) { if (material != null) { Graphics.Blit(src, renderTexture, material); } else { Graphics.Blit(src, renderTexture); } } dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, colorSpace == RenderTextureReadWrite.Linear); dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0); dst.name = src.name; dst.Apply(); RenderTexture.active = null; if (Application.isEditor) { GameObject.DestroyImmediate(renderTexture); } else { GameObject.Destroy(renderTexture); } return dst; } } }