I'm on a quest to share knowledge and help artists use Houdini in a practical way for their own projects. My goal is to help you skip the headaches and wasted time so you can bring your ideas to life - faster. [Sign up to receive new emails (almost) daily, and read some past articles under "Posts" below :) ]
10 Step Six N. Five Environment Breakdown [a case study]
This type of breakdown is something new that I haven't done before. So if you enjoy the breakdown format then let me know!
I'll recap a 10-step process I used to create these environment renders right here.
Camera One: Front 35mm
Camera Two: Top 35mm
Camera Three: 85mm
Camera Four: 35mm
Bonus points if you can guess which Six N. Five project this was inspired by ;)
The overall process was pretty standard and took roughly two hours (not including rendering). Lots of the time was spend dialing in the exact look of the lighting and the noises + other small details and the pace wasn't rushed at all.
If you enjoy this break down, please let me know. Hopefully it's a good balance of detail and steps.
Enjoy.
Step 1: Base Landscape
For this landscape I used a 1000x1000 resolution heightfield (2000x2000 for world size with a grid spacing of 2).
The goal was to get some nice ridges that I could use for the environment. I didn't need much detail in this one, since the grass was going to cover the entire landscape (in the end the ground was rendered with a pure-diffuse material).
I ended up using a single heightfield noise, and after some tweaking I eventually found a scale + offset that gave me some ridges that I liked.
Step 2: Add Some Distortion
This distortion (a heightfield distort by noise) was left with nearly default values. The amplitude was 10, element size was 100, and the noise type was set to "Curl".
The goal here was to add some more variation to the shape of the heightfield. Although the ground itself wasn't seen much in the final render, I used the normals from the surface to set the initial direction of the grass. So these small variations caused by this distort helped add some realistic / natural looking shapes to the overall look of the grass.
I did try to take the gradient of the Y-Position (the "steepness" of the slope) and use that in my wind that I fake later with some noises, but I didn't like the result so I stuck with just basic noises without any fancy tricks for that wind animation.
Step 3: Convert to Geometry and Cull by Camera
Since I was going to instance lots of grass patches, I didn't want to place them where the camera couldn't see them. So I did a camera culling to remove every part of my landscape that wasn't seen in any camera views.
(I created the camera in LOPS, so I had to import it back to the OBJ level to use it for this)
For the final animated shot, I had 2 cameras (a top-down and a ground-level camera) and I used the start and end frames for both camera animations to capture all areas of the landscape that were in the frames. So in total, I used the combination of 4 volumes created to group the points, and delete everything else.
Step 4: Scatter Lots of Points!
Next up I got started preparing the instancing!
This one was just scattering points onto the geometry (I recomputed the point normals on the landscape geo before I scattered, that way the points automatically inherited the normals from the landscape). This normal was later used for setting the orientation of the grass blades.
I could have removed the points that weren't seen by the final camera (points on the backfaces of the ridges) but since I wasn't worried about optimizing it too much I didn't worry about this.
I also used a point VOP to create this black and white noise on the points. The position was sampled and fed into a "Turbulent Noise" VOP with the noise type set to "original perlin noise". This noise came out between the ranges of -.5 and .5, so I had to remap it to be between 0 and 1 (which is the black and white pictured here in this image)
Step 5: Remap the Noise to Color (Cd)
This noise I then remapped to get the general color of my landscape. Each point here had a final Cd color that I then sampled in the material using a "primvar reader" in solaris. (NOTE: by default the Cd attribute is imported into Solaris and renamed to "displayColor", so you can either fetch the displayColor primvar, or you can rename the Cd to something different in SOPS, and then reference that new name that won't be changed by default).
BONUS TRICK:
A trick I did to get some slight variation between the color transitions on this noise was add a random value to the "f@noise" attribute I used to then create the color. The image just below here is what the noise looks like without this random value added.
No Random Noise Added
And then the one below here is the result of adding the noise.
With random noise added
I used some VEX to create this noise! and (hopefully) you can read it in this image if you're curious (I'll also paste the vex at the bottom of the email if you want to copy and paste it or read it in a bigger font).
The goal here was just to match the reference, the Six N. Five image had some nice blending between the transitions so I tried to get a similar effect.
Step 6: Create Procedural Grass
Next up was the grass! This one was fun, it was a nice refresher from the Procedural Plants section inside LEVEL UP: Houdini, where we cover how to make all sorts of plants from scratch.
The general idea I used here was to create some lines where I wanted the grass blades to be, then distort with a noise to add some variation to the tops of the grass (I used a remapped "curveu" attribute to control the intensity of this noise displacement, that way the base of the grass blades stay in place).
Then after that I used the "curveu" again to create a scaled attribute I'd use for the width of the geometry when I swept it. I decided to create actual geometry here (rather than render curves as geo at render time) that way I had bit more control over the edges and the exact normals I was using).
NOTE: If you're curious how to make more plants, or create projects like this, then you'd definitely be a fan of my course ;)
Step 7: Prepare Points for Instancing
Top Image is default normal. Bottom image is new normal with noises.
Because the normal attribute were already created from the landscape, I had the points nearly prepped and ready for my final grass instancing. But I wanted some more variation to the orientation of the grass, so I used some noises to adjust the rotation of each patch (each cube here represents an entire patch of grass).
The goal here was to create some natural looking shapes and patches of grass that all has slightly different rotations. HINT, if you animate this noise you can also create some pretty nice looking "wind" effects. Where the blades look like they are blowing in the wind.
(Bonus Hint) -> If you want the wind effect to be extra nice, you can take the attribute you used to randomize the rotations of the instances, and use that in the material for the grass. So the grass blades that are 'bent' with the wind, might have a slightly more saturated color, or a more glossy appearance. This can create some really nice looking motion if you dial it in correctly ;)
Also, when instancing in Houdini, you'll need to have your grass aligned with the +Z axis, because that's the axis that Houdini will place on the normal.
Step 8: Solaris Prep + Lighting!
This step was where it got fun. I imported everything into Solaris (stage/ LOPs context) where I do my layout and lookdev. (everything in Level Up: Houdini is done through Solaris by the way...so check that out if you want to learn how to become a Solaris wizard)
I then created 6 lights that I used to get the final lighting. There was a Karma physical sky I used to create the main background (top left in the image). Then there was a sun light (part of the physical sky), that I used to create a main light direction and brighten most of the scene. And then 4 hand placed rectangle lights I used to create some of the "accent" lighting. I messed a bit with the color and the shaping of these lights to create some interesting shapes that I really ended up liking in the final composition.
HINT: If you "split by LPE Tag", in Solaris, you can get a bonus render layer for each light. This lets you modify the lighting after you've rendered it, and even change the color, the intensity, or remove lights entirely from your finished render. It can be a game-changer for bigger projects.
Step 9: Instance Grass and Create the Material
This part is also where it gets fun.
I set up the instancing for my grass and create the material that would sample the Cd attribute I had created in SOPS. (Remember! The Cd attribute is renamed to "displayColor" when you import into LOPS, so you have to be sure to use the correct one, or to rename your attribute prior to importing).
The material itself was just a basic diffuse material with a constant roughness and no other fancy tricks. I did however end up using the same noise value I used to randomize some of the rotation values for the grass blades, and I increased the saturation and brightness of the diffuse color using that attribute. I also added a tinnyyyy bit of sheen based on this value too, which gave it a nice reflection variation in the final animation.
Step 10: Render and Wait!
The final render was pretty quick (I did it overnight so it was done in a few hours). And I had 240 frames of animation with a nice camera transition across the landscape.
For some "touch-ups" and compositing (all done in COPS), I didn't do much at all. I added a slight vignette, some glow to the highlights, and then some camera distortion near the very edges of the frame (which you can only see in the final animation, not really the still render).
Bonus Post-Mortem
The shot itself (the environment + animation) was a nice fun one to try and tackle. I always love Six N. Five and how nice all their projects are.
I think to better match the reference I could dial in the lighting a bit more. The plants they used in their render were more of a 'wheat' type grass, with some interesting shapes and silhouettes. So I could also try to create grass that better matches that shape.
The noises, coloring, and materials could also be improved with some more variation and interest. And the grass doesn't feel as soft and I'd like it to be.
But overall, it was a fun exercise. This full project will eventually make it's way into Level Up: Houdini. It was requested by one of the artist in the program, so I'm excited to get it added (@Theo! If you're reading this now, let me know how you like the final result ;)
If you're interested in learning more Houdini and want the skills to implement projects like this yourself (all 100% from scratch), then you might be interested in my course Level UP Houdini, which you can check out here.
I'll send a $100 off coupon code for Level Up: Houdini to the first person who responds back with the exact Six N. Five project I used as reference for this project.
Stay curious,
Will
P.P.S. Here's that vex I used to create the random noise. I split the vex lines in boldand the comments in italics, so you can see what each line does but let me know if you have more questions.
/*
This code adds some random value to the noise for each point. This "f@noise" attribute is what's later used to create the Cd attribute (color)
By adding a random value here, I can create that a "noisy" transition that gives some variation between the blends of colors.
*/
float maxOffset = chf("max_offset");
//This is the maximum noise offset allowed (set in the spare parameter I created that's named max_offset)
float rand = rand(@ptnum);
//create random float value between 0 and 1, which is seeded by the point number
rand = rand - .5;
//This sets the value to be between -.5 and .5
rand *= 2;
// multiply rand by 2, so it's now between -1 and 1. I then multiply this against "maxOffset" to get the random variation
f@noise += rand * maxOffset;
// add random offset to noise. The max value here is at most the value of maxOffset, since I know that rand of between -1 and 1
I'm on a quest to share knowledge and help artists use Houdini in a practical way for their own projects. My goal is to help you skip the headaches and wasted time so you can bring your ideas to life - faster. [Sign up to receive new emails (almost) daily, and read some past articles under "Posts" below :) ]