Home » 3D, Houdini

Writing a VEX shader for Houdini

22 May 2007 98,315 views 18 Comments

Driving the shader from geometry

Having a single shader that we can change parameters on doesn’t seem too flexible. What happens if we want to have multiple objects with different "wrap" amounts? We don’t want to have to create duplicate shaders with different parameter values, one for each object.

Luckily, Houdini has a solution for this. They’re called attributes.

The clever thing is that any parameters exposed to users in your VOP are automatically driven by attributes on geometry that have the same name. So, for example, if we create an attribute called "wrap", the shader will automatically read it and modify the wrap shader parameter for that piece of geometry.

In the first set of steps below, we’ll create a detail attribute on the sphere called "wrap" and use that to drive the shader. Note that a detail attribute is one that exists for the entire object, so we’re setting the wrap parameter on a per object basis. Also note that you won’t be able to preview this in the viewport, you’ll need to actually perform a render with Mantra.

  1. Create a spare "float" parameter on the "sphere" node. Set the "channel" to "wrapval", the "Label" to "Wrap Value", and the "Range" from -0.99 to 5.
  2. Right click on the label of the new "Wrap Value" node and select "Copy Parameter".
  3. Press "i" or <Enter> to step inside the "sphere" node.
  4. Right click on the output of "sphere1" and select "AttribCreate". Set the render and display flag to the new node.
  5. In parameters, set the "Name" to "wrap", the "Class" to "Detail". Right click inside the first "Value" edit field and select "Paste Copied Relative Refs".
  6. Press "u" to step out of the geometry context.
  7. Press Tab. Select "Camera".
  8. In parameters, set the "Resolution" on the "View" tab to 640 by 480. Set the camera to an appropriate view point.
  9. Change the context to "Outputs" (i.e. /out/->).
  10. Press Tab. Select "Mantra".
  11. In parameters, make sure "Camera" is pointing at the camera you just created.
  12. Go back to the "Objects" context.
  13. Render using the new "mantra1" node you just created.
  14. Adjust the "Wrap Value" spare parameter on the sphere object and re-render.

If you duplicate the sphere object (at object level), you’ll be able to individually set the wrap spare parameter value on each of the spheres, which is exactly what we wanted. Below is an image I created by doing exactly that.


In this render, each sphere is a different object andeach has a different wrap value as a Detail attribute.

It is also possible to control the wrap parameter on a per point basis (or primitives, etc.) by applying a point attribute instead. Following the steps below, you’ll assign an expression to a wrap point attribute that will only set the wrap value for the top half of the sphere.

  1. Select the "sphere" node and press "i" or <Enter> to navigate into the node.
  2. In parameters for the "attribcreate1" node, change "Class" to "Point".
  3. change the "Value" expression in the first edit box to "if($BBY>0.5,ch("../wrapval"),0)"
  4. Press "u" to go back up.
  5. Re-render and alter the "Wrap Value" spare parameter to see the result.

Again, if you duplicate the sphere object, you can change the wrap spare parameter on each one. So not only are you setting the wrap parameter on a per object basis, but you’re now exercising control over it on a per point basis too.


In the above image, each sphere has an expression that ignores the wrap effect in the lower half of the sphere, and sets it to a custom value (different for each sphere) for the top half.

Thanks go to all the guys on the Houdini list for their help along the way, and also to Andy Phillips and Nic Pliatsikas at Axis Animation for testing this tutorial out and giving feedback.

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5.00 out of 5)
Loading...

18 Comments »

  • SG said:

    Hi.
    I tried this in h10 but no luck. Any idea what might have to change>?
    thnks.

  • AndyN (author) said:

    Hmmm. No, not off the top of my head. I should probably update this tutorial for version 10 anyway.

    I’ll take a look and get back to you, or you can send me the hip file if you like. I’ll ping you my email address in a sec.

  • SG said:

    Hey – thnks.
    Im pondering over it now. The VOP errors at the moment, may be the inline code, but i have no way of
    error checking it. Im trying nodes instead of code to see if this fixes it.

  • SG said:

    my gaff, its working just fine in H10 – i think i gave the wrap a constant instead of a parameter.
    Useful little vop – thanks.

  • AndyN (author) said:

    Cool, glad you got it working πŸ™‚

  • Danil said:

    Hey guys,

    I could not find this option:
    43. Go to the “Shading” tab of the “sphere” node and use the “+” button of the “SHOP surface” parameter to select the “lightWrap1” shader inside the “shop” branch.

    I have a sphere node selected and i am in Shading where Sampling and Dicing is but i cant find “”+” button of the “SHOP surface” parameter to select the “lightWrap1” shader inside the “shop” branch.” πŸ™

    Any ideas?

  • AndyN (author) said:

    Hi Danil,

    Yep, this tutorial is quite confusing if you’re trying to follow it in the latest version of Houdini.

    The problem is that the interface and method of shader assignment in version 10 has changed. Basically, you need to set up a material with the shader in and assign it to the object on the Material tab of the object. If you’re not sure how to do that yet, then you should probably investigate some other more fundamental tutorials before trying to decipher this one.

    I’ll try and get round to updating this tutorial soon.

    Cheers

    Andy

  • Danil said:

    Hi AndyN,

    Ohhh now i got it πŸ™‚ Thanks for the explanation. Shader is working like a charm, i am actually using Houdini 9 here πŸ™‚ and trying to figure out last few steps from 50, and on.

    Also just wanted to say, very, very and i mean very good tutorial. I have been looking for something like that for god knows how long. This does not get any better that that. I hope to see any tutorials soon πŸ™‚ Maybe something about custom made SSS πŸ™‚

    Thank you.

  • Danil said:

    btw, by any chance do you know what would be the best way to output this as one of AOV in mantra render ?

  • AndyN (author) said:

    I’ve not needed to do that much, but I believe you can just export the parameter from inside the VOP network using a Parameter VOP with it set to Export Always. You can then pick it up from inside the ROP using the image planes.

  • Danil said:

    Hey AndyN.
    One more question, say i want to have light ramp happening only on the edge of the sphere. Like, something that would represent the light coming from the back side of the geo and then use Light Wrap to control how much light gets spieled over. I know it maya it would involved using facing ratio node that would use normal of the geo to figure out what is what.

  • AndyN (author) said:

    I’m not quite sure what you’re after, but you can generate a “facing ratio” value by doing the dot product of the Surface Normal (N) and the Eye Ray Vector (I) both of which you can get from the Global Parameters node inside the VOP network. You can use that to drive a ramp parameter.

  • kerem said:

    Typo?

    “We then create a temporary floating point variable called $t (it could be called anything, I just picked “t”) and take the dot product of L (the incoming eye ray) and N (the normal vector of the surface being shaded).”

    Is not “L” light vector?

  • AndyN (author) said:

    Hi Kerem. Yes, you’re exactly right. I’ve fixed it.

    Thanks for pointing it out.

  • Alex said:

    Hi Andy,

    Great tutorial you’ve written, I like the breakdowns and explanations especially. I know this was written for H9, but I’m using H11.1 and I’m running into a minor problem involving the viewport display of the shader.

    I’ve managed to get the material assigned to the sphere and can see the effect of the light wrap and diffuse color changes if I do a render or render region preview, but I can’t seem to get it to display in the viewport. I added in the OGL render parameters and can get the diffuse color to update, but can’t seem to figure out how to get the light wrap parameter to affect anything in the viewport. I don’t have this VEX shaded mode.

    Any help would be appreciated,
    thanks!
    alex

  • Alex said:

    hi Andy,

    OK, never mind about the previous question after reading the final page about requiring a render to see the effect…

    I was also wondering if this light wrap setting is easy to implement in a PBR shader like the default mantra surface shader in H11. I’m not sure where to insert it, must be somewhere in the surfaceModel?

    thanks
    alex

  • AndyN (author) said:

    Hi Alex,
    Glad you figured it out. Yep, I could do with updating this tutorial, it’s looking a little dated!

    As for the PBR, that’s not something I’ve spent a lot of time looking in to, so I’m probably not the best person to ask. Sorry!

    Cheers,
    Andy

  • Alex said:

    Hi Andy,

    No worries, I posted a question to the sidefx forums and we’ll see if it turns anything up. Some of the PBR stuff isn’t well documented in my opinion.

    thanks again,
    peace
    alex