Fix #96458: Add channel processing for UsdUVTexture

This adds the processing required to import and export simple material graphs utilizing the UsdUVTexture outputs channels.

If only r, g or b are specified as output, we hook up a `Separate Color` node and connect the appropriate channel from there.
(if a is specified as output, the Alpha output of an image texture node was used already)

On the export side, we traverse from the socket to the image texture node, and if a `Separate Color` on the way, we are using the channel from there to put on the output.

https://openusd.org/release/spec_usdpreviewsurface.html#texture-reader

Pull Request: https://projects.blender.org/blender/blender/pulls/117901
This commit is contained in:
Philipp Oeser
2024-02-08 10:01:41 +01:00
committed by Philipp Oeser
parent f9e976c899
commit 228ee8f1c3
2 changed files with 68 additions and 4 deletions

View File

@@ -778,6 +778,37 @@ static IntermediateNode add_scale_bias_adjust(bNodeTree *ntree,
return adjust;
}
static IntermediateNode add_separate_color(const pxr::TfToken &usd_source_name,
bNodeTree *ntree,
int column,
NodePlacementContext *r_ctx)
{
IntermediateNode separate_color{};
if (usd_source_name == usdtokens::r || usd_source_name == usdtokens::g ||
usd_source_name == usdtokens::b)
{
float locx = 0.0f;
float locy = 0.0f;
compute_node_loc(column, &locx, &locy, r_ctx);
separate_color.node = add_node(nullptr, ntree, SH_NODE_SEPARATE_COLOR, locx, locy);
separate_color.sock_input_name = "Color";
if (usd_source_name == usdtokens::r) {
separate_color.sock_output_name = "Red";
}
if (usd_source_name == usdtokens::g) {
separate_color.sock_output_name = "Green";
}
if (usd_source_name == usdtokens::b) {
separate_color.sock_output_name = "Blue";
}
}
return separate_color;
}
bool USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
bNode *dest_node,
const char *dest_socket_name,
@@ -826,6 +857,12 @@ bool USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
shift++;
}
/* Create a Separate Color node if necessary. */
IntermediateNode separate_color = add_separate_color(source_name, ntree, column + shift, r_ctx);
if (separate_color.node) {
shift++;
}
/* Create a Scale-Bias adjustment node if necessary. */
IntermediateNode scale_bias = add_scale_bias(
source_shader, ntree, column + shift, is_normal_map, r_ctx);
@@ -862,11 +899,22 @@ bool USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
link_nodes(ntree, normal_map.node, normal_map.sock_output_name, dest_node, dest_socket_name);
}
else if (scale_bias.node) {
link_nodes(ntree, scale_bias.node, scale_bias.sock_output_name, dest_node, dest_socket_name);
if (separate_color.node) {
link_nodes(ntree, separate_color.node, separate_color.sock_output_name, dest_node, dest_socket_name);
link_nodes(ntree, scale_bias.node, scale_bias.sock_output_name, separate_color.node, separate_color.sock_input_name);
}
else {
link_nodes(ntree, scale_bias.node, scale_bias.sock_output_name, dest_node, dest_socket_name);
}
target_node = scale_bias.node;
target_sock_name = scale_bias.sock_input_name;
shift++;
}
else if (separate_color.node) {
link_nodes(ntree, separate_color.node, separate_color.sock_output_name, dest_node, dest_socket_name);
target_node = separate_color.node;
target_sock_name = separate_color.sock_input_name;
}
convert_usd_uv_texture(source_shader,
source_name,

View File

@@ -211,9 +211,25 @@ static void create_usd_preview_surface_material(const USDExporterContext &usd_ex
/* Create the UsdUVTexture node output attribute that should be connected to this input. */
pxr::TfToken source_name;
if (input_spec.input_type == pxr::SdfValueTypeNames->Float) {
/* If the input is a float, we connect it to either the texture alpha or red channels. */
source_name = STREQ(input_link->fromsock->identifier, "Alpha") ? usdtokens::a :
usdtokens::r;
/* If the input is a float, we check if there is also a Separate Color node in between, if
* there is use the output channel from that, otherwise connect either the texture alpha or
* red channels. */
bNodeLink *input_link_sep_color = traverse_channel(sock, SH_NODE_SEPARATE_COLOR);
if (input_link_sep_color) {
if (STREQ(input_link_sep_color->fromsock->identifier, "Red")) {
source_name = usdtokens::r;
}
if (STREQ(input_link_sep_color->fromsock->identifier, "Green")) {
source_name = usdtokens::g;
}
if (STREQ(input_link_sep_color->fromsock->identifier, "Blue")) {
source_name = usdtokens::b;
}
}
else {
source_name = STREQ(input_link->fromsock->identifier, "Alpha") ? usdtokens::a :
usdtokens::r;
}
usd_shader.CreateOutput(source_name, pxr::SdfValueTypeNames->Float);
}
else {