/// Authors USD Shader inputs onto the given shader and material and connects private shader /// inputs to the public material inputs (the intent being, inputs are authored on the material /// and flow into the shader, which is a detail of the network). static void CreateShaderInputs <T>(pxr.UsdShadeShader shader, pxr.UsdShadeMaterial material, Dictionary <string, T> paramDict) { USD.NET.UsdTypeBinding binding; if (!USD.NET.UsdIo.Bindings.GetBinding(typeof(T), out binding)) { // TODO: add "with exception" to GetBinding(). throw new Exception("Type not found: " + typeof(T).Name); } foreach (var kvp in paramDict) { var inputName = new pxr.TfToken(kvp.Key); var matInput = material.CreateInput(inputName, binding.sdfTypeName); var shaderInput = shader.CreateInput(inputName, binding.sdfTypeName); matInput.Set(binding.toVtValue(kvp.Value)); shaderInput.Set(binding.toVtValue(kvp.Value)); shaderInput.ConnectToSource(matInput); } }
/// Authors a USD Material, Shader, parameters and connections between the two. /// The USD shader structure consists of a Material, which is connected to a shader output. The /// Shader consists of input parameters which are either connected to other shaders or in the case /// of public parameters, back to the material which is the public interface for the shading /// network. /// /// This function creates a material, shader, inputs, outputs, zero or more textures, and for each /// texture, a single primvar reader node to read the UV data from the geometric primitive. static string CreateMaterialNetwork(USD.NET.Scene scene, IExportableMaterial material, string rootPath = null) { var matSample = new ExportMaterialSample(); // Used scene object paths. string materialPath = GetMaterialPath(material, rootPath); string shaderPath = GetShaderPath(material, materialPath); string displayColorPrimvarReaderPath = GetPrimvarPath(material, "displayColor", shaderPath); string displayOpacityPrimvarReaderPath = GetPrimvarPath(material, "displayOpacity", shaderPath); // The material was already created. if (scene.GetPrimAtPath(materialPath) != null) { return(materialPath); } // Ensure the root material path is defined in the scene. scene.Stage.DefinePrim(new pxr.SdfPath(rootPath)); // Connect the materail surface to the output of the shader. matSample.surface.SetConnectedPath(shaderPath, "outputs:result"); scene.Write(materialPath, matSample); // Create the shader and conditionally connect the diffuse color to the MainTex output. var shaderSample = GetShaderSample(material); var texturePath = CreateAlphaTexture(scene, shaderPath, material); if (texturePath != null) { // A texture was created, so connect the opacity input to the texture output. shaderSample.opacity.SetConnectedPath(texturePath, "outputs:a"); } else { // TODO: currently primvars:displayOpacity is not multiplied when an alpha texture is // present. However, this only affects the USD preview. The correct solution // requires a multiply node in the shader graph, but this does not yet exist. scene.Write(displayOpacityPrimvarReaderPath, new PrimvarReader1fSample("displayOpacity")); shaderSample.opacity.SetConnectedPath(displayOpacityPrimvarReaderPath, "outputs:result"); } // Create a primvar reader to read primvars:displayColor. scene.Write(displayColorPrimvarReaderPath, new PrimvarReader3fSample("displayColor")); // Connect the diffuse color to the primvar reader. shaderSample.diffuseColor.SetConnectedPath(displayColorPrimvarReaderPath, "outputs:result"); scene.Write(shaderPath, shaderSample); // // Everything below is ad-hoc data, which is written using the low level USD API. // It consists of the Unity shader parameters and the non-exported texture URIs. // Also note that scene.GetPrimAtPath will return null when the prim is InValid, // so there is no need to call IsValid() on the resulting prim. // var shadeMaterial = new pxr.UsdShadeMaterial(scene.GetPrimAtPath(materialPath)); var shadeShader = new pxr.UsdShadeShader(scene.GetPrimAtPath(shaderPath)); if (material.SupportsDetailedMaterialInfo) { CreateShaderInputs(shadeShader, shadeMaterial, material.FloatParams); CreateShaderInputs(shadeShader, shadeMaterial, material.ColorParams); CreateShaderInputs(shadeShader, shadeMaterial, material.VectorParams); } CreateTextureUris(shadeShader.GetPrim(), material); return(materialPath); }