225 lines
7.2 KiB
C#
225 lines
7.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using JetBrains.Annotations;
|
|
using Needle.Engine.Gltf.Experimental;
|
|
using Needle.Engine.Gltf.Experimental.progressive;
|
|
using Needle.Engine.Utils;
|
|
using UnityEngine;
|
|
using UnityGLTF;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace Needle.Engine.Gltf
|
|
{
|
|
[UsedImplicitly]
|
|
public class TextureCompressionHandler : GltfExtensionHandlerBase, ITextureExportHandler
|
|
{
|
|
private static NeedleCompressionSettings defaultCompressionSettings;
|
|
|
|
public override void OnBeforeExport(GltfExportContext context)
|
|
{
|
|
base.OnBeforeExport(context);
|
|
TextureExportHandlerRegistry.Register(this);
|
|
if (!defaultCompressionSettings)
|
|
defaultCompressionSettings = Object.FindAnyObjectByType<NeedleCompressionSettings>();
|
|
}
|
|
|
|
public bool OnTextureExport(GltfExportContext context,
|
|
ref TextureExportSettings textureSettings,
|
|
string textureSlot,
|
|
List<object> extensions)
|
|
{
|
|
var texture = textureSettings.Texture;
|
|
|
|
if (!texture)
|
|
{
|
|
return false;
|
|
}
|
|
if (texture is RenderTexture rt)
|
|
{
|
|
extensions.Add(new NEEDLE_progressive_texture_settings(rt.GetId(), -1, false));
|
|
return true;
|
|
}
|
|
if (texture.IsHDR())
|
|
{
|
|
return false;
|
|
}
|
|
var lm = LightmapSettings.lightmaps;
|
|
foreach (var lightmap in lm)
|
|
{
|
|
if (texture == lightmap.lightmapColor)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// First check if we have a use progressive textures component on the exported asset
|
|
var compressionSettings = defaultCompressionSettings;
|
|
if (context.Root.TryGetComponent(out NeedleCompressionSettings rootSettings))
|
|
{
|
|
compressionSettings = rootSettings;
|
|
}
|
|
|
|
|
|
// Set the texture max size for UnityGltf
|
|
if (compressionSettings)
|
|
textureSettings.MaxSize = Mathf.Min(textureSettings.MaxSize, compressionSettings.TextureMaxSize);
|
|
|
|
|
|
var ext = CreateCompressionSettings(context, compressionSettings, ref textureSettings, textureSlot);
|
|
if (ext != null) extensions.Add(ext);
|
|
|
|
if (texture is Texture2D tex2d && compressionSettings != null)
|
|
{
|
|
// Texture LODs are disabled:
|
|
if (compressionSettings.GenerateTextureLODs == false)
|
|
{
|
|
// Workaround to disable progressive textures: setting an invalid max size to -1
|
|
extensions.Add(new NEEDLE_progressive_texture_settings(tex2d.GetId(), -1, false));
|
|
}
|
|
else
|
|
{
|
|
// We only need to load it progressively if the texture is larger than the max size
|
|
if (compressionSettings.LODsMaxSize < Mathf.Max(tex2d.width, tex2d.height))
|
|
{
|
|
extensions.Add(new NEEDLE_progressive_texture_settings(tex2d.GetId(),
|
|
compressionSettings.LODsMaxSize));
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
private static NEEDLE_compression_texture CreateCompressionSettings(IExportContext context,
|
|
NeedleCompressionSettings compressionSettings,
|
|
ref TextureExportSettings exportSettings,
|
|
string textureSlot)
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (compressionSettings && compressionSettings.DefaultTextureFormat == TextureCompressionMode.None)
|
|
{
|
|
return new NEEDLE_compression_texture(TextureCompressionMode.None.Serialize(), textureSlot);
|
|
}
|
|
|
|
#if !UNITY_6000_0_OR_NEWER
|
|
// Get importer settings. This feature is discontinued in Unity 6
|
|
if (NeedleAssetSettingsProvider.TryGetTextureSettings(exportSettings.Texture, out var needleSettings) &&
|
|
needleSettings.Override)
|
|
{
|
|
var compressionMode = needleSettings.CompressionMode.Serialize();
|
|
|
|
switch (needleSettings.CompressionMode)
|
|
{
|
|
case TextureCompressionMode.Automatic:
|
|
case TextureCompressionMode.Product:
|
|
case TextureCompressionMode.World:
|
|
compressionMode = GetCompressionModeFromSlot(compressionSettings, exportSettings, textureSlot);
|
|
break;
|
|
}
|
|
|
|
if (compressionMode != null)
|
|
{
|
|
var quality = needleSettings.CompressionQualitySupported
|
|
? (needleSettings.CompressionQuality / 100f)
|
|
: -1;
|
|
var settings = new NEEDLE_compression_texture(compressionMode, textureSlot, quality);
|
|
settings.maxSize = needleSettings.MaxSize;
|
|
exportSettings.MaxSize = needleSettings.MaxSize;
|
|
return settings;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
var texturePath = UnityEditor.AssetDatabase.GetAssetPath(exportSettings.Texture);
|
|
if (!string.IsNullOrEmpty(texturePath))
|
|
{
|
|
// check asset tags
|
|
var tags = UnityEditor.AssetDatabase.GetLabels(exportSettings.Texture);
|
|
if (TryGetCompressionModeFromAssetLabels(tags, out var mode))
|
|
return new NEEDLE_compression_texture(mode, textureSlot);
|
|
|
|
if (UnityEditor.EditorUtility.IsPersistent(context.Root))
|
|
{
|
|
var rootTags = UnityEditor.AssetDatabase.GetLabels(context.Root);
|
|
if (TryGetCompressionModeFromAssetLabels(rootTags, out mode))
|
|
return new NEEDLE_compression_texture(mode, textureSlot);
|
|
}
|
|
|
|
// Export sprite textures using UASTC
|
|
var importer = UnityEditor.AssetImporter.GetAtPath(texturePath) as UnityEditor.TextureImporter;
|
|
if (importer && importer.textureType == UnityEditor.TextureImporterType.Sprite)
|
|
{
|
|
return new NEEDLE_compression_texture(TextureCompressionMode.UASTC.Serialize(), textureSlot);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Auto: we don't insert any extension into the texture here because this should be all determined by the build pipeline
|
|
// We don't want multiple tools having an opinion here
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
private static bool TryGetCompressionModeFromAssetLabels(string[] labels, out string mode)
|
|
{
|
|
if (labels != null)
|
|
{
|
|
foreach (var tag in labels)
|
|
{
|
|
if (tag.Equals(TextureCompressionMode.UASTC.Serialize(), StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
mode = TextureCompressionMode.UASTC.Serialize();
|
|
return true;
|
|
}
|
|
if (tag.Equals(TextureCompressionMode.ETC1S.Serialize(), StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
mode = TextureCompressionMode.ETC1S.Serialize();
|
|
return true;
|
|
}
|
|
if (tag.Equals(TextureCompressionMode.WebP.Serialize(), StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
mode = TextureCompressionMode.WebP.Serialize();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
mode = null;
|
|
return false;
|
|
}
|
|
|
|
private static string GetCompressionModeFromSlot(NeedleCompressionSettings settings,
|
|
TextureExportSettings textureExportSettings,
|
|
string textureSlot)
|
|
{
|
|
switch (textureSlot)
|
|
{
|
|
case GLTFSceneExporter.TextureMapType.BaseColor:
|
|
case GLTFSceneExporter.TextureMapType.Emissive:
|
|
case GLTFSceneExporter.TextureMapType.Occlusion:
|
|
case GLTFSceneExporter.TextureMapType.sRGB:
|
|
return TextureCompressionMode.ETC1S.Serialize();
|
|
|
|
case GLTFSceneExporter.TextureMapType.Normal:
|
|
case GLTFSceneExporter.TextureMapType.MetallicRoughness:
|
|
case GLTFSceneExporter.TextureMapType.Linear:
|
|
if (settings && settings.DefaultTextureFormat == TextureCompressionMode.Product)
|
|
return TextureCompressionMode.WebP.Serialize();
|
|
return TextureCompressionMode.UASTC.Serialize();
|
|
}
|
|
|
|
// if we haven't catched the right slot above, we differentiate by linear setting
|
|
if (textureExportSettings.Linear)
|
|
{
|
|
if (settings && settings.DefaultTextureFormat == TextureCompressionMode.Product)
|
|
return TextureCompressionMode.WebP.Serialize();
|
|
return TextureCompressionMode.UASTC.Serialize();
|
|
}
|
|
|
|
return TextureCompressionMode.ETC1S.Serialize();
|
|
}
|
|
}
|
|
} |