diff --git a/package/com.unity.formats.usd/Dependencies/USD.NET.Unity/Shading/UsdPreviewSurface/UsdTransform2dSample.cs b/package/com.unity.formats.usd/Dependencies/USD.NET.Unity/Shading/UsdPreviewSurface/UsdTransform2dSample.cs
new file mode 100644
index 000000000..d24ed5ebe
--- /dev/null
+++ b/package/com.unity.formats.usd/Dependencies/USD.NET.Unity/Shading/UsdPreviewSurface/UsdTransform2dSample.cs
@@ -0,0 +1,56 @@
+// Copyright 2021 Unity Technologies. All rights reserved.
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using UnityEngine;
+
+namespace USD.NET.Unity
+{
+ ///
+ /// The following is based on the Pixar specification found here:
+ /// https://graphics.pixar.com/usd/release/spec_usdpreviewsurface.html#transform2d
+ ///
+ [System.Serializable]
+ [UsdSchema("Shader")]
+ public class UsdTransform2dSample : ShaderSample
+ {
+ public UsdTransform2dSample()
+ {
+ id = new pxr.TfToken("UsdTransform2d");
+ }
+
+ ///
+ /// Name of the primvar to be read from the primitive.
+ ///
+ [InputParameter("in")]
+ public Connectable @in = new Connectable();
+
+ [InputParameter("_Scale")]
+ public Connectable scale = new Connectable(new Vector2(1.0f, 1.0f));
+
+ [InputParameter("_Translation")]
+ public Connectable translation = new Connectable(new Vector2(0.0f, 0.0f));
+
+ [InputParameter("_Rotation")]
+ public Connectable rotation = new Connectable(0.0f);
+
+ public class Outputs : SampleBase
+ {
+ public Vector2? result;
+ }
+
+ [UsdNamespace("outputs")]
+ public Outputs outputs = new Outputs();
+ }
+}
diff --git a/package/com.unity.formats.usd/Dependencies/USD.NET.Unity/Shading/UsdPreviewSurface/UsdTransform2dSample.cs.meta b/package/com.unity.formats.usd/Dependencies/USD.NET.Unity/Shading/UsdPreviewSurface/UsdTransform2dSample.cs.meta
new file mode 100644
index 000000000..f855289c7
--- /dev/null
+++ b/package/com.unity.formats.usd/Dependencies/USD.NET.Unity/Shading/UsdPreviewSurface/UsdTransform2dSample.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: eb100e57b4f013643b2e911fee95c448
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/package/com.unity.formats.usd/Runtime/Scripts/IO/Materials/ShaderExporterBase.cs b/package/com.unity.formats.usd/Runtime/Scripts/IO/Materials/ShaderExporterBase.cs
index 2ec6e2c99..90992eb26 100644
--- a/package/com.unity.formats.usd/Runtime/Scripts/IO/Materials/ShaderExporterBase.cs
+++ b/package/com.unity.formats.usd/Runtime/Scripts/IO/Materials/ShaderExporterBase.cs
@@ -83,8 +83,11 @@ protected static string SetupTexture(Scene scene,
// normal needs to be converted if the one on disk isn't really a normal map
// (e.g. created from greyscale)
UnityEditor.TextureImporter importer =
- (UnityEditor.TextureImporter)UnityEditor.AssetImporter.GetAtPath(
- UnityEditor.AssetDatabase.GetAssetPath(srcTexture2d));
+ UnityEditor.AssetImporter.GetAtPath(
+ UnityEditor.AssetDatabase.GetAssetPath(srcTexture2d)) as UnityEditor.TextureImporter;
+
+ if (!importer) break;
+
if (importer.textureType != UnityEditor.TextureImporterType.NormalMap)
{
Debug.LogWarning("Texture " + textureName + " is set as NormalMap but isn't marked as such",
@@ -298,10 +301,44 @@ protected static string SetupTexture(Scene scene,
filePath = ImporterBase.MakeRelativePath(scene.FilePath, filePath);
filePath = filePath.Replace("\\", "/");
+ // uvReader - gets UV data from mesh
var uvReader = new PrimvarReaderSample();
uvReader.varname.defaultValue = new TfToken("st");
scene.Write(usdShaderPath + "/uvReader", uvReader);
- var usdTexReader = new TextureReaderSample(filePath, usdShaderPath + "/uvReader.outputs:result");
+ var connectionPath = "/uvReader.outputs:result";
+
+ var textureOffset = material.GetTextureOffset(textureName);
+ var textureScale = material.GetTextureScale(textureName);
+ var textureRotation = material.HasProperty(textureName + "Rotation") ? Mathf.Rad2Deg * material.GetFloat(textureName + "Rotation") : 0f;
+
+ if (textureOffset == Vector2.zero && textureScale == Vector2.one)
+ {
+ textureOffset = material.mainTextureOffset;
+ textureScale = material.mainTextureScale;
+ }
+
+ // Workaround: texture rotation in USDZ rotates around top left corner while glTF rotates around bottom left corner.
+ // Since shaders are built for the latter we need to compensate here.
+ var v = new Vector2(0 * textureScale.x, 1 * textureScale.y);
+ v = Matrix4x4.Rotate(Quaternion.Euler(0, 0, textureRotation)) * new Vector4(v.x, v.y, 0, 1);
+ v.y -= 1 * textureScale.y;
+ textureOffset -= v;
+
+ // export UsdTransform2d, only if non-default offset/scale
+ if(textureOffset != Vector2.zero || textureScale != Vector2.one || textureRotation != 0)
+ {
+ var usdTransform = new UsdTransform2dSample();
+ usdTransform.scale = new Connectable(textureScale);
+ usdTransform.translation = new Connectable(textureOffset);
+ if(textureRotation != 0)
+ usdTransform.rotation = new Connectable(textureRotation);
+ usdTransform.@in.SetConnectedPath(usdShaderPath + "/uvReader.outputs:result");
+ scene.Write(usdShaderPath + "/usdTransform", usdTransform);
+ connectionPath = "/usdTransform.outputs:result";
+ }
+
+ // texture reader - actual texture data based on transformed UV coordinates
+ var usdTexReader = new TextureReaderSample(filePath, usdShaderPath + connectionPath);
usdTexReader.wrapS =
new Connectable(
TextureReaderSample.GetWrapMode(srcTexture2d.wrapModeU));
@@ -312,9 +349,9 @@ protected static string SetupTexture(Scene scene,
{
usdTexReader.scale = new Connectable(scale);
}
-
// usdTexReader.isSRGB = new Connectable(TextureReaderSample.SRGBMode.Auto);
scene.Write(usdShaderPath + "/" + textureName, usdTexReader);
+
return usdShaderPath + "/" + textureName + ".outputs:" + textureOutput;
}
else
diff --git a/package/com.unity.formats.usd/Runtime/Scripts/IO/Materials/StandardShaderExporter.cs b/package/com.unity.formats.usd/Runtime/Scripts/IO/Materials/StandardShaderExporter.cs
index dfbd10cb2..cc533d4df 100644
--- a/package/com.unity.formats.usd/Runtime/Scripts/IO/Materials/StandardShaderExporter.cs
+++ b/package/com.unity.formats.usd/Runtime/Scripts/IO/Materials/StandardShaderExporter.cs
@@ -301,6 +301,7 @@ private static void ExportStandardCommon(Scene scene,
{
Color c;
+#if EXPORT_UNITY_SPECIFIC_DATA
// Export all generic parameter.
// These are not useful to UsdPreviewSurface, but enable perfect round-tripping.
surface.unity.shaderName = mat.shader.name;
@@ -333,6 +334,7 @@ private static void ExportStandardCommon(Scene scene,
break;
}
}
+#endif
#endif
if (mat.HasProperty("_MainTex") && mat.GetTexture("_MainTex") != null)