Houdini 20.0 Reference

Expression cookbook

Tips and tricks for writing expressions to accomplish various effects.

On this page


In Houdini, you can use expressions in parameters and in VEX snippets to accomplish complex and interesting effects with just a bit of math. This page demonstrates a few useful formulas and tricks to use in expressions.

  • See expressions for the basics of HScript expressions. See VEX for more about the VEX language.

  • On this page the expressions listed often have ch() functions to access values from parameters. See spare parameters for how to set up custom parameters your expressions can use.

  • Future versions of Houdini will move toward having users use VEX to modify geometry instead of allowing HScript expressions to modify local variables, because VEX is much faster.

Channel lookups


Hscript expression
















Equivalencies and differences



Current frame

$FF or @Frame


Current time

$T or @Time


Bounding box


relbbox(0,@P).x, relbbox(0,@P).y, relbbox(0,@P).z



vector cent = getpointbbox_center(0);
// cent.x, cent.y, cent.z



vector size = getbbox_size(0);
// size.x, size.y, size.z



vector min; vector max;
getbbox(0, min, max);
// min.x, min.y, min.z, max.x, max.y, max.z

Raise to power



Trig functions



You can convert degrees to radians using the radians function.

Random numbers

  • For examples of randomization in HScript expressions and VEX, open $HH/help/files/RandomExample.hip.





rand(@ptnum), rand($F)

random(@ptnum), random(@Frame)

The random number functions always return the same number given the same seed value. This makes “random” values repeatable between playbacks. However, to make sure that different points/particles/objects/frames etc. get different random values, you must vary the seed.

Choosing a random seed

The current frame number ($F) is usually a good seed value. However:

  • If you need random values for sub-frames, use the fractional frame number $FF instead of $F.

  • If you need more than one random value, such as R, G, and B values for a random color, give each call to rand a different seed value by multiplying or adding to $F, for example rgb(@Frame, @Frame * 10, @Frame * 100). Otherwise each call will return the same number and the color will be gray.

  • If you need a random number to span from -X to X, you can use rand(seed) * (2 * X) - X.

  • The random number is in the range 0-1. Use the fit01(n, newmin, newmax) function to map the random number to a different number range.

    The fit10 function is similar but reverses the mapping. For example, fit10(.3, 5, 20) == 15.5.

    The fit(n, oldmin, oldmax, newmin, newmax) is a more general form that lets you map any number from one range to another range. For example, fit(3,1,4,5,20) == 15.

    The fit functions exist in both the HScript expression language and VEX.

Randomizing values across geometry

The following will randomize every primitive color on every frame.

In HScript expressions:

rand(@primnum * 10)
rand(@primnum * 100)


@Cd.r = random(@primnum * @Frame);
@Cd.g = random(@primnum * 10 * @Frame);
@Cd.r = random(@primnum * 100 * @Frame);

Cycling values

  • For examples of cycling values in HScript expressions and VEX, open $HH/help/files/ModulusExample.hip.

The modulus operator a % b is the same in HScript expressions, VEX, and Python. It returns the remainder after dividing a by b. This is very useful because given a value that increases continuously (such as the frame number), you can produce a value that wraps around a range of values.


If you try this with a floating point value, you can get unexpected results. For example, 3.14 % 1 returns 0.14, and 34.999 % 5 returns 4.999.

For example:









$F % 3









  • For examples of ripples in HScript expressions and VEX, open $HH/help/files/RippleExample.hip.

To get mathematical radiating ripples, base the point position on a sin function using the distance of the point from the center of the surface.

Position Y

sin(sqrt(($BBX - 0.5) ^ 2 + ($BBZ - 0.5) ^ 2) * 1080)

To animate this, add a time-based variable to the expression:

Position Y

sin(sqrt(($BBX - 0.5) ^ 2 + ($BBZ - 0.5) ^ 2) * 720 + $F*4)

Arcs, circles, and spirals

  • For examples of ripples in HScript expressions and VEX, open $HH/help/files/ArcExamples.hip.

You can use sin and cos to generate positions along an arc or circular path.

Position X

cos(@ptnum * 2)

Position Z

sin(@ptnum * 2)

(This may be useful for creating interesting effects, however you can often accomplish similar effects by creating arcs and circles with the Circle SOP. For example, you can place items in a circle by creating a polygonal circle and then copying the items to the circle’s points.)

You can create a spiral by increasing the position in the third dimension as you control the other two with sin and cos.


cos(@ptnum * freq) * amplitudeX + offsetX


@ptnum * amplitudeY


sin(@ptnum * freq) * amplitudeZ + offsetZ

Logarithmic spiral in VEX

  • To play with this example, open $HH/help/files/logSpiral.hip.

The example uses channel references to get values from parameters.

// Expose point normals
@N = @N;

// Natural log
float e = 2.718281828;

// Calculate point positions of log spiral
@P.x = chf("a") * pow(e, chf("b") * @ptnum * .001) * sin(@ptnum);
@P.z = chf("a") * pow(e, chf("b") * @ptnum * .001) * cos(@ptnum);

// Calculate general size of each instance
@pscale = chf("sc") * chf("a") * pow(e, chf("b") * @ptnum * .001);

// Look up color table based on point position
@Cd = chramp("color_spectrum", @ptnum/(@numpt-1.0));


  • For examples of using waveforms in HScript expressions and VEX, open $HH/help/files/WaveFormExamples.hip.

Waveforms are very useful for generating mathematical repeating placement, size, or motion.

Step function

A step function takes a continuous input and converts it to an output in discrete steps.

floor(@P.x * freq) * amplitude

Sin wave

  • For examples of sin waves in HScript expressions and VEX, open $HH/help/files/SinFunctionExample.hip.

The sin (and cos) function are useful for creating of all kinds of shapes. You can use the basic sin function to transform a line or surface into an oscillating wave.

The general form for a geometric sin wave is:

sin ( @P.x * frequency ) * amplitude + offset

For wave motion, you could use this expression:

sin ( @Time * frequency ) * amplitude + offset



The basis for the wave: to animate the geometry of the wave, this could be set instead to (@P.x + @Frame).


Controls the number of waves. You could set this to the bounding box position, $BBX, to make the waves more frequent towards the end of the line.


Controls the height of waves. You could set this to the bounding box position, $BBX, to flatten the waves toward the end of the line, or the current frame, @Frame, to make the waves larger as the animation progresses.


Translates the waves “up” or “down”.

Other waveforms

A square wave alternates between two values:

abs(floor(@P.x * freq + offset) % 2 * amplitude))

A sawtooth wave increases and then resets:

@P.x - floor(@P.x)

A triangle wave bounces back and forth linearly:

abs(@P.x * freq % amplitude - 0.5 * amplitude)

Geometric deformations

  • For examples of deformations in HScript expressions and VEX, open $HH/help/files/Deformation_Examples.hip.

You can alter point positions using HScript expressions in the Point SOP, or using VEX in the Attribute Wrangle SOP, to create geometric deformations such as shear, taper, twist, squash, and bend.


You can get the common deformations much more easily through the Twist SOP. However, you can use these expressions if you need to customize or elaborate on the simple deformations.

Remember that the equivalent of $BBX in VEX is relbox(@P).x.

To shear along X:

Pos X

@P.x + $BBY * ch("strength")

To taper along Y:

Pos X

@P.x * (ch("strength") ^ $BBY)

Pos Z

@P.z * (ch("strength") ^ $BBY)

To squash and stretch along Y in HScript:

Scale X

1 / sqrt(ch("sy"))

Scale Y


Scale Z

1 / sqrt(ch("sy"))


v@scale = @scale;
@scale.x = set( 1/sqrt(ch("strength")));
@scale.y = ch("strength");
@scale.z = set(1/sqrt(ch("strength")));
@P.x *= @scale.x;
@P.y *= @scale.y;
@P.z *= @scale.z;

To twist along Y in HScript (note that you use sin in one axis and cos in the other):

Pos X

(@P.x - $CEX) * cos( ch("strength") * ($BBY - 0.5)) - (@P.z - $CEZ) * sin(ch("strength")) * ($BBY - 0.5)) + $CEX

Pos Z

(@P.x - $CEX) * cos( ch("strength") * ($BBY - 0.5)) - (@P.z - $CEZ) * cos(ch("strength")) * ($BBY - 0.5)) + $CEX


v@min = {0.0, 0.0, 0.0};
v@max = {0.0, 0.0, 0.0};
getpointbbox(0, @min, @max);
v@cent = (@max + @min) / 2.0;
f@twistX = cos(radians(chf("strength")) * (relbbox(@P).y - 0.5));
f@twistZ = sin(radians(chf("strength")) * (relbbox(@P).y - 0.5));
@P.x = (@P.x - @cent.x) * @twistX - (@P.z - @cent.z) * @twistZ + @centroid.x;
@P.z = (@P.x - @centroid.x) * @twistZ + (@P.z - @centroid.z) * @twistX + @centroid.z;

To bulge and pinch along Y in HScript:

Pos X

@P.x + (sin($BBY * 180) * (1 / ch("strength"))) - 1) * ($BBX - 0.5)

Pos Z

@P.z + (sin($BBY * 180) * (1 / ch("strength"))) - 1) * ($BBZ - 0.5)


float PI = 3.1415926535897932384;
@P.x += (sin(relbbox(@P).y * PI) * (1.0 / chf("bulge_factor")) - 1.0) *(relbbox(@P).x - 0.5);
@P.z += (sin(relbbox(@P).y * PI) * (1.0 / chf("bulge_factor")) - 1.0) *(relbbox(@P).z - 0.5);

To bend along Y in HScript:

Pos X

@P.x * cos($BBY * ch("strength")) - @P.y * sin($BBY * ch("strength"))

Pos Y

@P.x * sin($BBY * ch("strength")) + @P.y * cos($BBY * ch("strength"))


@P.x *= cos(radians(relbbox(@P).y * ch("strength"))) - @P.y * sin(radians(relbbox(@P).y * ch("bend_factor")));
@P.y *= sin(radians(relbbox(@P).y * ch("strength"))) + @P.y * cos(radians(relbbox(@P).y * ch("bend_factor")));


User interface

  • Menus

    Explains each of the items in the main menus.

  • Viewers

    Viewer pane types.

  • Panes

    Documents the options in various panes.

  • Windows

    Documents the options in various user interface windows.


  • Expression functions

    Expression functions let you compute the value of parameters.

  • Expression cookbook

    Tips and tricks for writing expressions to accomplish various effects.

  • Python scripting

    How to script Houdini using Python and the Houdini Object Model.

  • VEX

    VEX is a high-performance expression language used in many places in Houdini, such as writing shaders.

  • HScript commands

    HScript is Houdini’s legacy scripting language.

  • hwebserver

    Functions and classes for running a web server inside a graphical or non-graphical Houdini session.

Command line

Guru level

Plugin installation

  • Houdini packages

    How to write and combine multiple environment variable definition files for different plug-ins, tools, and add-ons.

Houdini Engine