Skip to content


Haven't looked at this section in a while, needs to be re-written. If you have the time, watch the first section of the webinar I did with sidefx, it gives a better overview than this does, start about 10 minutes in:

Houdini Vops

You might have dabbled in Houdini before, followed some tutorials, and thought 'ok, interesting, but whats the point?'. I'll tell you the point, it's Vops.

But what are vops? Why are vops? A few glib one liners depending on your background:

  • Vops are a node based shading network, but as well as describing surfaces, they can also deform, create and destroy geometry
  • Vops are a node based way to create create fast multithreaded plugins
  • Vops are a visual programming interface
  • Vops are like XSI's ICE, but more general in scope
  • Vops are like expresso in C4D, but better (I think, never really used it)
  • Vops are a wrapper around Vex, which is similar to RSL, which if you know either of those acronyms you shouldn't be reading this beginners guide.

Vops vs other packages

In maya, a classic case that comes up all the time is a noise deformer (ie, move every vertex on a mesh by a procedural noise function). Everyone expects it to be there, and everyone is surprised when they find it doesn't exist.

There's several solutions.

  1. Convert to soft body, write a per particle expression
  2. Write a plugin using the python API
  3. Write a plugin using the C++ API
  4. Download a plugin.

The problem is that using python or particles won't be multithreaded, so you'll hit performance bottlenecks quickly, and a plugin, unless carefully written, won't be hugely versatile. Futher, whatever work you do is specific to this context (pushing verts around), it can't be easily transferred to other geometry types or other domains of maya.

Vops, like XSI's ICE, is visual programming environment. Unlike python, it's multithreaded, unlike C++ it's easy to learn. Under the hood it uses its own compiler (vcc) to compile stuff to fast multithreaded machine code on the fly; when you're within a VOP network it recompiles each time you make a change to the network, which might incur a 0.1 second delay as it compiles. If you're outside the network, it doesn't try to recompile, and is fast fast fast.

Because of the core behavior of Houdini that 'everything is points', it means you can design a VOP network and use it on just about anything. Poly shapes, nurbs curves, particles, voxels, it doesn't matter. Further, because the geometry networks (VOPs) and shading networks (SHOPs) are so similar, you can often just copy paste your network over, and hey presto, its a shader. The only difference being that rather than operating on geometry points, its operating on micropolys, or shading points. This is a powerful thing!

It's worth pressing this point; an acronym that get thrown around for SL and VOPs (and it's underlying language VEX) is SIMD: 'Single Instruction Multiple Data'. For a render engine like renderman or mantra to run efficiently, it has to be able to shade many samples simultaneously. Because all the samples sharing a material are essentially running the same little program, SIMD structures the machine code so that a given operation (single instruction) can be run across lots of points at once (multiple data). The more CPU cores you have, the more you benefit from this.

The nice thing about VOPs/ICE/Fabric Engine is that they expose this performance for processing geometry, not just shaders, and wrap it in a nice GUI.

Simple example

Demo file here: vopsop_example.hipnc

To make this yourself, create some geo, dive into its sop network if you're not there already, append a 'point vop', dive inside.

In a fresh VOP network, you get a list of default input parameters and default output parameters. The defaults are normally expressed in terms of point attributes, which if you've used renderman or arnold or nuke, should be familiar. A point has a position (P), an id (ptnum), maybe a normal (N), a colour (Cd), and whatever other attributes you might have added.

So to start with, you might want to preview what a comp P-pass would look like on your geometry. You can simply connect P on the inputs to Cd on the outputs. Tada, your geometry is now coloured like a P-pass.

Similarly, you could preview a normals pass by connecting N to Cd.

But that's lame. Say you want to do the noise deformer like before. Well, VOPs has a rich set of nodes to play with, including many noise generators. You could drive a noise function with P, and add that to the original position. In code form, P = P+noise(P)

That in itself is ok, but what's interesting is how well it scales. Feed it 100 points, or 1000 points or 100,000 points, it'll play in near realtime. That's the advantage of VOPs vs protoyping in maya and python; high performance is there right from the start.

The pointcount overlay doesn't appear in this screengrab, but I go from 6,468 points, to 82,500, to 316,932, and Houdini smoothly degrades in performance. The lag as I increase the point count is from the upstream nodes calculating the new geometry; once that's done the vopsop performs quickly and smoothly.

What else can it do?

Lots. VOPs is a gui front end to VEX (hence the name; Vex Operators), which is a programming language similar to renderman's SL. If you've glimpsed at renderman shaders you'll recognise a lot of what VEX covers, eg noise functions, reading images, point clouds, vector manipulation. But it goes beyond SL in that it can also create and delete geometry, so you could write a vop network that procedurally grows curves, or polys, or eats away at a mesh. Also, unlike hypershade, vops supports node-based versions of common programming flow controls (if/while/for), allowing for quite advanced behavior.

What's nice here is that it's such a good gateway drug into Vex. Learning a programming language can be a daunting task, but messing around with nodes is standard for most 3d artists. VOPs lets you have your cake and eat it; you can hack and slash, plug x into y, bypass something, try out this other thing, really experiment, but still get pretty remarkable performance at the end of it.

Vops vs rest of houdini

A lot of beginner tutorials for houdini, and even some older 'advanced' tutorials, focus on the hscript way of doing things.

Most of the standard SOPs have 'local variables', a bash/tcsh looking thing with dollar signs and capital letters, which are aliases for certain point parameters. Eg, the point id is $PT, the red component might be $CR, the place within the bounding box on Y might be $BBY. These are either referenced directly in simple expressions ('$NY*0.2'), or referenced in bash/mel style expression calls in backticks, the worst offender being stamp: "`stamp(r, '../copy5',1)`*$PT".

Like maya mel and expressions, you get used to it eventually, but it all seemed a little clunky, and frankly, not that much better than just using maya.

Vops changes all that. I find it fast and elegant, and it's now a fun little game where I'll watch a tutorial that uses hscript/local variables, and I'll start thinking about ways to re-write it in vops. You can't do it for everything of course, but it can definitely replace a lot of the more cumbersome older workflows. Anytime you see a point SOP being used, its dying to be done in a vopsop.

I think users coming from other packages should immediately focus on VOPs, as they really fill the hole that is lacking in Maya/Max/C4D.

XSI ICE folk will feel right at home. 😃

Example - transformer cube

Someone on odforce asked how to do the transformers cube, specifically a bunch of cubes that fold up on themselves and disappear. I had a stab using VOPs, was a fun thing to attempt.

Here's the post:

I start with a cube of points (it can take any cloud of points), I tag a few moving points, and execute the following steps in VOPs. Again, the thing to keep in mind is that VOPs runs this in parallel, on all points, on as many CPU cores as you have. That's the key to it's speed.

For every point:

  1. If it's meant to be moving
  2. Find its nearest neighbour (that ideally isn't moving)
  3. Move towards it by a small amount
  4. If it's within a threshold of the neighbour
  5. Delete itself
  6. Mark the neighbour point to now move

If you crack open the scene you'll see there's a few things that differ from a vanilla vopsop. First, its using a 'solver' sop at the top level, this gives you an easy way to access the results of the previous frame. In this case my setup can easily calculate a delta for motion, calculating an absolute position would be a little harder. With a solver, I can just calculate that delta, and add it to the P of the previous frame.

Vop Sop?

Before Houdini13, all these networks were done in 'vopsop' nodes. Now you're meant to use a point vop, or its similarly named bretheren (attributevop, primvop, vertexvop, detailvop). What's the difference?

A vopsop was a specialised kind of vop network that only let you move geometry. An attrib vop is a more generalised vop network where you can move, create or delete geometry. Point/prim/detail vops are all actually just attribute vops, with a nice name, with their mode pre-selected to point/vert/prim/detail.

Because of their limited functionality, vopsops have been depreciated in favour of attrib vops (you'll get a warning on scene load if there's any vopsops in your scene). Vopsop is more fun to say than pointvop, but that's about it.

There's a few minor implementation differences, but for the most part, anything you can do in a vopsop, you can do in a pointvop.

Further learning

There's a great thread on odforce where people are posting gradually more difficult challenges with VOPs, starting easy and progressing. Kim Goosens also has a great bunch of tutorials on youtube.

Noise that always increases with cellnoise vop

Download scene: cellnoise_increasing.hiplc

Often you'll require a value that increases randomly. Usually you'll make a little solver sop for this, so it'll be noise between 0 and 1 varying over time, adding to the value of the previous frame.

Matt Ebb found a clever alternative that doesn't require a solver. He found if you feed an increasing value to a cellnoise vop, and read its center output, that value is random, but always increases.