Skip to content

UsdPreviewSurface.inputs:diffuseColor connection does not serialize (typed-attr connect ignored; #259

@execomrt

Description

@execomrt

When authoring a connection to UsdPreviewSurface.inputs:diffuseColor, TinyUSDZ does not serialize the relationship into USDA. I tested both ways:

Setting the connection on the typed attribute (UsdPreviewSurface::diffuseColor.connect.set(Path(...)))

Setting a relationship via Shader.props["inputs:diffuseColor.connect"]

In both cases, the generated USDA is missing the expected

rel inputs:diffuseColor.connect = </.../Image_Texture.outputs:rgb>

Note: A connection for UsdUVTexture.inputs:st does serialize correctly when authored as texShader.props["inputs:st.connect"], so the issue appears specific to UsdPreviewSurface.inputs:diffuseColor.

To Reproduce

#include <iostream>
#include "tinyusdz.hh"

int main() {
  using namespace tinyusdz;

  Stage stage;

  // /Materials scope
  Scope s; s.name = "Materials";
  Prim matScope(s);
  stage.add_root_prim(Prim(s));
  stage.commit();

  // Material "M"
  Material m; m.name = "M";
  Prim matPrim(m);

  // Shader "Principled_BSDF" (UsdPreviewSurface)
  Shader pbr; pbr.name = "Principled_BSDF"; pbr.info_id = kUsdPreviewSurface;
  UsdPreviewSurface surf;
  surf.outputsSurface.set_authored(true);
  // IMPORTANT: do NOT author a default diffuseColor when connecting
  pbr.value = surf;
  Prim pbrPrim(pbr);
  matPrim.add_child(std::move(pbrPrim), /*rename=*/true, nullptr);

  // Shader "Image_Texture" (UsdUVTexture)
  Shader tex; tex.name = "Image_Texture"; tex.info_id = kUsdUVTexture;
  UsdUVTexture uvtex;
  uvtex.outputsRgb.set_authored(true);
  uvtex.file = value::AssetPath("./textures/bk.png");
  tex.value = uvtex;
  Prim texPrim(tex);
  matPrim.add_child(std::move(texPrim), /*rename=*/true, nullptr);

  // Shader "uvmap" (UsdPrimvarReader_float2)
  Shader uv; uv.name = "uvmap"; uv.info_id = kUsdPrimvarReader_float2;
  UsdPrimvarReader_float2 stnode;
  stnode.result.set_authored(true);
  stnode.varname.set_value(std::string("st"));
  uv.value = stnode;
  Prim uvPrim(uv);
  matPrim.add_child(std::move(uvPrim), /*rename=*/true, nullptr);

  // Put Material under /Materials and commit to stabilize paths
  // (re-fetch scope since we moved it into Stage)
  Prim *materials = nullptr;
  for (auto &r : stage.root_prims()) if (r.element_name() == "Materials") materials = &r;
  materials->add_child(std::move(matPrim), /*rename=*/true, nullptr);
  stage.commit();

  // Resolve children
  Prim &addedMat = materials->children().back();
  Prim *pPrincipled=nullptr, *pTex=nullptr, *pUvmap=nullptr;
  for (auto &ch : addedMat.children()) {
    if (const Shader* s = ch.as<Shader>()) {
      if (s->info_id == kUsdPreviewSurface)       pPrincipled = &ch;
      else if (s->info_id == kUsdUVTexture)       pTex        = &ch;
      else if (s->info_id == kUsdPrimvarReader_float2) pUvmap  = &ch;
    }
  }

  // Hook Material.outputs:surface -> Principled_BSDF.outputs:surface
  if (pPrincipled) {
    Material mm = *addedMat.as<Material>();
    mm.surface.set(Path(pPrincipled->absolute_path().full_path_name(), "outputs:surface"));
    addedMat.set_primdata(addedMat.element_name(), mm);
  }

  // inputs:st.connect (works)
  if (pTex && pUvmap) {
    Shader texS = *pTex->as<Shader>();
    Relationship r; r.set(Path(pUvmap->absolute_path().full_path_name(), "outputs:result"));
    texS.props["inputs:st.connect"] = Property(r);
    pTex->set_primdata(pTex->element_name(), texS);
  }

  // inputs:diffuseColor.connect (DOES NOT SERIALIZE)

  // A) Typed-attribute way (expected to work, but currently does not)
  if (pPrincipled && pTex) {
    Shader pv = *pPrincipled->as<Shader>();
    if (auto *node = pv.value.as<UsdPreviewSurface>()) {
      node->diffuseColor.connect.set(
            Path(pTex->absolute_path().full_path_name(), "outputs:rgb"));
      pv.value = *node;
      pPrincipled->set_primdata(pPrincipled->element_name(), pv);
    }
  }

  // // B) Props way (also does not serialize for UsdPreviewSurface)
  // if (pPrincipled && pTex) {
  //   Shader pv = *pPrincipled->as<Shader>();
  //   Relationship r; r.set(Path(pTex->absolute_path().full_path_name(), "outputs:rgb"));
  //   pv.props["inputs:diffuseColor.connect"] = Property(r);
  //   pPrincipled->set_primdata(pPrincipled->element_name(), pv);
  // }

  stage.commit();

  std::string warn, err;
  usda::SaveAsUSDA("repro.usda", stage, &warn, &err);
  if (!warn.empty()) std::cout << "WARN: " << warn << "\n";
  if (!err.empty())  std::cout << "ERR : " << err << "\n";

  return 0;
}

Actual USDA

def Material "M" {
    token outputs:surface.connect = </Materials/M/Principled_BSDF.outputs:surface>

    def Shader "Principled_BSDF" {
        uniform token info:id = "UsdPreviewSurface"
        token outputs:surface
        // Missing: rel inputs:diffuseColor.connect = </Materials/M/Image_Texture.outputs:rgb>
    }

    def Shader "Image_Texture" {
        uniform token info:id = "UsdUVTexture"
        asset inputs:file = @./textures/bk.png@
        float3 outputs:rgb
    }

    def Shader "uvmap" {
        uniform token info:id = "UsdPrimvarReader_float2"
        string inputs:varname = "st"
        float2 outputs:result
    }
}

Expected behavior / Expected USDA

def Material "M" {
    token outputs:surface.connect = </Materials/M/Principled_BSDF.outputs:surface>

    def Shader "Principled_BSDF" {
        uniform token info:id = "UsdPreviewSurface"
        token outputs:surface
        rel inputs:diffuseColor.connect = </Materials/M/Image_Texture.outputs:rgb>
    }

    def Shader "Image_Texture" {
        uniform token info:id = "UsdUVTexture"
        asset inputs:file = @./textures/bk.png@
        float3 outputs:rgb
    }

    def Shader "uvmap" {
        uniform token info:id = "UsdPrimvarReader_float2"
        string inputs:varname = "st"
        float2 outputs:result
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions