Skip to content

Commit

Permalink
for editor import: convert normal maps to dxt5nm when its enabled in …
Browse files Browse the repository at this point in the history
…project settings
  • Loading branch information
pfcDorn committed Jan 12, 2024
1 parent c9e4592 commit dae24c7
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 26 deletions.
42 changes: 25 additions & 17 deletions Runtime/Scripts/SceneImporter/ImporterMaterials.cs
Expand Up @@ -11,6 +11,8 @@ namespace UnityGLTF
{
public partial class GLTFSceneImporter
{
internal static List<Texture> _runtimeNormalTextures = new List<Texture>();

protected virtual async Task ConstructMaterial(GLTFMaterial def, int materialIndex)
{
IUniformMap mapper;
Expand Down Expand Up @@ -116,7 +118,7 @@ void SetTransformKeyword()
if (pbr.BaseColorTexture != null)
{
TextureId textureId = pbr.BaseColorTexture.Index;
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false);
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false, false);
mrMapper.BaseColorTexture = _assetCache.TextureCache[textureId.Id].Texture;
mrMapper.BaseColorTexCoord = pbr.BaseColorTexture.TexCoord;

Expand Down Expand Up @@ -145,7 +147,7 @@ void SetTransformKeyword()
if (pbr.MetallicRoughnessTexture != null)
{
TextureId textureId = pbr.MetallicRoughnessTexture.Index;
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, true);
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, true, false);
mrMapper.MetallicRoughnessTexture = _assetCache.TextureCache[textureId.Id].Texture;
mrMapper.MetallicRoughnessTexCoord = pbr.MetallicRoughnessTexture.TexCoord;

Expand Down Expand Up @@ -197,7 +199,7 @@ void SetTransformKeyword()
if (specGloss.DiffuseTexture != null)
{
TextureId textureId = specGloss.DiffuseTexture.Index;
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false);
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false, false);
sgMapper.DiffuseTexture = _assetCache.TextureCache[textureId.Id].Texture;
sgMapper.DiffuseTexCoord = specGloss.DiffuseTexture.TexCoord;

Expand Down Expand Up @@ -226,7 +228,7 @@ void SetTransformKeyword()
if (specGloss.SpecularGlossinessTexture != null)
{
TextureId textureId = specGloss.SpecularGlossinessTexture.Index;
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false);
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false, false);
sgMapper.SpecularGlossinessTexture = _assetCache.TextureCache[textureId.Id].Texture;
sgMapper.SpecularGlossinessTexCoord = specGloss.SpecularGlossinessTexture.TexCoord;

Expand Down Expand Up @@ -258,7 +260,7 @@ void SetTransformKeyword()
if (pbr.BaseColorTexture != null)
{
TextureId textureId = pbr.BaseColorTexture.Index;
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false);
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false, false);
unlitMapper.BaseColorTexture = _assetCache.TextureCache[textureId.Id].Texture;
unlitMapper.BaseColorTexCoord = pbr.BaseColorTexture.TexCoord;

Expand Down Expand Up @@ -301,7 +303,7 @@ void SetTransformKeyword()

if (transmission.transmissionTexture != null)
{
var td = await FromTextureInfo(transmission.transmissionTexture);
var td = await FromTextureInfo(transmission.transmissionTexture, false);
transmissionMapper.TransmissionTexture = td.Texture;
transmissionMapper.TransmissionTextureTexCoord = td.TexCoord;
var ext = GetTextureTransform(transmission.transmissionTexture);
Expand Down Expand Up @@ -339,7 +341,7 @@ void SetTransformKeyword()
volumeMapper.ThicknessFactor = volume.thicknessFactor;
if (volume.thicknessTexture != null)
{
var td = await FromTextureInfo(volume.thicknessTexture);
var td = await FromTextureInfo(volume.thicknessTexture, false);
volumeMapper.ThicknessTexture = td.Texture;
volumeMapper.ThicknessTextureTexCoord = td.TexCoord;
var ext = GetTextureTransform(volume.thicknessTexture);
Expand Down Expand Up @@ -377,7 +379,7 @@ void SetTransformKeyword()
iridescenceMapper.IridescenceThicknessMaximum = iridescence.iridescenceThicknessMaximum;
if (iridescence.iridescenceTexture != null)
{
var td = await FromTextureInfo(iridescence.iridescenceTexture);
var td = await FromTextureInfo(iridescence.iridescenceTexture, false);
iridescenceMapper.IridescenceTexture = td.Texture;
iridescenceMapper.IridescenceTextureTexCoord = td.TexCoord;
var ext = GetTextureTransform(iridescence.iridescenceTexture);
Expand All @@ -400,7 +402,7 @@ void SetTransformKeyword()

if (iridescence.iridescenceThicknessTexture != null)
{
var td2 = await FromTextureInfo(iridescence.iridescenceThicknessTexture);
var td2 = await FromTextureInfo(iridescence.iridescenceThicknessTexture, false);
iridescenceMapper.IridescenceThicknessTexture = td2.Texture;
iridescenceMapper.IridescenceThicknessTextureTexCoord = td2.TexCoord;
var ext2 = GetTextureTransform(iridescence.iridescenceThicknessTexture);
Expand Down Expand Up @@ -436,7 +438,7 @@ void SetTransformKeyword()
specularMapper.SpecularColorFactor = specular.specularColorFactor.ToUnityColorLinear();
if (specular.specularTexture != null)
{
var td = await FromTextureInfo(specular.specularTexture);
var td = await FromTextureInfo(specular.specularTexture, false);
specularMapper.SpecularTexture = td.Texture;
specularMapper.SpecularTextureTexCoord = td.TexCoord;
var ext = GetTextureTransform(specular.specularTexture);
Expand All @@ -460,7 +462,7 @@ void SetTransformKeyword()

if (specular.specularColorTexture != null)
{
var td2 = await FromTextureInfo(specular.specularColorTexture);
var td2 = await FromTextureInfo(specular.specularColorTexture, false);
specularMapper.SpecularColorTexture = td2.Texture;
specularMapper.SpecularColorTextureTexCoord = td2.TexCoord;
var ext2 = GetTextureTransform(specular.specularColorTexture);
Expand Down Expand Up @@ -496,7 +498,7 @@ void SetTransformKeyword()
clearcoatMapper.ClearcoatRoughnessFactor = clearcoat.clearcoatRoughnessFactor;
if (clearcoat.clearcoatTexture != null)
{
var td = await FromTextureInfo(clearcoat.clearcoatTexture);
var td = await FromTextureInfo(clearcoat.clearcoatTexture, false);
clearcoatMapper.ClearcoatTexture = td.Texture;
clearcoatMapper.ClearcoatTextureTexCoord = td.TexCoord;
var ext = GetTextureTransform(clearcoat.clearcoatTexture);
Expand All @@ -520,7 +522,7 @@ void SetTransformKeyword()

if (clearcoat.clearcoatRoughnessTexture != null)
{
var td = await FromTextureInfo(clearcoat.clearcoatRoughnessTexture);
var td = await FromTextureInfo(clearcoat.clearcoatRoughnessTexture, false);
clearcoatMapper.ClearcoatRoughnessTexture = td.Texture;
clearcoatMapper.ClearcoatRoughnessTextureTexCoord = td.TexCoord;
var ext = GetTextureTransform(clearcoat.clearcoatRoughnessTexture);
Expand Down Expand Up @@ -548,7 +550,10 @@ void SetTransformKeyword()
{
if (clearcoat.clearcoatNormalTexture != null)
{
var td = await FromTextureInfo(clearcoat.clearcoatNormalTexture);
var td = await FromTextureInfo(clearcoat.clearcoatNormalTexture, false);

_runtimeNormalTextures.Add(td.Texture);

clearcoatNormalMapper.ClearcoatNormalTexture = td.Texture;
clearcoatNormalMapper.ClearcoatNormalTextureTexCoord = td.TexCoord;
var ext = GetTextureTransform(clearcoat.clearcoatNormalTexture);
Expand Down Expand Up @@ -581,11 +586,14 @@ void SetTransformKeyword()
if (def.NormalTexture != null)
{
TextureId textureId = def.NormalTexture.Index;
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, true);
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, true, true);

uniformMapper.NormalTexture = _assetCache.TextureCache[textureId.Id].Texture;
uniformMapper.NormalTexCoord = def.NormalTexture.TexCoord;
uniformMapper.NormalTexScale = def.NormalTexture.Scale;

_runtimeNormalTextures.Add(uniformMapper.NormalTexture);

var ext = GetTextureTransform(def.NormalTexture);
if (ext != null)
{
Expand All @@ -607,7 +615,7 @@ void SetTransformKeyword()
if (def.EmissiveTexture != null)
{
TextureId textureId = def.EmissiveTexture.Index;
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false);
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, false, false);
uniformMapper.EmissiveTexture = _assetCache.TextureCache[textureId.Id].Texture;
uniformMapper.EmissiveTexCoord = def.EmissiveTexture.TexCoord;

Expand All @@ -633,7 +641,7 @@ void SetTransformKeyword()
{
uniformMapper.OcclusionTexStrength = def.OcclusionTexture.Strength;
TextureId textureId = def.OcclusionTexture.Index;
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, true);
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, true, false);
uniformMapper.OcclusionTexture = _assetCache.TextureCache[textureId.Id].Texture;
uniformMapper.OcclusionTexCoord = def.OcclusionTexture.TexCoord;

Expand Down
35 changes: 26 additions & 9 deletions Runtime/Scripts/SceneImporter/ImporterTextures.cs
Expand Up @@ -36,17 +36,17 @@ private async Task CreateNotReferencedTexture(int index)
&& string.IsNullOrEmpty(Root.Textures[index].Source.Value.Uri))
{
await ConstructImageBuffer(Root.Textures[index], index);
await ConstructTexture(Root.Textures[index], index, !KeepCPUCopyOfTexture, true);
await ConstructTexture(Root.Textures[index], index, !KeepCPUCopyOfTexture, true, false);
}
}

private async Task<TextureData> FromTextureInfo(TextureInfo textureInfo)
private async Task<TextureData> FromTextureInfo(TextureInfo textureInfo, bool isNormal)
{
var result = new TextureData();
if (textureInfo?.Index?.Value == null) return result;

TextureId textureId = textureInfo.Index;
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, true);
await ConstructTexture(textureId.Value, textureId.Id, !KeepCPUCopyOfTexture, true, isNormal);
result.Texture = _assetCache.TextureCache[textureId.Id].Texture;
result.TexCoord = textureInfo.TexCoord;

Expand All @@ -67,7 +67,7 @@ private async Task<TextureData> FromTextureInfo(TextureInfo textureInfo)
return result;
}

protected async Task ConstructImage(GLTFImage image, int imageCacheIndex, bool markGpuOnly, bool isLinear)
protected async Task ConstructImage(GLTFImage image, int imageCacheIndex, bool markGpuOnly, bool isLinear, bool isNormal)
{
if (_assetCache.InvalidImageCache[imageCacheIndex])
return;
Expand Down Expand Up @@ -101,7 +101,7 @@ protected async Task ConstructImage(GLTFImage image, int imageCacheIndex, bool m
}

await YieldOnTimeoutAndThrowOnLowMemory();
await ConstructUnityTexture(stream, markGpuOnly, isLinear, image, imageCacheIndex);
await ConstructUnityTexture(stream, markGpuOnly, isLinear, isNormal, image, imageCacheIndex);
}
}

Expand Down Expand Up @@ -195,7 +195,7 @@ async Task<Texture2D> CheckMimeTypeAndLoadImage(GLTFImage image, Texture2D textu
return texture;
}

protected virtual async Task ConstructUnityTexture(Stream stream, bool markGpuOnly, bool isLinear, GLTFImage image, int imageCacheIndex)
protected virtual async Task ConstructUnityTexture(Stream stream, bool markGpuOnly, bool isLinear, bool isNormal, GLTFImage image, int imageCacheIndex)
{
#if UNITY_EDITOR
if (stream is AssetDatabaseStream assetDatabaseStream)
Expand All @@ -206,6 +206,17 @@ protected virtual async Task ConstructUnityTexture(Stream stream, bool markGpuOn
_assetCache.ImageCache[imageCacheIndex] = tx;
return;
}

bool convertToDxt5nmFormat = false;
if (isNormal && Context.SourceImporter != null)
{
BuildTargetGroup activeTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
if (PlayerSettings.GetNormalMapEncoding(activeTargetGroup) == NormalMapEncoding.DXT5nm)
{
convertToDxt5nmFormat = true;
}
}

#endif
Texture2D texture = new Texture2D(4, 4, TextureFormat.RGBA32, GenerateMipMapsForTextures, isLinear);
texture.name = string.IsNullOrEmpty(image.Name) ? Path.GetFileNameWithoutExtension(image.Uri) : image.Name;
Expand Down Expand Up @@ -277,6 +288,12 @@ protected virtual async Task ConstructUnityTexture(Stream stream, bool markGpuOn
texture = await CheckMimeTypeAndLoadImage(image, texture, buffer, markGpuOnly);
}

if (texture && convertToDxt5nmFormat)
{
await NormalMapEncodingConverter.ConvertToDxt5nmAsync(texture);
texture.Apply();
}

if (!texture)
_assetCache.InvalidImageCache[imageCacheIndex] = newTextureObject;

Expand Down Expand Up @@ -346,7 +363,7 @@ public virtual async Task LoadTextureAsync(GLTFTexture texture, int textureIndex
}

await ConstructImageBuffer(texture, textureIndex);
await ConstructTexture(texture, textureIndex, markGpuOnly, isLinear);
await ConstructTexture(texture, textureIndex, markGpuOnly, isLinear, false);
}
finally
{
Expand Down Expand Up @@ -383,13 +400,13 @@ public virtual Texture GetTexture(int textureIndex)
return _assetCache.TextureCache[textureIndex].Texture;
}

protected virtual async Task ConstructTexture(GLTFTexture texture, int textureIndex, bool markGpuOnly, bool isLinear)
protected virtual async Task ConstructTexture(GLTFTexture texture, int textureIndex, bool markGpuOnly, bool isLinear, bool isNormal)
{
if (_assetCache.TextureCache[textureIndex].Texture == null)
{
int sourceId = GetTextureSourceId(texture);
GLTFImage image = _gltfRoot.Images[sourceId];
await ConstructImage(image, sourceId, markGpuOnly, isLinear);
await ConstructImage(image, sourceId, markGpuOnly, isLinear, isNormal);

var source = _assetCache.ImageCache[sourceId];
if (!source) return;
Expand Down
50 changes: 50 additions & 0 deletions Runtime/Scripts/SceneImporter/NormalMapEncodingConverter.cs
@@ -0,0 +1,50 @@
using System.Threading.Tasks;
using UnityEngine;

namespace UnityGLTF
{
public static class NormalMapEncodingConverter
{
public static Texture2D ConvertToDxt5nm(Texture2D source)
{
var dest = new Texture2D(source.width, source.height, TextureFormat.DXT5, false);
var pixels = source.GetPixels();
for (var i = 0; i < pixels.Length; i++)
{
var c = pixels[i];
pixels[i] = new Color(1, c.g, 1, c.r);
}

dest.SetPixels(pixels);
return dest;
}

public static void ConvertToDxt5nm(Texture2D source, Texture2D dest)
{
var pixels = source.GetPixels();
for (var i = 0; i < pixels.Length; i++)
{
var c = pixels[i];
pixels[i] = new Color(1, c.g, 1, c.r);
}

dest.SetPixels(pixels);
}

public static async Task ConvertToDxt5nmAsync(Texture2D texture)
{
var pixels = texture.GetPixels();
await Task.Run(() =>
{
for (var i = 0; i < pixels.Length; i++)
{
var c = pixels[i];
pixels[i] = new Color(1, c.g, 1, c.r);
}
});

texture.SetPixels(pixels);
}

}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit dae24c7

Please sign in to comment.