Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vector2 values are not passing through shader connections #1290

Open
ix-nico opened this issue Nov 4, 2020 · 12 comments
Open

vector2 values are not passing through shader connections #1290

ix-nico opened this issue Nov 4, 2020 · 12 comments

Comments

@ix-nico
Copy link
Contributor

ix-nico commented Nov 4, 2020

Hi,

I tried several things and I failed to make vector2 values to pass from a shader to another one when connecting them.
I tried with builtin types like vector and color and it works perfectly. I suppose it is because a vector2 is a structure but I didn't try with similar types like vector4 or color4.

What I'm trying to do actually is to extract UV coordinates via a MaterialX texture node like mx_geompropvalue_vector2 and plug it into an mx_image_color. Am I doing something wrong or is it a bug?

I'm using OSL 1.11.8.0 compiled with LLVM 9.

EDIT: actually, the mx_geompropvalue_vector2 code is not even called. So it's like the connection is ignored whereas we don't get any error while setting it.

Thanks in advance!
Nicolas

@lgritz
Copy link
Collaborator

lgritz commented Nov 5, 2020

Well... what things did you try? Can you give an example showing the serialized shader or what sequence of C++ calls you're making?

@ix-nico
Copy link
Contributor Author

ix-nico commented Nov 5, 2020

Hi Larry,

Let's say I have a simple shader like this:

#include <vector2.h>

surface
shader_test
(
    int mode = 0,
    vector2 vec2 = {0, 0},
    vector vec3 = 0,
    color Cs = 1
  )
{
    color k;
    if (mode == 0) {
        k = color(vec2.x, vec2.y, 0);
    } else if (mode == 1) {
        k = color(vec3[0], vec3[1], vec3[2]);
    } else {
        k = Cs;
    }
    Ci = k * emission();
}

If I create a shader group containing this shader (layer "shader") and a mx_geompropvalue_vector2 (layer "texture") which outputs a vector2 and then I connect them, it doesn't seem to work.
To connect them, I'm doing the following from within the group:
osl_shading_system.ConnectShaders("texture", "out", "shader", "vec2");

I've even tried the following (which is probably dumb but it was worth a try):

osl_shading_system.ConnectShaders("texture", "out.x", "shader", "vec2.x");
osl_shading_system.ConnectShaders("texture", "out.y", "shader", "vec2.y");

But it doesn't work too. In both cases, the ConnectShaders function returns true but the code of mx_geompropvalue_vector2 is never called.

Now, if I replace the texture by a mx_geompropvalue_vector, plug its output into the vec3 param of my shader and set the mode param to 1, it works fine:
osl_shading_system.ConnectShaders("texture", "out", "shader", "vec3");

Is there any information I could check to understand what happens?

Thanks

@lgritz
Copy link
Collaborator

lgritz commented Nov 5, 2020

It looks like you're doing it correctly. I'm reasonably sure this works, we connect structs between shaders all the time.

I'm concerned about this bit:

EDIT: actually, the mx_geompropvalue_vector2 code is not even called. So it's like the connection is ignored whereas we don't get any error while setting it.

Is it possible that the connection is established just fine at shader group setup time, but that the connection is being optimized away (or the entire shader is not being run, as you note) because the results aren't used anywhere? (That kind of contradicts your statement that just changing the type to vector, with everything else being exactly the same, succeeds.)

Is there a way that you can give me a (minimal) reproduction case? Like, can you simulate the problem with a group consisting of 2 shaders, and give me the "serialized" description (see Chapter 9 of the OSL spec) of the connections, so that I can fully reproduce the problem using testshade on my end?

@lgritz
Copy link
Collaborator

lgritz commented Nov 5, 2020

Other things to try to probe at what might be going on: What happens to the behavior if you change the "optimize" attribute of the ShadingSystem to 1 or 0? (default is 2) What about if you set "lazylayers" to 0?

@ix-nico
Copy link
Contributor Author

ix-nico commented Nov 9, 2020

Hi Larry,

Thanks for the tip about the optimze attribute! When I set it to 1, my code is executed and it helped me understand what was going wrong. The MaterialX mx_geompropvalue_vector2 node can't work actually because it calls getattribute() function on the struct (getattribute(attrname, out)) which has an empty description whereas it should be called on each of its components (getattribute(attrname_x, out.x) and getattribute(attrname_y, out.y)).

This also showed me that we were doing the exact same mistake on our side by trying to set values of parameters directly on the struct. This is something that we didn't take into consideration so we'll have to adapt our code accordingly.
Can you just confirm that there's no way of addressing structures directly when setting parameter values?

Thanks a lot for your help!

@lgritz
Copy link
Collaborator

lgritz commented Nov 12, 2020

I'm still not sure what you mean by "addressing structure directly when setting parameter values".

You are right that the argument to getattribute must be a real individual variable, not a struct.

But the other things you wrote, like using ConnectShaders between two struct parameters, ought to work.

@lgritz
Copy link
Collaborator

lgritz commented Nov 12, 2020

Aside: It's on the roadmap to add a real vector2 type to the language at some point soon.

@ix-nico
Copy link
Contributor Author

ix-nico commented Nov 26, 2020

Hi Larry,

Thanks for the reply and sorry to come back to you so late, I've been pretty busy the last 2 weeks.

I'm still not sure what you mean by "addressing structure directly when setting parameter values".

At first, I was trying to set all values of a vector2 with a single call of Parameter function by simply giving OSL::TypeDesc(OSL::TypeDesc::FLOAT, 2) as a type but that is obviously not working.

I modified our code in order to keep the information about the structure so we now have 2 calls to Parameter, one for x and the other for y.

Aside: It's on the roadmap to add a real vector2 type to the language at some point soon.

That's good to know, thanks!

@lgritz
Copy link
Collaborator

lgritz commented Dec 1, 2020

Note that TypeDesc(FLOAT,2) is an array of 2 floats, but vec2 is a different type and is specified as TypeDesc(TypeDesc::FLOAT,TypeDesc::VEC2).

@ix-nico
Copy link
Contributor Author

ix-nico commented Dec 1, 2020

Sorry, my mistake, I'm actually doing this: TypeDesc(TypeDesc::FLOAT, (TypeDesc::AGGREGATE)2, TypeDesc::NOSEMANTICS)
I also tried with TypeDesc::VECTOR for vecsemantics but it doesn't change anything.

@lgritz
Copy link
Collaborator

lgritz commented Dec 1, 2020

No, like I said, vector2 is not actually a type in OSL (yet). For MaterialX, it's implemented as a struct, so you can't use Parameter() to set the value, because it's not one value. You could use Parameter(group, "mystruct.x", xval) and then Parameter(group, "mystruct.y", yval).

@ix-nico
Copy link
Contributor Author

ix-nico commented Dec 2, 2020

Yes, this is what I figured out and what I'm doing now. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants