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)