From 03bc930f81cb667907f511e2154319ccf18e8472 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 10 Jun 2024 06:30:29 +0900 Subject: [PATCH] [tydra] Fix connected texture outputChannel was not considered when constructing tydra::UVTexture. --- models/texture-channel-001.usda | 120 ++++++++++++++++++++++++++++++++ src/tydra/render-data.cc | 77 +++++++++++++++----- src/tydra/render-data.hh | 6 +- src/tydra/usd-export.cc | 24 ++++--- 4 files changed, 195 insertions(+), 32 deletions(-) create mode 100644 models/texture-channel-001.usda diff --git a/models/texture-channel-001.usda b/models/texture-channel-001.usda new file mode 100644 index 00000000..31afe192 --- /dev/null +++ b/models/texture-channel-001.usda @@ -0,0 +1,120 @@ +#usda 1.0 +( + defaultPrim = "root" + doc = "Blender v4.1.1" + metersPerUnit = 1 + upAxis = "Z" +) + +def Xform "root" ( + customData = { + dictionary Blender = { + bool generated = 1 + } + } +) +{ + def Xform "Grid" + { + matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + + def Mesh "Grid_001" ( + prepend apiSchemas = ["MaterialBindingAPI"] + ) + { + uniform bool doubleSided = 1 + float3[] extent = [(-1, -1, 0), (1, 1, 0)] + int[] faceVertexCounts = [4, 4, 4, 4, 4, 4, 4, 4, 4] + int[] faceVertexIndices = [0, 1, 5, 4, 1, 2, 6, 5, 2, 3, 7, 6, 4, 5, 9, 8, 5, 6, 10, 9, 6, 7, 11, 10, 8, 9, 13, 12, 9, 10, 14, 13, 10, 11, 15, 14] + rel material:binding = + normal3f[] normals = [(0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 0.99999994), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)] ( + interpolation = "faceVarying" + ) + point3f[] points = [(-1, -1, 0), (-0.3333333, -1, 0), (0.33333337, -1, 0), (1, -1, 0), (-1, -0.3333333, 0), (-0.3333333, -0.3333333, 0), (0.33333337, -0.3333333, 0), (1, -0.3333333, 0), (-1, 0.33333337, 0), (-0.3333333, 0.33333337, 0), (0.33333337, 0.33333337, 0), (1, 0.33333337, 0), (-1, 1, 0), (-0.3333333, 1, 0), (0.33333337, 1, 0), (1, 1, 0)] + bool[] primvars:sharp_face = [1, 1, 1, 1, 1, 1, 1, 1, 1] ( + interpolation = "uniform" + ) + texCoord2f[] primvars:UVMap = [(0, 0), (0.33333334, 0), (0.33333334, 0.33333334), (0, 0.33333334), (0.33333334, 0), (0.6666667, 0), (0.6666667, 0.33333334), (0.33333334, 0.33333334), (0.6666667, 0), (1, 0), (1, 0.33333334), (0.6666666, 0.33333334), (0, 0.33333334), (0.33333334, 0.33333334), (0.33333334, 0.6666667), (0, 0.6666667), (0.33333334, 0.33333334), (0.6666667, 0.33333334), (0.6666667, 0.6666667), (0.33333334, 0.6666667), (0.6666667, 0.33333334), (1, 0.33333334), (1, 0.6666667), (0.6666666, 0.6666667), (0, 0.6666666), (0.33333334, 0.6666666), (0.33333334, 1), (0, 1), (0.33333334, 0.6666666), (0.6666667, 0.6666666), (0.6666667, 1), (0.33333334, 1), (0.6666667, 0.6666666), (1, 0.6666666), (1, 1), (0.6666666, 1)] ( + interpolation = "faceVarying" + ) + uniform token subdivisionScheme = "none" + } + } + + def Scope "_materials" + { + def Material "Material_001" + { + token outputs:surface.connect = + + def Shader "Principled_BSDF" + { + uniform token info:id = "UsdPreviewSurface" + float inputs:clearcoat = 0 + float inputs:clearcoatRoughness = 0.03 + float inputs:metallic.connect = + float inputs:roughness.connect = + float inputs:ior = 1.5 + float inputs:opacity = 1 + float inputs:specular = 0.5 + token outputs:surface + } + + def Shader "Image_Texture" + { + uniform token info:id = "UsdUVTexture" + asset inputs:file = @./textures/texture-cat.jpg@ + token inputs:sourceColorSpace = "sRGB" + float2 inputs:st.connect = + token inputs:wrapS = "repeat" + token inputs:wrapT = "repeat" + float outputs:b + float outputs:g + } + + def Shader "uvmap" + { + uniform token info:id = "UsdPrimvarReader_float2" + token inputs:varname = "UVMap" + float2 outputs:result + } + } + } + + def Xform "Camera" + { + matrix4d xformOp:transform = ( (0.6859206557273865, 0.7276763319969177, 0, 0), (-0.32401347160339355, 0.305420845746994, 0.8953956365585327, 0), (0.6515582203865051, -0.6141703724861145, 0.44527140259742737, 0), (7.358891487121582, -6.925790786743164, 4.958309173583984, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + + def Camera "Camera" + { + float2 clippingRange = (0.1, 100) + float focalLength = 0.5 + float horizontalAperture = 0.36 + float horizontalApertureOffset = 0 + token projection = "perspective" + float verticalAperture = 0.2025 + float verticalApertureOffset = 0 + } + } + + def Xform "Light" + { + matrix4d xformOp:transform = ( (-0.29086464643478394, 0.9551711678504944, -0.05518905818462372, 0), (-0.7711008191108704, -0.1998833566904068, 0.6045247316360474, 0), (0.5663931965827942, 0.21839119493961334, 0.7946722507476807, 0), (4.076245307922363, 1.0054539442062378, 5.903861999511719, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + + def SphereLight "Light" + { + float3[] extent = [(-0.1, -0.1, -0.1), (0.1, 0.1, 0.1)] + color3f inputs:color = (1, 1, 1) + float inputs:diffuse = 1 + float inputs:exposure = 0 + float inputs:intensity = 318.30988 + bool inputs:normalize = 1 + float inputs:radius = 0.1 + float inputs:specular = 1 + } + } +} + diff --git a/src/tydra/render-data.cc b/src/tydra/render-data.cc index 75c3b1a7..c30a739c 100644 --- a/src/tydra/render-data.cc +++ b/src/tydra/render-data.cc @@ -4190,7 +4190,7 @@ nonstd::expected GetConnectedUVTexture( } if (tex_abs_path) { - (*tex_abs_path) = Path(prim_part, ""); + (*tex_abs_path) = Path(prim_part, prop_part); } if (const Shader *pshader = prim->as()) { @@ -4570,23 +4570,35 @@ bool RenderSceneConverter::ConvertUVTexture(const RenderSceneConverterEnv &env, } // - // Set outputChannel + // Set authored outputChannels // if (texture.outputsRGB.authored()) { - tex.outputChannel = UVTexture::Channel::RGB; - } else if (texture.outputsA.authored()) { - tex.outputChannel = UVTexture::Channel::A; - } else if (texture.outputsR.authored()) { - tex.outputChannel = UVTexture::Channel::R; - } else if (texture.outputsG.authored()) { - tex.outputChannel = UVTexture::Channel::G; - } else if (texture.outputsB.authored()) { - tex.outputChannel = UVTexture::Channel::B; - } else { - PUSH_WARN("No valid output channel attribute authored. Default to RGB"); - tex.outputChannel = UVTexture::Channel::RGB; + tex.authoredOutputChannels.insert(UVTexture::Channel::RGB); } + if (texture.outputsA.authored()) { + tex.authoredOutputChannels.insert(UVTexture::Channel::A); + } + + if (texture.outputsR.authored()) { + tex.authoredOutputChannels.insert(UVTexture::Channel::R); + } + + if (texture.outputsG.authored()) { + tex.authoredOutputChannels.insert(UVTexture::Channel::G); + } + + if (texture.outputsB.authored()) { + tex.authoredOutputChannels.insert(UVTexture::Channel::B); + } + +#if 0 // TODO + if (tex.authoredOutputChannels.empty()) { + PUSH_WARN("No valid output channel attribute authored. Default to RGB"); + tex.authoredOutputChannels.insert(UVTexture::Channel::RGB); + } +#endif + // // Convert other UVTexture parameters // @@ -4753,7 +4765,7 @@ bool RenderSceneConverter::ConvertPreviewSurfaceShaderParam( if (param.is_blocked()) { PUSH_ERROR_AND_RETURN(fmt::format("{} attribute is blocked.", param_name)); } else if (param.is_connection()) { - DCOUT(fmt::format("{] is attribute connection.", param_name)); + DCOUT(fmt::format("{} is attribute connection.", param_name)); const UsdUVTexture *ptex{nullptr}; const Shader *pshader{nullptr}; @@ -4783,13 +4795,32 @@ bool RenderSceneConverter::ConvertPreviewSurfaceShaderParam( "Failed to convert UVTexture connected to {}", param_name)); } + // Extract connected outputChannel from prop part. + std::string prop_part = texPath.prop_part(); + + // TODO: Attribute type check. + if (prop_part == "outputs:r") { + rtex.connectedOutputChannel = tydra::UVTexture::Channel::R; + } else if (prop_part == "outputs:g") { + rtex.connectedOutputChannel = tydra::UVTexture::Channel::G; + } else if (prop_part == "outputs:b") { + rtex.connectedOutputChannel = tydra::UVTexture::Channel::B; + } else if (prop_part == "outputs:a") { + rtex.connectedOutputChannel = tydra::UVTexture::Channel::A; + } else if (prop_part == "outputs:rgb") { + rtex.connectedOutputChannel = tydra::UVTexture::Channel::RGB; + } else { + PUSH_ERROR_AND_RETURN(fmt::format("Unknown or invalid connection to a property of output channel: {}(Abs path {})", prop_part, texPath.full_path_name())); + } + + uint64_t texId = textures.size(); textures.push_back(rtex); textureMap.add(texId, shader_abs_path.prim_part() + "." + param_name); - DCOUT(fmt::format("TexId {} = {}", - shader_abs_path.prim_part() + ".diffuseColor", texId)); + DCOUT(fmt::format("TexId {}.{} = {}", + shader_abs_path.prim_part(), param_name, texId)); dst_param.texture_id = int32_t(texId); @@ -7005,8 +7036,16 @@ std::string DumpUVTexture(const UVTexture &texture, uint32_t indent) { ss << "UVTexture {\n"; ss << pprint::Indent(indent + 1) << "primvar_name " << texture.varname_uv << "\n"; - ss << pprint::Indent(indent + 1) << "outputChannel " - << to_string(texture.outputChannel) << "\n"; + ss << pprint::Indent(indent + 1) << "connectedOutputChannel "; + ss << to_string(texture.connectedOutputChannel) << "\n"; + + ss << pprint::Indent(indent + 1) << "authoredOutputChannels "; + + for (const auto &c : texture.authoredOutputChannels) { + ss << to_string(c) << " "; + } + ss << "\n"; + ss << pprint::Indent(indent + 1) << "bias " << texture.bias << "\n"; ss << pprint::Indent(indent + 1) << "scale " << texture.scale << "\n"; ss << pprint::Indent(indent + 1) << "wrapS " << to_string(texture.wrapS) diff --git a/src/tydra/render-data.hh b/src/tydra/render-data.hh index 1cfab818..f1fddd02 100644 --- a/src/tydra/render-data.hh +++ b/src/tydra/render-data.hh @@ -1011,8 +1011,10 @@ struct UVTexture { vec4 fetch_uvw_channel(size_t faceId, float varyu, float varyv, float varyw, Channel channel); - // output channel info - Channel outputChannel{Channel::RGB}; + // Connected output channel(determined by connectionPath in UsdPreviewSurface) + Channel connectedOutputChannel{Channel::RGB}; + + std::set authoredOutputChannels; // Authored `output:***` attribute in UsdUVTexture // bias and scale for texel value vec4 bias{0.0f, 0.0f, 0.0f, 0.0f}; diff --git a/src/tydra/usd-export.cc b/src/tydra/usd-export.cc index 3e2e80a0..caaab09a 100644 --- a/src/tydra/usd-export.cc +++ b/src/tydra/usd-export.cc @@ -861,17 +861,19 @@ static bool ToMaterialPrim(const RenderScene &scene, const std::string &abs_path } image_tex.wrapT.set_value(wrapS); - if (tex.outputChannel == UVTexture::Channel::R) { - image_tex.outputsR.set_authored(true); - } else if (tex.outputChannel == UVTexture::Channel::G) { - image_tex.outputsG.set_authored(true); - } else if (tex.outputChannel == UVTexture::Channel::B) { - image_tex.outputsB.set_authored(true); - } else if (tex.outputChannel == UVTexture::Channel::RGB) { - image_tex.outputsRGB.set_authored(true); - } else if (tex.outputChannel == UVTexture::Channel::RGBA) { - PUSH_ERROR_AND_RETURN("rgba texture is not supported yet."); - } + for (const auto &c : tex.authoredOutputChannels) { + if (c == UVTexture::Channel::R) { + image_tex.outputsR.set_authored(true); + } else if (c == UVTexture::Channel::G) { + image_tex.outputsG.set_authored(true); + } else if (c == UVTexture::Channel::B) { + image_tex.outputsB.set_authored(true); + } else if (c == UVTexture::Channel::RGB) { + image_tex.outputsRGB.set_authored(true); + } else if (c == UVTexture::Channel::RGBA) { + PUSH_ERROR_AND_RETURN("rgba texture is not supported yet."); + } + } UsdTransform2d uv_xform; uv_xform.name = "place2d_" + param_name;