Generate a realistic sandy terrain in Houdini
Learn how to make natural-looking sand elements using heightfield tools and the Vellum Grain Solver
Kyle Climaco showcases how to produce a natural-looking terrain, while also significantly cutting down on simulation time
In this tutorial, we are going to learn how to use heightfield tools and the Vellum Grain Solver to create realistic sand elements. We will go through various methods to properly art direct the scattering of grains throughout the terrain and techniques that will cut down on simulation time significantly. We start the tutorial with pre-made terrain geometry and create an occlusion mask to control where the sand is generated. We will then convert this to geometry and create depth using VDB tools and attribute paint nodes. From there we split the geometry that will be static and the elements that will interact with the animation.
We pre-solve the simulation to ensure the grains are natural and settled within the terrain, and then simulate the necessary frames. Finally we’ll go through specific parameters for the Vellum Solver such as auto-sleep, friction and attraction weight.
01 WORK WITH TERRAIN
When looking at real-life references, sand tends to fill between the cracks of rocks and coincidentally occlusion gives us exactly what we need. The flat open areas have lower mask values and the cracks provide higher mask values. I converted the geo into a heightfield, used the mask by occlusion node, and utilised the draw mask node to art direct the mask, adding more occlusion where I wanted more sand. Then I converted it back to geo, grouped the points that are over the occlusion value (here the value is .696) and then deleted the rest.
02 CREATE DEPTH
It’s important to be efficient with grains, so I group painted the geometry that can be seen with the camera and deleted the rest. Right now the geo is flat and grains need a solid, closed surface. I scattered millions of points converted to VDB then back to geo to get the whole geometry. Then I grouped the points using the expression “@N.y >= 0” to get the top faces.
Next I used a very aggressive smooth on the top-facing group and to flatten out the surface. The
templated geo is the top of the geometry, and what is displayed is the bottom geometry.
03 MANUALLY SCULPT
This next step is pretty straightforward, I manually painted the geometry and used that value to raise the top surface. The resulting geometry was very uneven but was close to what I wanted, so I used another smooth to blend the sand mound back with the rest of the geo.
04 SAND FILL
I used a group paint node to control what part of the geo is the active area, and deleted the rest of the geometry. When working with grains there tends to be plenty of points under the surface that don’t really contribute to the final look of the effect, and only make the simulation slower. I used the same method as before but instead I raised the top group by a smaller value and sourced this geometry as a collider for the simulation. With this method I brought the active area from 25 million points down to only 7 million points.
05 SPLIT IT UP
“WITH THIS METHOD I BROUGHT THE ACTIVE AREA FROM 25 MILLION POINTS DOWN TO ONLY 7 MILLION”
As seen here, green is the active grain source and blue is the background static grain source. I know this currently looks like a spaghetti of nodes but to explain it simply, I Boolean the sand fill geometry with the old geometry and delete what isn’t in the active area group. To achieve background static geometry, I Boolean the
active grain source geometry from the original geometry.
06 COLLISIONS
To make sure the geometry creates a proper VDB surface volume I extruded the edges and used a Polyfill. I also combined the sand collider VDB created from the previous step with the environment. For the astronaut in this image all we need is the feet, so I just delete the top half, saving a lot on data and calculations.
07 GRAIN SETUP
I find it really helpful to keep notes of the particle separation on the side. I used the grain source node because I had to check the Dither Surface parameter or the points won’t even show up. Since sand is just the tiny broken bits from the surrounding rocks I used the same texture from the terrain. I added noise to the UV so it won’t exactly match, blurred the colour then transferred the attributes to the points. I grouped the points using the terrain as a bounding volume and deleted them. If you don’t do this step, the grains would just explode as the solver tries to push them out.
08 PRE-SOLVE
Grains always need a couple of frames to settle in the beginning, especially if you use jitter scale. For the static grains we can stop after this step, but for the active grains we save a lot of frames of calculation. This is also important if you want to have grains with lower friction values as they tend to slip away from their original place. I added attraction weight after presolving with some noise to create interest in the simulation. The astronaut starts walking 20 frames into the shot. I also like to add a POP Wind animated left and right to make sure all cracks get filled.
09 THE SIMULATION
A lot of work with grains is preparing them beforehand, but there are a couple of settings you need to keep in mind. Grains need 10 substeps or it will give you unstable results. This simulation is pretty slow in general so I added a speed limit of 1.5. Friction is the
most important value and I used a dynamic scale of .2. I also limited max acceleration to around 15, as grains tend to be unstable and this parameter really helps. I set the attraction weight to 1 because I set this value on the points and I had a range of between .01-.03.
10 SLEEPING GRAINS
Initially, I simulated without any sleep so I could get an idea of the average speed of all the grains, then I started tuning this value. This is probably the most important part of the entire simulation and you just have to experiment with the values. How auto-sleep works is that if a single point stays below the velocity threshold for the sleep delay in seconds, stop that point. In order to wake these points up we use a POP Awaken node and a volume source, in this case the astronaut’s foot. Points can also wake up other points with Self Awaken. If a point is moving faster than the Velocity threshold it will wake up other points in an area of its Pscale * the Wakeup Scale. When calculating this area, points are turned into volume grids and you need to set this as low as you can or you will see a ‘terracing’ effect. •