Skip to content
This repository has been archived by the owner on Sep 2, 2021. It is now read-only.

Commit

Permalink
Fixed DXT5 texture export. #14
Browse files Browse the repository at this point in the history
  • Loading branch information
ousttrue committed Aug 6, 2018
1 parent c481c92 commit 185cfd0
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 58 deletions.
24 changes: 0 additions & 24 deletions Core/Scripts/Extensions/UnityExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,30 +289,6 @@ public static Material[] GetSharedMaterials(this Transform t)
return new Material[] { };
}

public static IEnumerable<Texture> GetTextures(this Material m)
{
#if UNITY_EDITOR
for (int i = 0; i < ShaderUtil.GetPropertyCount(m.shader); ++i)
{
if(ShaderUtil.GetPropertyType(m.shader, i)==ShaderUtil.ShaderPropertyType.TexEnv)
{
var texture = m.GetTexture(ShaderUtil.GetPropertyName(m.shader, i));
if (texture != null)
{
yield return texture;
}
}
}

#else
var texture = m.mainTexture as Texture2D;
if (texture != null)
{
yield return texture;
}
#endif
}

public static bool Has<T>(this Transform transform, T t) where T : Component
{
return transform.GetComponent<T>() == t;
Expand Down
19 changes: 13 additions & 6 deletions Core/Scripts/IO/ShaderPropExporter/PreShaderPropExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ public static partial class PreShaderPropExporter
static void PreExport()
{
foreach (var fi in typeof(PreShaderPropExporter).GetFields(
BindingFlags.Static
| BindingFlags.Public
BindingFlags.Static
| BindingFlags.Public
| BindingFlags.NonPublic))
{
var attr = fi.GetCustomAttributes(true).FirstOrDefault(y => y is PreExportShadersAttribute);
if (attr != null)
{
var supportedShaders = fi.GetValue(null) as SupportedShader[];
foreach(var supported in supportedShaders)
foreach (var supported in supportedShaders)
{
PreExport(supported);
}
Expand Down Expand Up @@ -109,12 +109,19 @@ public static ShaderProps GetPropsForSupportedShader(string shaderName)
}

ShaderProps props;
if (!m_shaderPropMap.TryGetValue(shaderName, out props))
if (m_shaderPropMap.TryGetValue(shaderName, out props))
{
return null;
return props;
}

return props;
#if UNITY_EDITOR
// fallback
Debug.LogWarningFormat("Unsupported shader: {0}", shaderName);
var shader = Shader.Find(shaderName);
return ShaderProps.FromShader(shader);
#else
return null;
#endif
}
#endregion
}
Expand Down
36 changes: 35 additions & 1 deletion Core/Scripts/IO/TextureIO.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
Expand Down Expand Up @@ -29,6 +30,39 @@ public static void MarkTextureAssetAsNormalMap(string assetPath)
}
#endif

public struct TextureExportItem
{
public Texture Texture;
public bool IsNormalMap;

public TextureExportItem(Texture texture, bool isNormalMap)
{
Texture = texture;
IsNormalMap = isNormalMap;
}

public TextureExportItem(Texture texture) : this(texture, false)
{
}
}

public static IEnumerable<TextureExportItem> GetTextures(Material m)
{
var props = ShaderPropExporter.PreShaderPropExporter.GetPropsForSupportedShader(m.shader.name);
if (props == null)
{
yield return new TextureExportItem(m.mainTexture);
}

foreach (var prop in props.Properties)
{
if (prop.ShaderPropertyType == ShaderPropExporter.ShaderPropertyType.TexEnv)
{
yield return new TextureExportItem(m.GetTexture(prop.Key), prop.IsNormalMap);
}
}
}

struct BytesWithPath
{
public Byte[] Bytes;
Expand All @@ -43,7 +77,7 @@ public BytesWithPath(Texture texture)
}
}

public static int ExportTexture(glTF gltf, int bufferIndex, Texture texture)
public static int ExportTexture(glTF gltf, int bufferIndex, Texture texture, bool isNormalMap)
{
var bytesWithPath = new BytesWithPath(texture); ;

Expand Down
66 changes: 57 additions & 9 deletions Core/Scripts/IO/TextureItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,30 +260,78 @@ static Color32 ConvertOcclusion(Color32 src)

class sRGBScope : IDisposable
{
bool sRGBWrite;
public sRGBScope()
bool m_sRGBWrite;
public sRGBScope(bool sRGBWrite)
{
sRGBWrite = GL.sRGBWrite;
GL.sRGBWrite = true;
m_sRGBWrite = GL.sRGBWrite;
GL.sRGBWrite = sRGBWrite;
}

public void Dispose()
{
GL.sRGBWrite = sRGBWrite;
GL.sRGBWrite = m_sRGBWrite;
}
}

static Texture2D DTXnm2RGBA(Texture2D tex)
{
Color[] colors = tex.GetPixels();
for (int i = 0; i < colors.Length; i++)
{
Color c = colors[i];
c.r = c.a * 2 - 1; //red<-alpha (x<-w)
c.g = c.g * 2 - 1; //green is always the same (y)
Vector2 xy = new Vector2(c.r, c.g); //this is the xy vector
c.b = Mathf.Sqrt(1 - Mathf.Clamp01(Vector2.Dot(xy, xy))); //recalculate the blue channel (z)
colors[i] = new Color(c.r * 0.5f + 0.5f, c.g * 0.5f + 0.5f, c.b * 0.5f + 0.5f); //back to 0-1 range
}
tex.SetPixels(colors); //apply pixels to the texture
tex.Apply();
return tex;
}

static bool IsDxt5(Texture src)
{
var srcAsTexture2D = src as Texture2D;
if (srcAsTexture2D != null)
{
Debug.LogFormat("{0} format {1}", srcAsTexture2D.name, srcAsTexture2D.format);
return srcAsTexture2D.format == TextureFormat.DXT5;
}
return false;
}

static Material s_dxt5decode;
static Material GetDecodeDxt5()
{
if (s_dxt5decode == null)
{
s_dxt5decode = new Material(Shader.Find("UniGLTF/Dxt5Decoder"));
}
return s_dxt5decode;
}

public static Texture2D CopyTexture(Texture src)
{
Texture2D dst = null;

var renderTexture = new RenderTexture(src.width, src.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
using (var scope = new sRGBScope())

using (var scope = new sRGBScope(true))
{
Graphics.Blit(src, renderTexture);
dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, false);
dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0);
if (IsDxt5(src))
{
var mat = GetDecodeDxt5();
Graphics.Blit(src, renderTexture, mat);
}
else
{
Graphics.Blit(src, renderTexture);
}
}
dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, false);
dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0);

RenderTexture.active = null;
if (Application.isEditor)
{
Expand Down
40 changes: 22 additions & 18 deletions Core/Scripts/IO/gltfExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ public gltfExporter(glTF gltf)
{
glTF = gltf;

glTF.asset=new glTFAssets
glTF.asset = new glTFAssets
{
generator = "UniGLTF-"+UniGLTFVersion.VERSION,
generator = "UniGLTF-" + UniGLTFVersion.VERSION,
version = "2.0",
};
}
Expand Down Expand Up @@ -251,7 +251,8 @@ static AnimationWithSampleCurves ExportAnimation(AnimationClip clip, Transform r

var nodeIndex = GetNodeIndex(root, nodes, binding.path);
var target = PropertyToTarget(binding.propertyName);
if (target == glTFAnimationTarget.NOT_IMPLEMENTED) {
if (target == glTFAnimationTarget.NOT_IMPLEMENTED)
{
continue;
}
var samplerIndex = animation.Animation.AddChannelAndGetSampler(nodeIndex, target);
Expand All @@ -277,7 +278,9 @@ static AnimationWithSampleCurves ExportAnimation(AnimationClip clip, Transform r
binding.propertyName == "m_LocalRotation.w")
{
values.Output[j] = -keys[i].value;
} else {
}
else
{
values.Output[j] = keys[i].value;
}
}
Expand All @@ -295,9 +298,9 @@ public struct Exported
public List<Texture> Textures;
}

static glTFMesh ExportPrimitives(glTF gltf, int bufferIndex,
static glTFMesh ExportPrimitives(glTF gltf, int bufferIndex,
string rendererName,
Mesh mesh, Material[] materials,
Mesh mesh, Material[] materials,
List<Material> unityMaterials)
{
var positions = mesh.vertices.Select(y => y.ReverseZ()).ToArray();
Expand Down Expand Up @@ -460,20 +463,20 @@ static gltfMorphTarget ExportMorphTarget(glTF gltf, int bufferIndex,
{
for (int i = 0; i < blendShpaeNormals.Length; ++i) blendShpaeNormals[i] = blendShpaeNormals[i].ReverseZ();
blendShapeNormalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
blendShpaeNormals,
blendShpaeNormals,
glBufferTarget.ARRAY_BUFFER);
}

if (useTangent)
{
for (int i = 0; i < blendShapeTangents.Length; ++i) blendShapeTangents[i] = blendShapeTangents[i].ReverseZ();
blendShapeTangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
blendShapeTangents,
blendShapeTangents,
glBufferTarget.ARRAY_BUFFER);
}
}

if(blendShapePositionAccessorIndex!=-1)
if (blendShapePositionAccessorIndex != -1)
{
gltf.accessors[blendShapePositionAccessorIndex].min = blendShapeVertices.Aggregate(blendShapeVertices[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray();
gltf.accessors[blendShapePositionAccessorIndex].max = blendShapeVertices.Aggregate(blendShapeVertices[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray();
Expand Down Expand Up @@ -520,7 +523,7 @@ static void ExportMeshes(glTF gltf, int bufferIndex,
}
}

public static Exported FromGameObject(glTF gltf, GameObject go, bool useSparseAccessorForMorphTarget=false)
public static Exported FromGameObject(glTF gltf, GameObject go, bool useSparseAccessorForMorphTarget = false)
{
var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
var bufferIndex = gltf.AddBuffer(bytesBuffer);
Expand All @@ -536,15 +539,16 @@ public static Exported FromGameObject(glTF gltf, GameObject go, bool useSparseAc

#region Materials and Textures
var unityMaterials = unityNodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList();
var unityTextures = unityMaterials.SelectMany(x => x.GetTextures()).Where(x => x != null).Distinct().ToList();
var unityTextures = unityMaterials.SelectMany(x => TextureIO.GetTextures(x)).Where(x => x.Texture != null).Distinct().ToList();

for (int i = 0; i < unityTextures.Count; ++i)
{
var texture = unityTextures[i];
TextureIO.ExportTexture(gltf, bufferIndex, texture);
TextureIO.ExportTexture(gltf, bufferIndex, texture.Texture, texture.IsNormalMap);
}

gltf.materials = unityMaterials.Select(x => MaterialIO.ExportMaterial(x, unityTextures)).ToList();

var textures = unityTextures.Select(y => y.Texture).ToList();
gltf.materials = unityMaterials.Select(x => MaterialIO.ExportMaterial(x, textures)).ToList();
#endregion

#region Meshes
Expand All @@ -556,12 +560,12 @@ public static Exported FromGameObject(glTF gltf, GameObject go, bool useSparseAc
})
.Where(x =>
{
if(x.Mesh == null)
if (x.Mesh == null)
{
return false;
}
if(x.Rendererer.sharedMaterials==null
|| x.Rendererer.sharedMaterials.Length==0)
if (x.Rendererer.sharedMaterials == null
|| x.Rendererer.sharedMaterials.Length == 0)
{
return false;
}
Expand Down Expand Up @@ -658,7 +662,7 @@ public static Exported FromGameObject(glTF gltf, GameObject go, bool useSparseAc
Meshes = unityMeshes,
Nodes = unityNodes.Select(x => x.transform).ToList(),
Materials = unityMaterials,
Textures = unityTextures,
Textures = textures,
};
}
#endregion
Expand Down
54 changes: 54 additions & 0 deletions Resources/Shaders/Dxt5Decoder.shader
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Shader "UniGLTF/Dxt5Decoder"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};

struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};

v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}

sampler2D _MainTex;

fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);

col.xyz = (UnpackNormal(col) + 1) * 0.5;
col.z = 1;

return col;
}
ENDCG
}
}
}
Loading

0 comments on commit 185cfd0

Please sign in to comment.