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); }
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; } }
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; } }
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); } } }
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); } } }