Community
Arnold for Houdini Forum
Rendering with Arnold in Houdini and Solaris using the HtoA plug-in.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

[HtoA-6.1.3.0] Unable to Create Custom VOPs for Shading Subnets

4 REPLIES 4
Reply
Message 1 of 5
mmarengoKAM7M
224 Views, 4 Replies

[HtoA-6.1.3.0] Unable to Create Custom VOPs for Shading Subnets

I need to create custom VOP interfaces for a series of OSL VOPs which are meant to be instantiated inside shading vop nets (i.e: inside `arnold_materialbuilder` instances). Nothing I've tried so far appears to work -- at a minimum, a new VOP type defined with an "any" vopnet mask is not instantiatable inside an Arnold Materialbuilder vopnet, when we would expect it should be. Something is barring the instantiation from happening and producing an `Invalid Node Type Name` error.

 

Now, I can see that Arnold scans the existing .oso files (I don't expose .osl files in $ARNOLD_PLUGIN_PATH; just the compiled .oso files) and manufactures a VOP for each one that it finds during startup, but those wrappers are not sufficient in a lot of cases. Therefore I must be able to construct custom VOP wrappers for some of my OSL shders.

 

Could someone please describe how to go about doing this? (that is: What VOP properties is Arnold inspecting in order to allow/disallow VOP definitions to be instantiated inside arnold_vopnet instances?)

 

Thanks.

4 REPLIES 4
Message 2 of 5

In the latest beta 43 we support this (see below), is that what you're looking for?

 

julianhodgson_0-1657622303635.png

 

Message 3 of 5

Hi Julian,

 

Thanks for the response!

 

Hard to tell exactly, but it would seem, from your picture, that both of those custom HDAs are instances of subnet. If that's the case, then no, that's not what I'm talking about (although custom subnets are good too, of course).

 

What I'm talking about are custom VOPs -- i.e: a hand-rolled VOP, not a subnet containing a collection of existing VOPs). Imagine the mix_rgba1 VOP in your picture, but created by a client, instead of distributed by you guys.

 

The need to create custom VOP interfaces for external "shaders" (OSL, C++, whatever) is super important in a studio.

The auto-generated wrappers that Arnold produces while scanning $ARNOLD_PLUGIN_PATH are not sufficient in many (many) cases, due to the complexity of some of these interfaces, so one must have the ability to define our own. I'd be happy to cite several use-case samples that require this capability if you're interested.

 

Renderman (RfH) and Mantra/Karma do this by allowing any VOP (custom or otherwise) that has the correct netmask to be instantiated within the corresponding shading network (a "material builder" network similar to your Vop/arnold_materialbuilder), but, alas, your arnold_materialbuilder does not (at least as of HtoA-6.1.3.0) allow this.

All of these renderers then do a "scan" of the networks of each active material (same as you do in your .../htoa/material.py lib) in order to extract the shader-command tree into their individual bytestream formats. But here comes the important part, esp. if you're currently working on this topic during beta: When they scan each VOP in the network (regardless of whether it is a "factory" or "custom" VOP), they look at the VOP's type definition (it's "HDA"), and basically proceed as follows:

 

  1. Check if this VOP is marked as being a wrapper for an external shader/program (i.e: it's just a "bag of parameters" to be converted into arguments in a call to some .oso.so, etc). This can be set in the OperatorTypeProperties dialog under Node > External or Procedural Shader and inspected via HOM API.
  2. If it is found to be a wrapper for an external program (per #1 above), then the Shader Name property is inspected (also avail. via HOM API) and interpreted as a subpath -- meaning that it is appended to every location in $ARNOLD_PLUGIN_PATH (in Arnold's case) to see if it resolves to a valid path to an .oso.so, etc. And if it does, then the VOP's parms are interpreted as args to that callable (with variations depending on the renderer).
  3. The subpath interpretation is actually a Renderman thing and I'm not sure if others do this as well, but it is sooooo incredible convenient that I believe should be adopted by all renderers 🙂 -- it basically allows you to organize many (hundreds) of shaders into logical subdirectories of some root... but more on this if you're interested.

Hope that makes sense.

Message 4 of 5

Thanks, I've created HTOA-2021 to look at this.

 

So as I understand it, you want to create a custom VOP HDA, which is effectively a proxy for a compiled OSL shade and the Shader Name in the HDA would correspond to the OSL shader name?

 

This framework could be used to make a proxy for a compiled shader too, although it doesn't sound like that's your use case.

 

If you have an example hip file of how you can see the setup working, that would be useful too.

 

Thanks

Julian

 

Message 5 of 5

Thanks, Julian!

 

So as I understand it, you want to create a custom VOP HDA, which is effectively a proxy for a compiled OSL shade and the Shader Name in the HDA would correspond to the OSL shader name?

 

Correct. The name given in the ShaderName property of the HDA (when the External or Procedural Shader toggle is ON) determines the "file name" (though I'm suggesting that it be interpreted as a subpath instead of just the file name, relative to any one of the entries in $ARNOLD_PLUGIN_PATH) of the callable that the VOP is a wrapper for (.oso or .so)..

 

[EDIT] An important point that I forgot to mention here: There are really good, practical reasons for wanting to decouple the "shader name" (subpath of the callable file mentioned above), from the VOP's type name. This allows you to call the actual compiled shader file something like "bxdf_lambert_1_0_0.so" while presenting it to Houdini as something like "studio::diffuse::1.0.0" (which would be the VOP wrapper's "type name")

 

This framework could be used to make a proxy for a compiled shader too, although it doesn't sound like that's your use case.

Correct. The mechanics are universal in the sense that the "callable" could be any one of the "executable" or "callable" types accepted by Arnold -- in linux, a c++ "shader" would produce an .so file (.dll in Windows), whereas a compiled OSL shader would produce an .oso callable, and so on. The details of parameter introspection for the different types would vary (for example, a .so/.dll usually needs a side-car "parameter description" file in XML or similar format, whereas an .oso is able to provide self-introspection).

 

If you have an example hip file of how you can see the setup working, that would be useful too.

Okay, I'll put something together, except I won't be able to show a mockup of a custom VOP inside an Arnold Material Builder (like you show in your pic upstream, because, well, that's the whole point of this thread 😄

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums