Closed marwie closed 1 year ago
The material compiles when I remove one of the texcoord usages (both nodes use channel 0 but one is vector2
and one is vector3
)
Here is a minimal material that reproduces the issue above
<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
<standard_surface name="SR_marble1" type="surfaceshader" xpos="6.159420" ypos="-0.568965">
<input name="base" type="float" value="1" />
<input name="base_color" type="color3" nodename="image_color3" />
<input name="specular_roughness" type="float" value="0.1" />
<input name="subsurface" type="float" value="0.4" />
<input name="subsurface_color" type="color3" nodename="image_color4" />
</standard_surface>
<surfacematerial name="Marble_3D" type="material" xpos="8.695652" ypos="0.000000">
<input name="surfaceshader" type="surfaceshader" nodename="SR_marble1" />
</surfacematerial>
<image name="image_color3" type="color3" xpos="3.528986" ypos="-1.241379">
<input name="file" type="filename" value="Tile_Albedo.jpg" />
<input name="texcoord" type="vector2" nodename="texcoord_vector2" />
</image>
<texcoord name="texcoord_vector2" type="vector2" xpos="1.666667" ypos="-1.413793" />
<texcoord name="texcoord_vector3" type="vector3" xpos="0.275362" ypos="1.077586" />
<image name="image_color4" type="color3" xpos="3.485507" ypos="1.905172">
<input name="file" type="filename" value="Tile_Albedo.jpg" />
<input name="texcoord" type="vector2" nodename="swizzle_vector3_vector2" />
</image>
<swizzle name="swizzle_vector3_vector2" type="vector2" xpos="1.637681" ypos="1.767241">
<input name="in" type="vector3" nodename="texcoord_vector3" />
<input name="channels" type="string" value="xy" />
</swizzle>
</materialx>
This is the generated GLSL code snippet:
void main()
{
in VertexData
{
vec3 normalWorld;
vec3 tangentWorld;
vec2 texcoord_0;
vec3 positionWorld;
} vd;
vec3 geomprop_Nworld_out1 = normalize(vd.normalWorld);
vec3 geomprop_Tworld_out1 = normalize(vd.tangentWorld);
vec2 texcoord_vector2_out = vd.texcoord_0;
vec3 texcoord_vector3_out = vd.texcoord_0;
vec3 image_color3_out = vec3(0.0);
Seem we are declaring one stream input (vec2) and then skipping adding in the second (vec3) and then reusing the same stream route. Hence there is a vec2
to vec3
cast.
Adding @niklasharrysson, for thoughts on this.
I'm guessing that a type check is not being performed when determingin whether to create a geomstry stream ShaderNode
?
BTW @marwie, The MaterialX Viewer has more diagnostic functionality as it allows you to do things like dump out the GLSL code (G
key) if case you find this useful.
As suggested offline to avoid this declare unique stream inputs which are type vec3
as a workaround for now.
What happens here is that VariableBlock::add
is called twice, once by each texcoord node, to create the necessary stage variables. The first call obviously wins, and depending on which texture node is first, texcoord_0
gets either a vec3
or vec2
type. Then, each node proceeds to generating code via TexCoordNodeGlsl::emitFunctionCall
, which assigns the output of the node to texcoord_0
, resulting in an error for the node that has the wrong type. It might make sense to either:
I'd be happy to work on this as a first issue for the dev days. If you think that makes sense, please let me know what you think about either solution.
Hi @madmann91,
Thanks a lot for taking a look at this!
I think the choices are:
As you suggest, always keep vec3
and add code to extract a vec2
from vec3
if the lookup is vec2
. (Basically you want to avoid explicit casts again). I like the idea to widen only when necessary.
Keep both a vec2
and a vec3
. This means no code generator changes are required but there needs to be a way to avoid 2 streams having the same name. The published naming convention indicates a renderer can bind to a stream with name of the form: <stream_type>_<stream_number>
. All I can think of is to add an additional qualifier to get something like texcoord_0:2
, texcoord_0:3
. Binding code needs to be updated.
I'm leaning towards 1 since it does not affect integrators.
In this case vec3
->vec2
conversion can be done by:
1a. inserting additional shader code on lookups,
1b. replace/insert a vec3-to-vec2 conversion ShaderNode
instead of a texcoord ShaderNode
. ShaderNode
s only exist for code generation and generators do insert additional nodes as necessary including geometry nodes.
Option 1b allows you to not worry about each shading language's syntax and I think it should be pretty robust. There may be a 1c. but this is all that comes to mind currently :)
If this is okay to work on, it would great if you look at this for dev days. Of course there will be folks around to help out in this area :)
This seems to be related to
texcoord
0 being used for the normalmap as well as the basecolor - I'm still investigating this and will try to reproduce it with a fresh material but for the sake of documentation I'll open an issue here now šTextures
![Tile_Albedo](https://github.com/AcademySoftwareFoundation/MaterialX/assets/5083203/17b6f8f0-9b64-468c-aa53-05ff758d97a2) ![Tile_Normal](https://github.com/AcademySoftwareFoundation/MaterialX/assets/5083203/8f66cff8-8416-4bea-9eef-f6708e6d8108)