Beispiel #1
0
        public static void ExportStandard(Scene scene,
                                          string usdShaderPath,
                                          Material material,
                                          UnityPreviewSurfaceSample surface,
                                          string destTexturePath)
        {
            ExportStandardCommon(scene, usdShaderPath, material, surface, destTexturePath);
            surface.useSpecularWorkflow.defaultValue = 0;

            if (material.HasProperty("_MetallicGlossMap") && material.GetTexture("_MetallicGlossMap") != null)
            {
                var newTex = SetupTexture(scene, usdShaderPath, material, surface, destTexturePath, "_MetallicGlossMap", "r");
                surface.metallic.SetConnectedPath(newTex);
            }
            else if (material.HasProperty("_Metallic"))
            {
                surface.metallic.defaultValue = material.GetFloat("_Metallic");
            }
            else
            {
                surface.metallic.defaultValue = .5f;
            }

            if (material.HasProperty("_Glossiness"))
            {
                surface.roughness.defaultValue = 1 - material.GetFloat("_Glossiness");
            }
            else
            {
                surface.roughness.defaultValue = 0.5f;
            }
        }
        /// <summary>
        /// Reads and returns the UsdPreviewSurface data for the prim at the given path, if present.
        /// </summary>
        /// <param name="scene">The USD scene object.</param>
        /// <param name="primPath">The path to the object in the USD scene.</param>
        /// <returns>A PreviewSurfaceSample if found, otherwise null.</returns>
        public static UnityPreviewSurfaceSample GetSurfaceShaderPrim(Scene scene, string primPath)
        {
            var materialBinding = new MaterialBindingSample();

            scene.Read(primPath, materialBinding);

            var matPath = materialBinding.binding.GetTarget(0);

            if (matPath == null)
            {
                //Debug.LogWarning("No material binding found at: <" + meshPath + ">");
                return(null);
            }

            var materialSample = new MaterialSample();

            scene.Read(matPath, materialSample);
            if (string.IsNullOrEmpty(materialSample.surface.connectedPath))
            {
                Debug.LogWarning("Material surface not connected: <" + matPath + ">");
            }

            var exportSurf = new UnityPreviewSurfaceSample();

            scene.Read(new pxr.SdfPath(materialSample.surface.connectedPath).GetPrimPath(), exportSurf);

            return(exportSurf);
        }
Beispiel #3
0
        public static void ExportStandardSpecular(Scene scene,
                                                  string usdShaderPath,
                                                  Material material,
                                                  UnityPreviewSurfaceSample surface,
                                                  string destTexturePath)
        {
            Color c;

            ExportStandardCommon(scene, usdShaderPath, material, surface, destTexturePath);
            surface.useSpecularWorkflow.defaultValue = 1;
            surface.metallic.defaultValue            = 0;

            if (material.HasProperty("_SpecGlossMap") && material.GetTexture("_SpecGlossMap") != null)
            {
                var scale = Vector4.one;
                if (material.HasProperty("_SpecColor"))
                {
                    scale = material.GetColor("_SpecColor");
                }

                var newTex = SetupTexture(scene, usdShaderPath, material, surface, scale, destTexturePath,
                                          "_SpecGlossMap", "rgb");
                surface.specularColor.SetConnectedPath(newTex);
            }
            else if (material.HasProperty("_SpecColor"))
            {
                // If there is a spec color, then this is not metallic workflow.
                c = material.GetColor("_SpecColor").linear;
                surface.specularColor.defaultValue = new Vector3(c.r, c.g, c.b);
            }
            else
            {
                c = new Color(.5f, .5f, .5f);
                surface.specularColor.defaultValue = new Vector3(c.r, c.g, c.b);
            }

            // TODO: Specular and roughness are combined and the shader configuration dictates
            // where the glossiness comes from (albedo or spec alpha).

            if (material.HasProperty("_Glossiness"))
            {
                surface.roughness.defaultValue = 1 - material.GetFloat("_Glossiness");
            }
            else
            {
                surface.roughness.defaultValue = 0.5f;
            }
        }
        public static void ExportMaterial(Scene scene, Material mat, string usdMaterialPath)
        {
            string shaderPath = usdMaterialPath + "/PreviewSurface";

            var material = new MaterialSample();

            material.surface.SetConnectedPath(shaderPath, "outputs:surface");
            var origTime = scene.Time;

            try
            {
                scene.Time = null;
                scene.Write(usdMaterialPath, material);
            }
            finally
            {
                scene.Time = origTime;
            }

            var shader  = new UnityPreviewSurfaceSample();
            var texPath = /*TODO: this should be explicit*/
                          System.IO.Path.GetDirectoryName(scene.FilePath);

            ExportHandler handler = null;

            if (!ExportRegistry.TryGetValue(mat.shader.name, out handler))
            {
                handler = ExportRegistry[kStandardFallbackHandler];
            }

            if (handler == null)
            {
                Debug.LogException(new System.Exception("Could not find handler to export shader: " + mat.shader.name));
                return;
            }

            try
            {
                scene.Time = null;
                handler(scene, shaderPath, mat, shader, texPath);
                scene.Write(shaderPath, shader);
            }
            finally
            {
                scene.Time = origTime;
            }
        }
Beispiel #5
0
        public static void ExportStandard(Scene scene,
                                          string usdShaderPath,
                                          Material material,
                                          UnityPreviewSurfaceSample surface,
                                          string destTexturePath)
        {
            ExportStandardCommon(scene, usdShaderPath, material, surface, destTexturePath);
            surface.useSpecularWorkflow.defaultValue = 0;

            if (material.HasProperty("_MetallicGlossMap") && material.GetTexture("_MetallicGlossMap") != null)
            {
                var scale = Vector4.one;
                if (material.HasProperty("_Metallic"))
                {
                    scale.x = material.GetFloat("_Metallic");
                }

                var newTex = SetupTexture(scene, usdShaderPath, material, surface, scale, destTexturePath,
                                          "_MetallicGlossMap", "b", ConversionType.SwapRASmoothnessToBGRoughness);
                surface.metallic.SetConnectedPath(newTex);
                scale   = Vector4.one;
                scale.x = 1 - material.GetFloat("_Glossiness");
                var roughnessTex = SetupTexture(scene, usdShaderPath, material, surface, scale, destTexturePath,
                                                "_MetallicGlossMap", "g", ConversionType.SwapRASmoothnessToBGRoughness);
                surface.roughness.SetConnectedPath(roughnessTex);
            }
            else if (material.HasProperty("_Metallic"))
            {
                surface.metallic.defaultValue = material.GetFloat("_Metallic");
            }
            else
            {
                surface.metallic.defaultValue = .5f;
            }

            if (material.HasProperty("_Glossiness"))
            {
                surface.roughness.defaultValue = 1 - material.GetFloat("_Glossiness");
            }
            else
            {
                surface.roughness.defaultValue = 0.5f;
            }
        }
Beispiel #6
0
        private static void ExportStandardCommon(Scene scene,
                                                 string usdShaderPath,
                                                 Material mat,
                                                 UnityPreviewSurfaceSample surface,
                                                 string destTexturePath)
        {
            Color c;

            // Export all generic parameter.
            // These are not useful to UsdPreviewSurface, but enable perfect round-tripping.
            surface.unity.shaderName     = mat.shader.name;
            surface.unity.shaderKeywords = mat.shaderKeywords;

            // Unfortunately, parameter names can only be discovered generically in-editor.
#if UNITY_EDITOR
            for (int i = 0; i < UnityEditor.ShaderUtil.GetPropertyCount(mat.shader); i++)
            {
                string name = UnityEditor.ShaderUtil.GetPropertyName(mat.shader, i);
                if (!mat.HasProperty(name))
                {
                    continue;
                }

                // Note that for whatever reason, shader properties may be listed multiple times.
                // So dictionary assignment is used here, instead of Add().

                switch (UnityEditor.ShaderUtil.GetPropertyType(mat.shader, i))
                {
                case UnityEditor.ShaderUtil.ShaderPropertyType.Color:
                    surface.unity.colorArgs[name] = mat.GetColor(name).linear;
                    break;

                case UnityEditor.ShaderUtil.ShaderPropertyType.Float:
                case UnityEditor.ShaderUtil.ShaderPropertyType.Range:
                    surface.unity.floatArgs[name] = mat.GetFloat(name);
                    break;

                case UnityEditor.ShaderUtil.ShaderPropertyType.Vector:
                    surface.unity.vectorArgs[name] = mat.GetVector(name);
                    break;
                }
            }
#endif

            if (mat.HasProperty("_MainTex") && mat.GetTexture("_MainTex") != null)
            {
                var scale = new Vector4(1, 1, 1, 1);
                if (mat.HasProperty("_Color"))
                {
                    scale = mat.GetColor("_Color").linear;
                }
                var newTex = SetupTexture(scene, usdShaderPath, mat, surface, scale, destTexturePath, "_MainTex",
                                          "rgb");
                surface.diffuseColor.SetConnectedPath(newTex);
            }
            else if (mat.HasProperty("_Color"))
            {
                // Standard.
                c = mat.GetColor("_Color").linear;
                surface.diffuseColor.defaultValue = new Vector3(c.r, c.g, c.b);
            }
            else
            {
                c = Color.white;
                surface.diffuseColor.defaultValue = new Vector3(c.r, c.g, c.b);
            }

            // Standard Shader has 4 modes (magic shader values internally defined in StandardShaderGUI.cs):
            // Opaque - no opacity/transparency
            // Cutout - opacityThreshold should be used to cut off based on alpha values (in _MainTex.a)
            // Fade - opacity should be used, but no opacityThreshold
            // Transparent - opacity should be used, but no opacityThreshold.
            // Note: not quite sure if and how the difference between Fade and Transparent should be handled in USD.
            StandardShaderBlendMode shaderMode = StandardShaderBlendMode.Opaque;
            if (mat.HasProperty("_Mode"))
            {
                shaderMode = (StandardShaderBlendMode)mat.GetFloat("_Mode");
            }

            if (shaderMode != StandardShaderBlendMode.Opaque)
            {
                if (mat.HasProperty("_MainTex") && mat.GetTexture("_MainTex") != null)
                {
                    var scale = Vector4.one;
                    if (mat.HasProperty("_BaseColor"))
                    {
                        scale.w = mat.GetColor("_BaseColor").linear.a;
                    }
                    var newTex = SetupTexture(scene, usdShaderPath, mat, surface, scale, destTexturePath, "_MainTex",
                                              "a");
                    surface.opacity.SetConnectedPath(newTex);
                }
                else if (mat.HasProperty("_Color"))
                {
                    c = mat.GetColor("_Color").linear;
                    surface.opacity.defaultValue = c.a;
                }
                else
                {
                    c = Color.white;
                    surface.opacity.defaultValue = 1.0f;
                }
            }
            else
            {
                surface.opacity.defaultValue = 1.0f;
            }

            if (shaderMode == StandardShaderBlendMode.Cutout && mat.HasProperty("_Cutoff"))
            {
                surface.opacityThreshold.defaultValue = mat.GetFloat("_Cutoff");
            }

            surface.useSpecularWorkflow.defaultValue = 1;

            if (mat.HasProperty("_BumpMap") && mat.GetTexture("_BumpMap") != null)
            {
                var newTex = SetupTexture(scene, usdShaderPath, mat, surface, Vector4.one, destTexturePath, "_BumpMap",
                                          "rgb", ConversionType.UnpackNormal);
                surface.normal.SetConnectedPath(newTex);
            }

            if (mat.HasProperty("_ParallaxMap") && mat.GetTexture("_ParallaxMap") != null)
            {
                var newTex = SetupTexture(scene, usdShaderPath, mat, surface, Vector4.one, destTexturePath,
                                          "_ParallaxMap", "rgb");
                surface.displacement.SetConnectedPath(newTex);
            }

            if (mat.HasProperty("_OcclusionMap") && mat.GetTexture("_OcclusionMap") != null)
            {
                var newTex = SetupTexture(scene, usdShaderPath, mat, surface, Vector4.one, destTexturePath,
                                          "_OcclusionMap", "r");
                surface.occlusion.SetConnectedPath(newTex);
            }

            /*
             * if (mat.HasProperty("_Metallic")) {
             * surface.metallic.defaultValue = mat.GetFloat("_Metallic");
             * } else {
             * surface.metallic.defaultValue = .5f;
             * }
             */

            if (mat.IsKeywordEnabled("_EMISSION"))
            {
                if (mat.HasProperty("_EmissionMap") && mat.GetTexture("_EmissionMap") != null)
                {
                    var scale = Vector4.one;
                    if (mat.HasProperty("_EmissionColor"))
                    {
                        scale = mat.GetColor("_EmissionColor").linear;
                    }
                    var newTex = SetupTexture(scene, usdShaderPath, mat, surface, scale, destTexturePath,
                                              "_EmissionMap", "rgb");
                    surface.emissiveColor.SetConnectedPath(newTex);
                }

                if (mat.HasProperty("_EmissionColor"))
                {
                    c = mat.GetColor("_EmissionColor").linear;
                    surface.emissiveColor.defaultValue = new Vector3(c.r, c.g, c.b);
                }
            }
        }
Beispiel #7
0
        public static void ExportGeneric(Scene scene,
                                         string usdShaderPath,
                                         Material material,
                                         UnityPreviewSurfaceSample surface,
                                         string destTexturePath)
        {
            Color c;

            ExportStandardCommon(scene, usdShaderPath, material, surface, destTexturePath);

            if (material.HasProperty("_SpecColor"))
            {
                // If there is a spec color, then this is not metallic workflow.
                c = material.GetColor("_SpecColor").linear;
            }
            else
            {
                c = new Color(.4f, .4f, .4f);
            }

            surface.specularColor.defaultValue = new Vector3(c.r, c.g, c.b);

            if (material.HasProperty("_Metallic"))
            {
                surface.metallic.defaultValue = material.GetFloat("_Metallic");
            }
            else
            {
                surface.metallic.defaultValue = .5f;
            }

            // Gross heuristics to detect workflow.
            if (material.IsKeywordEnabled("_SPECGLOSSMAP") ||
                material.HasProperty("_SpecColor") ||
                material.HasProperty("_SpecularColor") ||
                material.shader.name.ToLower().Contains("specular"))
            {
                if (material.HasProperty("_SpecGlossMap") && material.GetTexture("_SpecGlossMap") != null)
                {
                    var scale = Vector4.one;
                    if (material.HasProperty("_SpecularColor"))
                    {
                        scale = material.GetColor("_SpecularColor");
                    }

                    var newTex = SetupTexture(scene, usdShaderPath, material, surface, scale, destTexturePath,
                                              "_SpecGlossMap", "rgb");
                    surface.specularColor.SetConnectedPath(newTex);
                }
                else if (material.HasProperty("_SpecColor"))
                {
                    // If there is a spec color, then this is not metallic workflow.
                    c = material.GetColor("_SpecColor").linear;
                    surface.specularColor.defaultValue = new Vector3(c.r, c.g, c.b);
                }
                else
                {
                    c = new Color(.5f, .5f, .5f);
                    surface.specularColor.defaultValue = new Vector3(c.r, c.g, c.b);
                }

                if (material.HasProperty("_Glossiness"))
                {
                    surface.roughness.defaultValue = 1 - material.GetFloat("_Glossiness");
                }
                else
                {
                    surface.roughness.defaultValue = 0.5f;
                }

                surface.useSpecularWorkflow.defaultValue = 1;
            }
            else
            {
                surface.useSpecularWorkflow.defaultValue = 0;
                if (material.HasProperty("_MetallicGlossMap") && material.GetTexture("_MetallicGlossMap") != null)
                {
                    var scale = Vector4.one;
                    if (material.HasProperty("_Metallic"))
                    {
                        scale.x = material.GetFloat("_Metallic");
                    }

                    var newTex = SetupTexture(scene, usdShaderPath, material, surface, scale, destTexturePath,
                                              "_MetallicGlossMap", "r");
                    surface.metallic.SetConnectedPath(newTex);
                }
                else if (material.HasProperty("_Metallic"))
                {
                    surface.metallic.defaultValue = material.GetFloat("_Metallic");
                }
                else
                {
                    surface.metallic.defaultValue = .5f;
                }

                if (material.HasProperty("_Glossiness"))
                {
                    surface.roughness.defaultValue = 1 - material.GetFloat("_Glossiness");
                }
                else
                {
                    surface.roughness.defaultValue = 0.5f;
                }
            }

            if (material.HasProperty("_Smoothness"))
            {
                surface.roughness.defaultValue = 1 - material.GetFloat("_Smoothness");
            }
            else if (material.HasProperty("_Glossiness"))
            {
                surface.roughness.defaultValue = 1 - material.GetFloat("_Glossiness");
            }
            else if (material.HasProperty("_Roughness"))
            {
                surface.roughness.defaultValue = material.GetFloat("_Roughness");
            }
            else
            {
                surface.roughness.defaultValue = 0.5f;
            }
        }
        /// <summary>
        /// Builds a Unity Material from the given USD material sample.
        /// </summary>
        public static Material BuildMaterial(Scene scene,
                                             string materialPath,
                                             MaterialSample sample,
                                             SceneImportOptions options)
        {
            if (string.IsNullOrEmpty(sample.surface.connectedPath))
            {
                return(null);
            }

            var previewSurf = new UnityPreviewSurfaceSample();

            scene.Read(new pxr.SdfPath(sample.surface.connectedPath).GetPrimPath(), previewSurf);

            // Currently, only UsdPreviewSurface is supported.
            if (previewSurf.id == null || previewSurf.id != "UsdPreviewSurface")
            {
                Debug.LogWarning("Unknown surface type: <" + sample.surface.connectedPath + ">"
                                 + "Surface ID: " + previewSurf.id);
                return(null);
            }

            Material mat = null;

            if (options.materialMap.useOriginalShaderIfAvailable && !string.IsNullOrEmpty(previewSurf.unity.shaderName))
            {
                // We may or may not have the original shader.
                var shader = Shader.Find(previewSurf.unity.shaderName);
                if (shader)
                {
                    mat = new Material(shader);
                    mat.shaderKeywords = previewSurf.unity.shaderKeywords;
                }
                else
                {
                    Debug.LogWarning("Original shader not found: " + previewSurf.unity.shaderName);
                }
            }

            if (mat == null)
            {
                if (previewSurf.useSpecularWorkflow.defaultValue == 1)
                {
                    // Metallic workflow.
                    mat = Material.Instantiate(options.materialMap.SpecularWorkflowMaterial);
                }
                else
                {
                    // Metallic workflow.
                    mat = Material.Instantiate(options.materialMap.MetallicWorkflowMaterial);
                }
            }

            foreach (var kvp in previewSurf.unity.colorArgs)
            {
                mat.SetColor(kvp.Key, kvp.Value);
            }

            foreach (var kvp in previewSurf.unity.floatArgs)
            {
                mat.SetFloat(kvp.Key, kvp.Value);
            }

            foreach (var kvp in previewSurf.unity.vectorArgs)
            {
                mat.SetVector(kvp.Key, kvp.Value);
            }

            var pipeline = UnityEngine.Rendering.GraphicsSettings.renderPipelineAsset;

            if (!pipeline)
            {
                var matAdapter = new StandardShaderImporter(mat);
                matAdapter.ImportParametersFromUsd(scene, materialPath, sample, previewSurf, options);
                matAdapter.ImportFromUsd();
            }
            else if (pipeline.GetType().Name == "HDRenderPipelineAsset")
            {
                // Robustness: Comparing a strng ^ here is not great, but there is no other option.
                var matAdapter = new HdrpShaderImporter(mat);
                matAdapter.ImportParametersFromUsd(scene, materialPath, sample, previewSurf, options);
                matAdapter.ImportFromUsd();
            }
            else
            {
                // Fallback to the Standard importer, which may pickup some attributes by luck.
                var matAdapter = new StandardShaderImporter(mat);
                matAdapter.ImportParametersFromUsd(scene, materialPath, sample, previewSurf, options);
                matAdapter.ImportFromUsd();
            }

            // Get the material name from the path
            if (mat != null && !string.IsNullOrEmpty(materialPath))
            {
                mat.name = new pxr.SdfPath(materialPath).GetName();
            }

            return(mat);
        }
        private static void ExportStandardCommon(Scene scene,
                                                 string usdShaderPath,
                                                 Material mat,
                                                 UnityPreviewSurfaceSample surface,
                                                 string destTexturePath)
        {
            Color c;

            // Export all generic parameter.
            // These are not useful to UsdPreviewSurface, but enable perfect round-tripping.
            surface.unity.shaderName     = mat.shader.name;
            surface.unity.shaderKeywords = mat.shaderKeywords;

            // Unfortunately, parameter names can only be discovered generically in-editor.
#if UNITY_EDITOR
            for (int i = 0; i < UnityEditor.ShaderUtil.GetPropertyCount(mat.shader); i++)
            {
                string name = UnityEditor.ShaderUtil.GetPropertyName(mat.shader, i);
                if (!mat.HasProperty(name))
                {
                    continue;
                }
                switch (UnityEditor.ShaderUtil.GetPropertyType(mat.shader, i))
                {
                case UnityEditor.ShaderUtil.ShaderPropertyType.Color:
                    surface.unity.colorArgs.Add(name, mat.GetColor(name).linear);
                    break;

                case UnityEditor.ShaderUtil.ShaderPropertyType.Float:
                case UnityEditor.ShaderUtil.ShaderPropertyType.Range:
                    surface.unity.floatArgs.Add(name, mat.GetFloat(name));
                    break;

                case UnityEditor.ShaderUtil.ShaderPropertyType.Vector:
                    surface.unity.vectorArgs.Add(name, mat.GetVector(name));
                    break;
                }
            }
#endif

            surface.opacity.defaultValue = 1;

            if (mat.HasProperty("_MainTex") && mat.GetTexture("_MainTex") != null)
            {
                var newTex = SetupTexture(scene, usdShaderPath, mat, surface, destTexturePath, "_MainTex", "rgb");
                surface.diffuseColor.SetConnectedPath(newTex);
            }
            else if (mat.HasProperty("_Color"))
            {
                // Standard.
                c = mat.GetColor("_Color").linear;
                surface.diffuseColor.defaultValue = new Vector3(c.r, c.g, c.b);
            }
            else
            {
                c = Color.white;
                surface.diffuseColor.defaultValue = new Vector3(c.r, c.g, c.b);
            }

            surface.useSpecularWorkflow.defaultValue = 1;

            if (mat.HasProperty("_BumpMap") && mat.GetTexture("_BumpMap") != null)
            {
                var newTex = SetupTexture(scene, usdShaderPath, mat, surface, destTexturePath, "_BumpMap", "rgb");
                surface.normal.SetConnectedPath(newTex);
            }

            if (mat.HasProperty("_ParallaxMap") && mat.GetTexture("_ParallaxMap") != null)
            {
                var newTex = SetupTexture(scene, usdShaderPath, mat, surface, destTexturePath, "_ParallaxMap", "rgb");
                surface.displacement.SetConnectedPath(newTex);
            }

            if (mat.HasProperty("_OcclusionMap") && mat.GetTexture("_OcclusionMap") != null)
            {
                var newTex = SetupTexture(scene, usdShaderPath, mat, surface, destTexturePath, "_OcclusionMap", "r");
                surface.occlusion.SetConnectedPath(newTex);
            }

            /*
             * if (mat.HasProperty("_Metallic")) {
             * surface.metallic.defaultValue = mat.GetFloat("_Metallic");
             * } else {
             * surface.metallic.defaultValue = .5f;
             * }
             */

            if (mat.IsKeywordEnabled("_EMISSION"))
            {
                if (mat.HasProperty("_EmissionMap") && mat.GetTexture("_EmissionMap") != null)
                {
                    var newTex = SetupTexture(scene, usdShaderPath, mat, surface, destTexturePath, "_EmissionMap", "rgb");
                    surface.emissiveColor.SetConnectedPath(newTex);
                }

                if (mat.HasProperty("_EmissionColor"))
                {
                    c = mat.GetColor("_EmissionColor").linear;
                    surface.emissiveColor.defaultValue = new Vector3(c.r, c.g, c.b);
                }
            }
        }