USD: improve I/O of emission color in preview surface

Don't export color if strength is 0, and on import set strength to 1 when
there is a color. This is more important now that the default is color white
and strength 0 in the Principled BSDF.

Ref #99447
Ref #112848
This commit is contained in:
Brecht Van Lommel 2023-09-25 19:24:18 +02:00
parent 3d38b51435
commit a469640861
3 changed files with 39 additions and 14 deletions

@ -464,10 +464,16 @@ void USDMaterialReader::set_principled_node_inputs(bNode *principled,
set_node_input(diffuse_input, principled, "Base Color", ntree, column, &context);
}
float emission_strength = 0.0f;
if (pxr::UsdShadeInput emissive_input = usd_shader.GetInput(usdtokens::emissiveColor)) {
set_node_input(emissive_input, principled, "Emission Color", ntree, column, &context);
if (set_node_input(emissive_input, principled, "Emission Color", ntree, column, &context)) {
emission_strength = 1.0f;
}
}
bNodeSocket *emission_strength_sock = nodeFindSocket(principled, SOCK_IN, "Emission Strength");
((bNodeSocketValueFloat *)emission_strength_sock->default_value)->value = emission_strength;
if (pxr::UsdShadeInput specular_input = usd_shader.GetInput(usdtokens::specularColor)) {
set_node_input(specular_input, principled, "Specular Tint", ntree, column, &context);
}
@ -503,7 +509,7 @@ void USDMaterialReader::set_principled_node_inputs(bNode *principled,
}
}
void USDMaterialReader::set_node_input(const pxr::UsdShadeInput &usd_input,
bool USDMaterialReader::set_node_input(const pxr::UsdShadeInput &usd_input,
bNode *dest_node,
const char *dest_socket_name,
bNodeTree *ntree,
@ -511,13 +517,13 @@ void USDMaterialReader::set_node_input(const pxr::UsdShadeInput &usd_input,
NodePlacementContext *r_ctx) const
{
if (!(usd_input && dest_node && r_ctx)) {
return;
return false;
}
if (usd_input.HasConnectedSource()) {
/* The USD shader input has a connected source shader. Follow the connection
* and attempt to convert the connected USD shader to a Blender node. */
follow_connection(usd_input, dest_node, dest_socket_name, ntree, column, r_ctx);
return follow_connection(usd_input, dest_node, dest_socket_name, ntree, column, r_ctx);
}
else {
/* Set the destination node socket value from the USD shader input value. */
@ -525,41 +531,46 @@ void USDMaterialReader::set_node_input(const pxr::UsdShadeInput &usd_input,
bNodeSocket *sock = nodeFindSocket(dest_node, SOCK_IN, dest_socket_name);
if (!sock) {
std::cerr << "ERROR: couldn't get destination node socket " << dest_socket_name << std::endl;
return;
return false;
}
pxr::VtValue val;
if (!usd_input.Get(&val)) {
std::cerr << "ERROR: couldn't get value for usd shader input "
<< usd_input.GetPrim().GetPath() << std::endl;
return;
return false;
}
switch (sock->type) {
case SOCK_FLOAT:
if (val.IsHolding<float>()) {
((bNodeSocketValueFloat *)sock->default_value)->value = val.UncheckedGet<float>();
return true;
}
else if (val.IsHolding<pxr::GfVec3f>()) {
pxr::GfVec3f v3f = val.UncheckedGet<pxr::GfVec3f>();
float average = (v3f[0] + v3f[1] + v3f[2]) / 3.0f;
((bNodeSocketValueFloat *)sock->default_value)->value = average;
return true;
}
break;
case SOCK_RGBA:
if (val.IsHolding<pxr::GfVec3f>()) {
pxr::GfVec3f v3f = val.UncheckedGet<pxr::GfVec3f>();
copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, v3f.data());
return true;
}
break;
case SOCK_VECTOR:
if (val.IsHolding<pxr::GfVec3f>()) {
pxr::GfVec3f v3f = val.UncheckedGet<pxr::GfVec3f>();
copy_v3_v3(((bNodeSocketValueVector *)sock->default_value)->value, v3f.data());
return true;
}
else if (val.IsHolding<pxr::GfVec2f>()) {
pxr::GfVec2f v2f = val.UncheckedGet<pxr::GfVec2f>();
copy_v2_v2(((bNodeSocketValueVector *)sock->default_value)->value, v2f.data());
return true;
}
break;
default:
@ -568,9 +579,11 @@ void USDMaterialReader::set_node_input(const pxr::UsdShadeInput &usd_input,
break;
}
}
return false;
}
void USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
bool USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
bNode *dest_node,
const char *dest_socket_name,
bNodeTree *ntree,
@ -578,7 +591,7 @@ void USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
NodePlacementContext *r_ctx) const
{
if (!(usd_input && dest_node && dest_socket_name && ntree && r_ctx)) {
return;
return false;
}
pxr::UsdShadeConnectableAPI source;
@ -588,20 +601,20 @@ void USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
usd_input.GetConnectedSource(&source, &source_name, &source_type);
if (!(source && source.GetPrim().IsA<pxr::UsdShadeShader>())) {
return;
return false;
}
pxr::UsdShadeShader source_shader(source.GetPrim());
if (!source_shader) {
return;
return false;
}
pxr::TfToken shader_id;
if (!source_shader.GetShaderId(&shader_id)) {
std::cerr << "ERROR: couldn't get shader id for source shader "
<< source_shader.GetPrim().GetPath() << std::endl;
return;
return false;
}
/* For now, only convert UsdUVTexture and UsdPrimvarReader_float2 inputs. */
@ -635,6 +648,8 @@ void USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input,
convert_usd_primvar_reader_float2(
source_shader, source_name, dest_node, dest_socket_name, ntree, column + 1, r_ctx);
}
return true;
}
void USDMaterialReader::convert_usd_uv_texture(const pxr::UsdShadeShader &usd_shader,

@ -95,7 +95,7 @@ class USDMaterialReader {
const pxr::UsdShadeShader &usd_shader) const;
/** Convert the given USD shader input to an input on the given Blender node. */
void set_node_input(const pxr::UsdShadeInput &usd_input,
bool set_node_input(const pxr::UsdShadeInput &usd_input,
bNode *dest_node,
const char *dest_socket_name,
bNodeTree *ntree,
@ -106,7 +106,7 @@ class USDMaterialReader {
* Follow the connected source of the USD input to create corresponding inputs
* for the given Blender node.
*/
void follow_connection(const pxr::UsdShadeInput &usd_input,
bool follow_connection(const pxr::UsdShadeInput &usd_input,
bNode *dest_node,
const char *dest_socket_name,
bNodeTree *ntree,

@ -157,8 +157,18 @@ static void create_usd_preview_surface_material(const USDExporterContext &usd_ex
}
const InputSpec &input_spec = it->second;
bNodeLink *input_link = traverse_channel(sock, SH_NODE_TEX_IMAGE);
if (bNodeLink *input_link = traverse_channel(sock, SH_NODE_TEX_IMAGE)) {
if (input_spec.input_name == usdtokens::emissive_color) {
/* Don't export emission color if strength is zero. */
bNodeSocket *emission_strength_sock = nodeFindSocket(node, SOCK_IN, "Emission Strength");
if (!input_link &&
((bNodeSocketValueFloat *)emission_strength_sock->default_value)->value == 0.0f) {
continue;
}
}
if (input_link) {
/* Convert the texture image node connected to this input. */
bNode *input_node = input_link->fromnode;
pxr::UsdShadeShader usd_shader = create_usd_preview_shader(