Re: Cycles in the shader graph

Larry Gritz

So, underneath, it's really all flattened to just a simple list of shaders in the group (that's why we sometimes call them "layers"). Connections can only go from outputs of earlier numbered layers to inputs of later numbered layers. Thus, there are no cycles in the graph.

I think I understand what you're getting at here. You don't need the shader to execute cyclically, you just want to, essentially, make a single value supply both an input to one shader node and also supply the default value of the output of another shader (which happens to be later in the layer list).

But you're imaging kind of a special case where it's all simple. In general, there are a lot of complications. For one thing, the value of output parameters (even for their default values) aren't stored in those variables until the node runs. And some parameters get their values in particularly complicated ways (like interpolated vertex values). Also, the order that nodes are evaluated more complex than the flat list implies, because we actually do it lazily (layers are run out of order, if and when only when their results are needed). So it would be a lot of additional logical complexity to allow what you're suggesting -- and ensuring it was correct for all these corner cases.

It feels like... maybe your problem can be handled outside of OSL, at the level where you are specifying the shader group to OSL in the first place? You want the same value to end up a few different places, so maybe there's some logic in the material assignment or something where it can ensure that this happens, without needing to explicitly tell OSL that these nodes are connected in that odd way?

-- lg

On Aug 16, 2021, at 2:35 AM, bbannayan@... wrote:

Consider the following:


Shader A has parameters: diffdiff_tex, and diff_value

Shader B has parameters: valuetex, and output


I'd like to connect in this way:


A.diffuse -> B.value

A.diffuse_tex -> B.tex


B.output -> A.diffuse_value


The A parameters are not "outputs" from the shader.  They are merely parameters with values that I'd like carried forward to B so that the output can be calculated and sent back to A.


The OSL code of A references only the diff_value parameter so there's no actual cycle when you get down to the final evaluation.


Something like this:


A(float diff = 1,

  string diff_tex = "",

  float diff_value = 1)


  Ci = diff_value * diffuse(N);




B(float value = 1,

  string tex = "",

  output float out = 1,

  float st[2] = { 0.0, 0.0 })


  out = value * texture(tex, st[0], st[1]);



The idea for me is that I can have the B shader doing some work but I only ever have to interact with the parameters of A when editing my scene (I'm doing this in a renderer that allows modifying the parameters of shaders during a render).  In my particular case A represents a node in my DCC scene and B is a convenience/implementation detail. So when my DCC says "A.diff" has been changed I can change "A.diff" in my render scene without having to figure out if B exists.


Larry Gritz

Join to automatically receive all group messages.