Howdy everyone! Indie-Pixel here and I wanted to get my blog writing going by beginning to post all my Houdini VEX recipes. This will be an ongoing effort and my goal is to continually add more chapters as I learn more myself! But I do have quite a library of VEX snippets already and so I wanted to begin to post them here. This set of snippets assumes that you already have a basic understanding of the VEX language. If you are new to VEX it is highly recommended that you read through the Intro to VEX post to get acquainted with the language inside of Houdini.
Chapter 1 is all about learning the core foundational VEX snippets that lead to more advanced VEX systems. We are going to cover creating gradient values, how to create new geometry, and finally how to generate vector directions that are useful when modeling procedurally. The snippets found in here will open up so many possibilities for you and your procedural models. So lets get into the snippets and start coding some VEX!
VEX Snippet 1 - Gradients
I find that I need to use this all the time when I am creating new procedural modeling graphs. The idea is that we want to create a normalized range, meaning a value between 0 and 1, using a set of points. This can be done in a few ways. So lets start with a line inside of Houdini. This will keep our first snippet in the 2D world. Once we understand the basic format of the snippet then we will move onto 3D versions of creating a gradient value.
So the first thing you want to do is create a line inside of Houdini. Then, using the parameters for the line, give it a few more points for us to work with. We will need these points to generate the gradient value.
With the line node created as seen in the screenshot above. Add an Attribute Wrangle node and enter the following code into the wrangle node.
float gradient = (float)@ptnum / (float)(@numpt-1);
This will give us a value that goes from 0 to 1 over the amount of points in the line. Meaning each point will have some sort of float value, between 0 and 1, as it approaches the last point in the line. So point 0 will have a value of 0, point 1 will have some value like 0.1, point 2 will be something like 0.2, all the way until we reach the last point, where the value will be 1.
To view our gradient value we can change the gradient variable to an attribute, by removing the float declaration and adding the f@ prefix. This will display the current value for each point in the "Geometry Spreadsheet". This makes it easier to debug your values in VEX. You can change it back to a variable at any moment. The f before the @ symbol means that we are declaring a float type of attribute. So it has a single component. A decimal value.
You should now see a value on each point in the Geometry spreadsheet underneath the gradient name. This value should go from 0 at the start point then to 1 at the end point of the line. We can visualize this in the scene in a couple different ways. We can input the gradient value into the color attribute of each point or we can utilize the visualize node. Lets take a look at both.
In order to pass the gradient value into the point color value we need to add one more line of code. Type in the following VEX code, right below the gradient code in the same wrangle node.
The other way we can visual the gradient value is to use the Visualize Node. I recommend reading the documentation for the Visualize Node.
We can also create a gradient in 3D space by comparing the size of an objects bounding box. To do this in VEX we are going to utilize the getbbox_min(), getbbox_max(), and getbbox_size() functions.
So lets learn a bit about these functions inside of VEX. Before we begin to code, lets setup our scene within Houdini. The best way to play around with these specific methods is to create a box in the scene and give it a few divisions. We will want to be able to visualize the gradient values on the box itself, so we need to have the divisions in order to do so.
Starting with the getbbox_min() function, lets type in the following into a Wrangle node and set the Wrangle node to run over Detail (Only Once).
v@minBox = getbbox_min(0);
This will output the results of the function to the Geometry spreadsheet but just for the Detail class. You can see in the output we are getting the minimum values for the objects bounding box in x, y and z.
With this in mind, go ahead and type in the rest of the different bbox functions and see what kinds of input they give us. You can find out quite a bit of information about the object we are working with, with just these few functions. This is a very powerful snippet in your arsenal of procedural modeling VEX techniques. Try out getbbox_max(0), getbbox_size(0), and getbbox_center(0), functions and take a look at their outputs in the geometry spreadsheet.
Now lets create a gradient from the different bbox functions. Type in the following code, into a wrangle node set to run over points, and view the results.
v@minbox = getbbox_min(0); v@maxbox = getbbox_max(0); float xGradient = fit(@P.x, @minbox.x, @maxbox.x, 0, 1); float yGradient = fit(@P.y, @minbox.y, @maxbox.y, 0, 1); float zGradient = fit(@P.z, @minbox.z, @maxbox.z, 0, 1); @Cd = set(xGradient, yGradient, zGradient);
This gives us the following results. We can now view our different gradients in 3D space. Each gradient defines a gradient from 0 to 1 in the corresponding axis. This means we can now use this data to create masks and falloffs for our procedural modeling.
Both of these techniques provide the base for many types of solutions in procedural modeling. I encourage you to try them out and see how they might help you!
VEX Snippet 2 - Random Numbers
One of the staples of creating Procedural models in Houdini is to add randomization to your systems. This helps make things feel more real. Or at least gives the preception of reality. Learning to create random numbers inside of VEX is something everyone wanting to get into procedural modeling and VEX, should know. So lets take a peak at the basics of creating random numbers with VEX!
Lets start by creating a new Geometry node in the network view. Then inside of that geometry network lets add a grid of points by adding a grid node and setting its type to points.
With the grid of points created lets add a wrangle node and hook it just below the grid. Once done, type the following code into the VEX Expression area of the Attribute Wrangle node.
float randNum = rand(@ptnum);
This will give us a random number between 0 and 1. each time the wrangle node processes a new point, we feed the @ptnum, which is the current number of the point being worked on, into the rand() function. This then returns a new random number for each point in the grid of points. That is the most basic way of generating a random number inside of VEX.
We can take it one step further and add a seed value and also visualize our random number by assigning it to the color property of each point. For this next step it is useful to have the geometry spreadsheet open to further give ourselves an easy way to see the data.
To add a global seed value and to visualize the random number in the color of each point, enter the following code into the VEX Expression window in the Attribute Wrangle node.
float randNum = rand(@ptnum + chf("seed")); @Cd = randNum;
Make sure to hit the "Create Spare Parameters" button to generate the seed value slider. Once completed, you can see that by dragging the seed slider around, you get different results. This is the core idea behind random numbers.
The next item we usually do with random numbers is to remap the range of the 0 to 1 random number. There are many times when we need to take the 0 to 1 range and change it to a different range, for instance 1 to 10.
In VEX we can do this by using the fit01() function. This function takes a number between 0 and 1 and lets us define a new range for that number. Lets take a look at how this is used inside of VEX. Enter the following code into the VEX Expression window in the Attribute Wrangle node.
float randNum = fit01(rand(@ptnum + chf("seed")), 1, 10); f@randNum = randNum;
We can take this even further and let a user of this wrangle node determine the range in which they want to use. Enter the following to get two sliders that will define the Min and Max range for the random number.
float randNum = fit01(rand(@ptnum + chf("seed")), chf("min"), chf("max")); f@randNum = randNum;
Finally we can further visualize the random value by assigning it to the @pscale attribute which is an attribute the Houdini is specifically looking for. Especially when using it with the "Copy To Points" node.
Add a Copy to Points node and a new box node, and wire them up according to how the nodes are hooked up in the following image.
Once hooked up in the correct way, add the following code into the Attribute Wrangle node. This will help us visualize our random number by scaling each copy of the box to a different scale.
float randNum = fit01(rand(@ptnum + chf("seed")), chf("min"), chf("max")); @pscale = randNum;
You can now see how using random numbers can be extremely useful when creating procedural models.
That concludes the fisrt set of VEX snippets! I hope you found the information valuable and informative, or just a good place to reference VEX code. I will be posting new VEX snippets every week, so keep an eye out on Indie-Pixel.com for more VEX tutorials! Thanks so much!