Issue
In shader generation when there are 2 or more nodes with the same name at different scopes, only first node appears appears to output
it's corresponding function and inputs.
AFAIK this is supposed to be fixed but no longer appears to be the case so marking it as a regression when tested
with main with SHA c23f7ef.
Test Example
- Input without duplicates
<?xml version="1.0"?>
<materialx version="1.39">
<nodegraph name="nodegraph1" xpos="-0.594203" ypos="3.172414">
<image name="myimage" type="color3" xpos="4.369565" ypos="-0.827586">
<input name="file" type="filename" value="D:\Work\materialx\bernard_MaterialX\resources\Images\brass_color.jpg" />
</image>
<output name="output_color3" type="color3" nodename="myimage" xpos="9.884058" ypos="1.500000" />
</nodegraph>
<image name="myimage2" type="color3" xpos="-0.876812" ypos="6.344828">
<input name="file" type="filename" value="D:\Work\materialx\bernard_MaterialX\resources\Images\cloth.png" fileprefix="" />
</image>
<burn name="burn_color3" type="color3" xpos="5.246377" ypos="2.344828">
<input name="fg" type="color3" output="output_color3" nodegraph="nodegraph1" />
<input name="bg" type="color3" nodename="myimage2" />
</burn>
<surface_unlit name="surface_unlit" type="surfaceshader" xpos="9.956522" ypos="2.344828">
<input name="emission_color" type="color3" nodename="burn_color3" />
</surface_unlit>
<surfacematerial name="surfacematerial" type="material" xpos="15.855072" ypos="2.896552">
<input name="surfaceshader" type="surfaceshader" nodename="surface_unlit" />
</surfacematerial>
</materialx>
and corresponding OSL created using generateshader script:
#include "mx_funcs.h"
#define true 1
#define false 0
struct textureresource { string filename; string colorspace; };
#define BSDF closure color
#define EDF closure color
#define VDF closure color
struct surfaceshader { closure color bsdf; closure color edf; float opacity; };
#define volumeshader closure color
#define displacementshader vector
#define lightshader closure color
#define MATERIAL closure color
#define M_FLOAT_EPS 1e-8
closure color null_closure() { closure color null_closure = 0; return null_closure; }
vector2 mx_transform_uv(vector2 texcoord)
{
return texcoord;
}
void mx_image_color3(textureresource file, string layer, color default_value, vector2 texcoord, string uaddressmode, string vaddressmode, string filtertype, string framerange, int frameoffset, string frameendaction, output color out)
{
if (file.filename == "" ||
(uaddressmode == "constant" && (texcoord.x<0.0 || texcoord.x>1.0)) ||
(vaddressmode == "constant" && (texcoord.y<0.0 || texcoord.y>1.0)))
{
out = default_value;
return;
}
color missingColor = default_value;
vector2 st = mx_transform_uv(texcoord);
out = texture(file.filename, st.x, st.y,
"subimage", layer, "interp", filtertype,
"missingcolor", missingColor,
"swrap", uaddressmode, "twrap", vaddressmode
#if (OSL_VERSION_MAJOR == 1 && OSL_VERSION_MINOR >= 14) || (OSL_VERSION_MAJOR > 1)
, "colorspace", file.colorspace
#endif
);
}
void mx_burn_float(float fg, float bg, float mix, output float result)
{
if (abs(fg) < M_FLOAT_EPS)
{
result = 0.0;
return;
}
result = mix*(1.0 - ((1.0 - bg) / fg)) + ((1.0-mix)*bg);
}
void mx_burn_color3(color fg, color bg, float mix, output color result)
{
mx_burn_float(fg[0], bg[0], mix, result[0]);
mx_burn_float(fg[1], bg[1], mix, result[1]);
mx_burn_float(fg[2], bg[2], mix, result[2]);
}
void mx_surface_unlit(float emission_weight, color emission_color, float transmission_weight, color transmission_color, float opacity, output surfaceshader result)
{
float trans = clamp(transmission_weight, 0.0, 1.0);
result.bsdf = trans * transmission_color * transparent();
result.edf = (1.0 - trans) * emission_weight * emission_color * emission();
result.opacity = clamp(opacity, 0.0, 1.0);
}
void mx_surfacematerial(surfaceshader surface, surfaceshader back, displacementshader disp, output MATERIAL result)
{
float opacity_weight = clamp(surface.opacity, 0.0, 1.0);
result = (surface.bsdf + surface.edf) * opacity_weight + transparent() * (1.0 - opacity_weight);
}
shader surfacematerial
[[
string mtlx_category = "surfacematerial",
string mtlx_name = "surfacematerial"
]]
(
surfaceshader backsurfaceshader = { 0, 0, 1.0 },
displacementshader displacementshader1 = vector(0.0),
int geomprop_UV0_index = 0
[[
string widget = "number"
]],
string myimage_file = "D:\Work\materialx\bernard_MaterialX\resources\Images\brass_color.jpg"
[[
string widget = "filename"
]],
string myimage_file_colorspace = ""
[[
string widget = "colorspace"
]],
string myimage_layer = "",
color myimage_default = color(0.000000, 0.000000, 0.000000),
string myimage_uaddressmode = "periodic",
string myimage_vaddressmode = "periodic",
string myimage_filtertype = "linear",
string myimage_framerange = "",
int myimage_frameoffset = 0
[[
string widget = "number"
]],
string myimage_frameendaction = "constant",
string myimage2_file = "D:\Work\materialx\bernard_MaterialX\resources\Images\cloth.png"
[[
string widget = "filename"
]],
string myimage2_file_colorspace = ""
[[
string widget = "colorspace"
]],
string myimage2_layer = "",
color myimage2_default = color(0.000000, 0.000000, 0.000000),
string myimage2_uaddressmode = "periodic",
string myimage2_vaddressmode = "periodic",
string myimage2_filtertype = "linear",
string myimage2_framerange = "",
int myimage2_frameoffset = 0
[[
string widget = "number"
]],
string myimage2_frameendaction = "constant",
float burn_color3_mix = 1.000000
[[
string widget = "number"
]],
float surface_unlit_emission = 1.000000
[[
string widget = "number"
]],
float surface_unlit_transmission = 0.000000
[[
string widget = "number"
]],
color surface_unlit_transmission_color = color(1.000000, 1.000000, 1.000000),
float surface_unlit_opacity = 1.000000
[[
string widget = "number"
]],
output MATERIAL out = 0
)
{
textureresource myimage_file_ = {myimage_file, myimage_file_colorspace};
textureresource myimage2_file_ = {myimage2_file, myimage2_file_colorspace};
vector2 geomprop_UV0_out1 = vector2(u,v);
color myimage_out = color(0.0);
mx_image_color3(myimage_file_, myimage_layer, myimage_default, geomprop_UV0_out1, myimage_uaddressmode, myimage_vaddressmode, myimage_filtertype, myimage_framerange, myimage_frameoffset, myimage_frameendaction, myimage_out);
color myimage2_out = color(0.0);
mx_image_color3(myimage2_file_, myimage2_layer, myimage2_default, geomprop_UV0_out1, myimage2_uaddressmode, myimage2_vaddressmode, myimage2_filtertype, myimage2_framerange, myimage2_frameoffset, myimage2_frameendaction, myimage2_out);
color burn_color3_out = color(0.0);
mx_burn_color3(myimage_out, myimage2_out, burn_color3_mix, burn_color3_out);
surfaceshader surface_unlit_out = surfaceshader(null_closure(), null_closure(), 1.0);
mx_surface_unlit(surface_unlit_emission, burn_color3_out, surface_unlit_transmission, surface_unlit_transmission_color, surface_unlit_opacity, surface_unlit_out);
MATERIAL surfacematerial_out = null_closure();
mx_surfacematerial(surface_unlit_out, backsurfaceshader, displacementshader1, surfacematerial_out);
out = surfacematerial_out;
}
- Input document with duplicates:
<?xml version="1.0"?>
<materialx version="1.39">
<nodegraph name="nodegraph1" xpos="-0.594203" ypos="3.172414">
<image name="myimage" type="color3" xpos="4.369565" ypos="-0.827586">
<input name="file" type="filename" value="D:\Work\materialx\bernard_MaterialX\resources\Images\brass_color.jpg" />
</image>
<output name="output_color3" type="color3" nodename="myimage" xpos="9.884058" ypos="1.500000" />
</nodegraph>
<image name="myimage" type="color3" xpos="-0.876812" ypos="6.344828">
<input name="file" type="filename" value="D:\Work\materialx\bernard_MaterialX\resources\Images\cloth.png" fileprefix="" />
</image>
<burn name="burn_color3" type="color3" xpos="5.246377" ypos="2.344828">
<input name="fg" type="color3" output="output_color3" nodegraph="nodegraph1" />
<input name="bg" type="color3" nodename="myimage" />
</burn>
<surface_unlit name="surface_unlit" type="surfaceshader" xpos="9.956522" ypos="2.344828">
<input name="emission_color" type="color3" nodename="burn_color3" />
</surface_unlit>
<surfacematerial name="surfacematerial" type="material" xpos="15.855072" ypos="2.896552">
<input name="surfaceshader" type="surfaceshader" nodename="surface_unlit" />
</surfacematerial>
</materialx>
with corresponding OSL output
#include "mx_funcs.h"
#define true 1
#define false 0
struct textureresource { string filename; string colorspace; };
#define BSDF closure color
#define EDF closure color
#define VDF closure color
struct surfaceshader { closure color bsdf; closure color edf; float opacity; };
#define volumeshader closure color
#define displacementshader vector
#define lightshader closure color
#define MATERIAL closure color
#define M_FLOAT_EPS 1e-8
closure color null_closure() { closure color null_closure = 0; return null_closure; }
vector2 mx_transform_uv(vector2 texcoord)
{
return texcoord;
}
void mx_image_color3(textureresource file, string layer, color default_value, vector2 texcoord, string uaddressmode, string vaddressmode, string filtertype, string framerange, int frameoffset, string frameendaction, output color out)
{
if (file.filename == "" ||
(uaddressmode == "constant" && (texcoord.x<0.0 || texcoord.x>1.0)) ||
(vaddressmode == "constant" && (texcoord.y<0.0 || texcoord.y>1.0)))
{
out = default_value;
return;
}
color missingColor = default_value;
vector2 st = mx_transform_uv(texcoord);
out = texture(file.filename, st.x, st.y,
"subimage", layer, "interp", filtertype,
"missingcolor", missingColor,
"swrap", uaddressmode, "twrap", vaddressmode
#if (OSL_VERSION_MAJOR == 1 && OSL_VERSION_MINOR >= 14) || (OSL_VERSION_MAJOR > 1)
, "colorspace", file.colorspace
#endif
);
}
void mx_burn_float(float fg, float bg, float mix, output float result)
{
if (abs(fg) < M_FLOAT_EPS)
{
result = 0.0;
return;
}
result = mix*(1.0 - ((1.0 - bg) / fg)) + ((1.0-mix)*bg);
}
void mx_burn_color3(color fg, color bg, float mix, output color result)
{
mx_burn_float(fg[0], bg[0], mix, result[0]);
mx_burn_float(fg[1], bg[1], mix, result[1]);
mx_burn_float(fg[2], bg[2], mix, result[2]);
}
void mx_surface_unlit(float emission_weight, color emission_color, float transmission_weight, color transmission_color, float opacity, output surfaceshader result)
{
float trans = clamp(transmission_weight, 0.0, 1.0);
result.bsdf = trans * transmission_color * transparent();
result.edf = (1.0 - trans) * emission_weight * emission_color * emission();
result.opacity = clamp(opacity, 0.0, 1.0);
}
void mx_surfacematerial(surfaceshader surface, surfaceshader back, displacementshader disp, output MATERIAL result)
{
float opacity_weight = clamp(surface.opacity, 0.0, 1.0);
result = (surface.bsdf + surface.edf) * opacity_weight + transparent() * (1.0 - opacity_weight);
}
shader surfacematerial
[[
string mtlx_category = "surfacematerial",
string mtlx_name = "surfacematerial"
]]
(
surfaceshader backsurfaceshader = { 0, 0, 1.0 },
displacementshader displacementshader1 = vector(0.0),
int geomprop_UV0_index = 0
[[
string widget = "number"
]],
string myimage_file = "D:\Work\materialx\bernard_MaterialX\resources\Images\brass_color.jpg"
[[
string widget = "filename"
]],
string myimage_file_colorspace = ""
[[
string widget = "colorspace"
]],
string myimage_layer = "",
color myimage_default = color(0.000000, 0.000000, 0.000000),
string myimage_uaddressmode = "periodic",
string myimage_vaddressmode = "periodic",
string myimage_filtertype = "linear",
string myimage_framerange = "",
int myimage_frameoffset = 0
[[
string widget = "number"
]],
string myimage_frameendaction = "constant",
float burn_color3_mix = 1.000000
[[
string widget = "number"
]],
float surface_unlit_emission = 1.000000
[[
string widget = "number"
]],
float surface_unlit_transmission = 0.000000
[[
string widget = "number"
]],
color surface_unlit_transmission_color = color(1.000000, 1.000000, 1.000000),
float surface_unlit_opacity = 1.000000
[[
string widget = "number"
]],
output MATERIAL out = 0
)
{
textureresource myimage_file_ = {myimage_file, myimage_file_colorspace};
vector2 geomprop_UV0_out1 = vector2(u,v);
color myimage_out = color(0.0);
mx_image_color3(myimage_file_, myimage_layer, myimage_default, geomprop_UV0_out1, myimage_uaddressmode, myimage_vaddressmode, myimage_filtertype, myimage_framerange, myimage_frameoffset, myimage_frameendaction, myimage_out);
color myimage_out1 = color(0.0);
mx_image_color3(myimage_file_, myimage_layer, myimage_default, geomprop_UV0_out1, myimage_uaddressmode, myimage_vaddressmode, myimage_filtertype, myimage_framerange, myimage_frameoffset, myimage_frameendaction, myimage_out1);
color burn_color3_out = color(0.0);
mx_burn_color3(myimage_out, myimage_out1, burn_color3_mix, burn_color3_out);
surfaceshader surface_unlit_out = surfaceshader(null_closure(), null_closure(), 1.0);
mx_surface_unlit(surface_unlit_emission, burn_color3_out, surface_unlit_transmission, surface_unlit_transmission_color, surface_unlit_opacity, surface_unlit_out);
MATERIAL surfacematerial_out = null_closure();
mx_surfacematerial(surface_unlit_out, backsurfaceshader, displacementshader1, surfacematerial_out);
out = surfacematerial_out;
}
Here myimage is at different scopes so should create unique shader nodes (which I think it does), but the code generation outputs only the first (I think).
This applies for all languages so is a core generation issue.
Issue
In shader generation when there are 2 or more nodes with the same name at different scopes, only first node appears appears to output
it's corresponding function and inputs.
AFAIK this is supposed to be fixed but no longer appears to be the case so marking it as a regression when tested
with main with SHA c23f7ef.
Test Example
and corresponding OSL created using
generateshaderscript:with corresponding OSL output
Here
myimageis at different scopes so should create unique shader nodes (which I think it does), but the code generation outputs only the first (I think).This applies for all languages so is a core generation issue.