logo80lv
Articlesclick_arrow
Research
Talentsclick_arrow
Events
Workshops
Aboutclick_arrow
profile_loginLogIn

A Detailed Guide on Setting Up a Procedural Cabin Generator in Houdini

Fabian Zackrisson shared an extensive breakdown of the Procedural Scandinavian Cottage Generator project, detailed the production process behind it, and explained why procedural modeling in Houdini is not as scary as it appears.

Introduction

My name is Fabian Zackrisson, and I'm a 26-year-old guy from a little town in Sweden called Ytterby, which translates to "the outer village" for all you 3 people wondering, located about 20 minutes away from Gothenburg.

Right now, I'm working as a Mid Lookdev and Modeling Artist at a fantastic studio Goodbye Kansas. I'm working from our Stockholm office and have been doing so for the last 3 years. Goodbye Kansas is a VFX studio that is mostly known for our, if I dare say so myself, incredible game cinematics, but we also do feature films and TV series. And I, along with my amazing colleagues, have been fortunate enough to work with some really cool clients such as Disney, Netflix, Amazon, Ubisoft, CD Projekt Red, and many more.

Some projects that I have worked on are game cinematics for IPs such as Alan Wake 2, Skull and Bones, and PUBG: Battlegrounds, as well as some TV series such as Shogun, SEE, and Netflix's One Piece, to name a few.

I studied VFX and Games for two and a half years at Luleå Technical University in Sweden (Gscept) before landing an internship at Goodbye Kansas. Fast forward three years to today, and I'm still at the same company, still love waking up every morning and going to work. And as cliché as it may sound, when you're having this much, it never feels like work!

To see more breakdowns of the cottage generator in higher resolution, along with other projects I tinker with in my spare time, you can visit my ArtStation.

Learning Houdini

My first glimpse into Houdini was during a very short week's introduction to FX that my university hosted. And if I remember correctly, I was more scared of Houdini after that lesson than I was walking into it. This is just my personal opinion, but if you want to get into Houdini for the first time, don't start with FX like I did, as it very easily can become too large of a hurdle to jump over (unless your goal is to become an FX Artist, of course).

When it comes to my work at Goodbye Kansas, I use Houdini for things such as lookdev, environments, scene assembly, automatic UV mapping, procedural modeling, tool building, and some other bits and bobs. I would say that Houdini is the backbone of our software pipeline at Goodbye Kansas, as all components eventually have to go through it before they get rendered out. And the importance has grown even further since our implementation of USD and its tight integration with Houdini. 

My real personal Houdini journey started around 3 years ago when I first got my internship at Goodbye Kansas. I had gotten the word that Goodbye Kansas moved over most parts of the pipeline into Houdini, which initially made me panic because I had just spent my last 2 and a half years of university getting very acquainted with Maya in terms of scene assembly, lighting, lookdev, and so on. But I just had to embrace the fact that Houdini was going to be a part of my life from now on. So during the weeks leading up to my internship, I started a new project at home where the main goal was to get used to working in Houdini. So, I made a little environment scene with an adventurous frog in a lush forest scene, as you can see below: 

I wouldn't say that I instantly fell in love with the program, but I really liked the visual structure of laying out nodes and being able to sort out different networks using colors and labels. And when it came to lighting, lookdev, and general scene assembly, I could really see the benefit of the software compared to other ones.

What has motivated me the most with learning Houdini is mostly because I absolutely hate having to redo simple and repetitive tasks. I also feel like I'm at the point where I have memorized a good enough chunk of the nodes in Houdini so that I can comfortably build things fairly quickly. But don't get me wrong, I more than often get stuck and have to run with my tail between my legs to our FX/CFX department at work, because they are the true wizards of Houdini at the office. There's no shame in asking for help from people who know more than you, or anyone else for that matter!

The Cottage Generator

The main goal was to learn more about procedural modeling and the HDA creation process within Houdini. With every single project I create, I set out to learn something new and challenge myself. So I thought that a house would be a suitable project due to its core shapes not being overly complicated to create within Houdini, plus that it's an "asset" that makes much more sense to generate multiple versions of in a VFX or games pipeline. If you compare the cottage to something like a car or a toaster, they would most likely be built by hand in 3D software like Maya or Blender. 

Now let's talk about cottages! 

If you have been to any of the Scandinavian countries, you might have seen these old, most often red, charming little cottages. They're not unique to Scandinavia, of course, but there is an abundance of them here in the countryside in Sweden, which I would say has really left a lasting impression on the Swedish architectural landscape. So, I decided that a Scandinavian Cottage Generator was the perfect contestant for my procedural journey. 

In this project, I took a pragmatic approach, opting for the most straightforward solution that I could come up with at the time instead of worrying too much about optimization and figuring out the cleanest solution to a problem.

I used a "brute force" way of working, which for me meant quickly throwing down the very first nodes that came to my mind, which I thought would solve the issue, even if it meant potential performance trade-offs compared to if I found some clever VEX code which would have done the job faster and better. This decision aimed to save time, considering the larger scope of the project.

But to summarize my core goals:

  • Learn more about procedural modeling.
  • Learn more about HDA building.
  • "Brute force" most aspects of the project for the sake of time.
  • Try to make a little environment scene for the final render.
  • Try to build it with as little geometry intersection as possible.
  • All primitives need to generate UVs.
  • Don't let the project drag on for too long (this I failed with)

Thoughts on Procedural Modeling in Houdini

Procedural modeling is extremely fun, satisfying, and rewarding once you get the hang of it. It's very much like solving a really engaging puzzle. Procedural modeling can be extremely beneficial if the task you are to complete requires multiple variations. And if your procedural systems are set up "properly", then your iteration time for each variation can be drastically reduced. Plus, you're able to address feedback notes much quicker. In a professional environment, however, it's crucial to carefully evaluate whether assets should be created through procedural or manual methods, especially considering the scarcity of time in a VFX production. 

And I would like to break the myth, if you'd call it that, that you have to be super-duper technical to get started with modeling procedurally in Houdini. In fact, to prove at least some deniers wrong about this line of thinking, have a look at this super simple procedural setup below that I created in a few minutes just as an example:

In the GIF above, I'm just demonstrating a simple procedural setup (unrelated to my cottage generator). While not visually striking, it illustrates the fundamental principles of how procedural setups like my Cottage Generator typically operate at their core.

The process involves creating individual sections, such as the base foundation and roof and then using the Match Size node to procedurally position the second component on top of the first one. The final node network for the cottage generator uses 56 Match Size nodes, hopefully emphasizing the node's significance within procedural modeling.

And similar to artistic principles, procedural modeling often begins with primary shapes, progressing to secondary and then tertiary forms. In the simplified example above, I started with a basic roof shape. Once the core functions, like Y-Axis scaling were established, I progressed to crafting more "complex" shapes, such as the timber roof (below you can see the nodes I used for the timber roof example).

While I won't claim the cottage generator setup was a breeze – because, more often than not, it wasn't – I do want to underscore that delving into the fundamental aspects of procedural modeling is actually quite approachable and straightforward, even for beginners. Of course, as always, the ease of the process depends on the complexity of the project you're undertaking!

The Workflow

Given the generator's sheer size and amount of components, I can't cover them all here. However, I'll highlight key aspects of the cottage construction and demonstrate vital procedural problem-solving approaches that I used on the project.

The foundation of the house

To manage the four main walls of my cottage efficiently and enable future tasks like copying objects or performing boolean operations to them, I split out each wall, assigning unique groups and/or attributes (e.g., "left_grp," "rear_grp"). Tagging the base curves for the walls with groups and attributes helps me isolate individual walls using split nodes down the node chain for example. 

The GIF above illustrates the foundational curve setup, with unique Cd color attributes assigned to each side of the house (indicated by red, green, blue, and cyan colors). Later in the node tree, I can use a split or blast node with an expression like "@Cd.r=1" to separate curves based on specified colors.

After the foundation curves have been established, I then sweep the shape of the "main wall plank" onto them, which gives me unique plank geometry for each side of the house. 

For the left and right sides of the house, I make sure to create much longer curves that get swept vertically much higher than the ones in the front (see GIF above). I then boolean the top of the side planks using the roof shape to create the correct "triangle shape" for the house's side planks. 

By looking at the image below, you can see that the base of the house gets defined by the following parameters being multiplied by each other: ch("../resample_base_width/segs") * ch("../main_plank_wall/sizex").

What this basically means is that the amount of points that I resample on the X-axis of the base house grid gets multiplied by the "main plank wall's" width parameter (also X-axis). This will give me the total length for the house's X-axis. And then I do the same for the Z-axis of the house, which ultimately gives me the final depth and width of the house.

Managing normal direction

So much of procedural modeling is just managing the normal direction of points and other primitives. So learning how to manipulate normals is key to being able to bend Houdini's will to your power. And I realize this is not the most thrilling topic to discuss, but I've come to realize that it's way more important than you'd think.

Why you would want to set your normal direction in the first place is for example to be able to copy out objects such as windows and doors, and have the orientation of the object be according to the surface of the object you want to copy it onto. Just like in the GIF above. 

Example A: In the GIF below I am multiplying the current normals of the "copy points" with new normal values through an attribute wrangle using the following VEX code:
@N = @N * chv("scale_n");'

Using "chv()" for example I can create my own custom parameter. In this example, it creates a vector parameter. This allowed me to set the correct angle for the bricks on top of the roof so that they lie neatly on top of each other.

Example B: Setting the Normal direction using an Attribute Create node. Basically, I set/force the normal direction of each respective side to be pointing away from the center of the scene. So for the left side of the house, I set a value of -1 in the Attribute Create X vector field which makes the normals point to the left for that side. See image below:

I actually wrote about 4 additional methods of manipulating normals, but when I read back what I had written I realized how darn boring it was. So I removed the rest of the examples for your sake, you're welcome! But hopefully, by saying this I can convince you that knowing how to manage normals and vectors in general is very important when it comes to modeling procedurally. 

Simple code and expressions to solve tasks

I’m not very good at coding in general, but I have picked up some snippets here and there which often aids me in the building process. To be honest, most of the things I do using either VEX or expressions are just recurring pieces of code that I have memorized. And for all of you who think coding is scary, I'm totally with you, I think it is too. But here are some quite important, and slightly more technical things, that you can do inside of an Attribute Wrangle or straight into the parameter slot of nodes to perform certain operations:

chf, chv, chramp etc:

Using an attribute wrangle, you can create custom channels/parameters that can be used for a thousand different reasons. In the GIF below, I'm "chramp" to shape my roof tiles. I'm pretty sure I just found these exact lines of VEX code on the SideFX forums and plugged it straight in. And that is often the reality of learning any new software, getting inspiration from others and learning about how they create things, then trying to implement it into your workflow with your own spin on it.  

The VEX code below is run through a point wrangle, and it looks like this:

float d = fit(length(@P.x), 0, 1, 0, 1);

@P.y = chramp('myramp', d);

@myramp = @P.y;

This creates a ramp for me which I used to shape the roof tiles:

IF statements

"if statements" can be very powerful in Houdini. In the simple example below, I create groups depending on IF the point is located more than 0 "distance" on the X-axis. ELSE put the points into another group, which I can define as well. See the example below where I group the main walls of the house using this method. 

How the Chimney Was Made

As I mentioned at the start of the article, I won't be able to go through the entire cottage due to logical reasons. But I'm going to break down some parts of the chimney which I think are worth highlighting, since it took some more finessing than some other parts of the cottage. And also because the chimney covers a lot of procedural principles that were applied to most parts of the house.

Avoiding geometry intersections

Since I wanted to avoid geometry intersections as much as possible, I had to work out a way to have the roof tiles removed to make room for the chimney without them colliding/intersecting. So this is what I did. In the GIF below you can see the results. 

And in the GIF below you can also see some of the nodes that I used for that specific setup:

And finally, here you can read the steps taken in the GIF above:

  1. Create bound shape from chimney.
  2. Group points on the roof tiles using the chimney bound shape.
  3. Promote the point group to a prim group.
  4. Expand the group using "flood fill to connected geometry" to make sure the group fills the selection to the entire object that the chimney bound shape has intersected with.
  5. Blast away the tiles using the created group.

The Carve node

The Carve Node, which you can see in the GIF below, proves exceptionally useful when copying the chimney to a curve, ensuring it remains confined to the entire length of the roof.

You can easily promote the "First U" parameter from the carve node on your HDA interface, turning it into your primary slider for positioning any object along your house or custom tool. This way, regardless of the house's width, the Carve node ensures that the copied object adheres to the width constraints of the house.

Now, let's delve into the chimney's brickwork. Once I had made the initial layer of bricks, I just had to copy them out on the vertical axis (refer to the GIF above). However, there were additional steps to take to create the desired appearance and behavior of the bricks.

Quick tip: When creating HDAs, change the color of the nodes that you eventually want to promote to the HDA interface with a vivid color, like green, to keep track of them in your network!

In the following GIF, I wanted to ensure that the chimney consistently stood slightly taller than the house in its "default state." To achieve this, I had to find some sort of "relationship" of parameters which ensured so. While it may not be the cleanest solution in hindsight, it worked for me, and that's all that mattered to me at the time. This gets quite difficult to describe in words and GIFs, but I hope the information below will suffice.

Here are the steps:

  1. Use a measure node to get the total height of the house. Save that value into an attribute called @length.
  2. Then I created an arbitrary attribute called @chimneyHeight using integer values. 
  3. Finally, I took the first mentioned @length attribute and multiplied it by the @chimneyHeight attribute inside of the "Total Number" parameter of the "Copy and Transform" node. 

This is what the expression looked like that I fed into the "Total Number" parameter of the Copy and Transform node:

- prim("../measure_length_of_house", 0, "length", 0) * point(0, 0, "chimneyHeight", 0)

The "prim(...)" part fetches the house's total height that was saved into an attribute, while the "point(...)" part fetches the custom "chimneyHeight" attribute. This parameter expression ensures the chimney always stays above the roofline, even when increasing the overall house height.

As just mentioned, I utilize the prim() and point() VEX functions to fetch attributes, a crucial skill for when you’re getting into more advanced procedural setups. Explore more about this on SideFX's official documentation.

Using modulo for grouping every second chimney brick row

Knowing exactly what I wanted to do, but not knowing how to do it should be the headline of this entire article. And what you see below is a perfect example of that. I knew I wanted to group every second brick layer to then be able to rotate them 90 degrees to create a more natural-looking brick layout. So through the SideFX forums, I found some guy who had a fairly similar problem which he solved with the math function modulo. 

Here’s how all this works in practice: 

Since the Copy And Transform node can spit out an attribute called “copynum”, which basically assigns a unique integer to each copy, I could then use the math function modulo to help me with grouping every even integer of the attribute “copynum”.

How this works is because every even number thrown into the modulo function below would give me a result of 0, which according to the VEXpression below would also throw that primitive into the group called “@group_group2”.

Example of mod result scenarios: 

  • 1 % 2 = 1
  • 2 % 2 = 0
  • 3 % 2 = 1
  • 4 % 2 = 0
  • 5 % 2 = 1
  • And so on…

Below you can see that only every second brick layer gets rotated 90 degrees, thanks to the modulo grouping!

Random rotation of each individual brick

Using a For Each Loop and a Transform node, I used the following expression to randomly rotate each brick slightly to break the perfectly straight 3D lines. This is usually done on the actual points before you copy out objects. But since I went for a different approach with the chimney bricks creation, I had to apply the rotations on the actual geometry instead. See the image and GIF below for the expression I used to achieve this: 

Parameters

When it comes to HDA parameters, there’s almost no end to what you can promote to the user. And I reached a certain point where I was promoting too many parameters which just started making the HDA interface messy and non-intuitive. So I started “hard coding” some of the features of the generator to not make the interface too messy. So the HDA features most parameters that I think one would expect from a house generator. You can see them in the image below.

Funny enough, when I initially completed and uploaded the project to ArtStation, the generator lacked the capability to add more floors. It wasn't until 80 Level approached me for this interview that I found the motivation to incorporate that feature into the HDA. And for that, I’m glad, because it adds a lot of visual fidelity to the cottage.

If you want to see a video where I showcase the parameters of the cabin, check out this video:

Managing UVs and the high-poly version of the house

To speed up parameter changes in the HDA without lengthy updates, I implemented a straightforward switch node setup. By pressing a button in the HDA interface, the switch node toggled between a high-poly version of the house with UVs and a version without UVs and reduced poly count. This allowed users to explore HDA parameters with the non-UV-mapped, non-beveled version and switch to the high-poly version with UVs once satisfied.

Leveraging the house's predominantly predictable angles and corners, the Labs Auto UV node could easily handle most of the geometry. I ensured uniform UV orientation for easier texturing and used the Texel Density node on most components to maintain consistent tiling of textures across objects.

Shading

Shading the house was initially not on the to-do list. But somewhere along the way, I changed my mind and decided to do some simple procedural material setups that would hold up for mid to far distance. Everything is procedural here as well, but none of the parameters are promoted to the HDA interface since the cottage was built in SOPS, and the rendering takes place in USD/Solaris. There aren’t too many fancy things happening within the material network, but I'll highlight some things that might be interesting to some people: 

As I opted not to invest in external rendering software, I utilized Karma within Solaris/USD. Initially, my intention was to render with Karma XPU using MaterialX shaders. However, certain missing features, primarily material blending, made me not be able to use XPU. Notably, this limitation has been addressed in the Houdini 20 release, and you can now render using your GPU using material blending!

The material creation was a fairly straightforward process. With the HDA handling all of the UV unwrapping, I had the flexibility to tile textures through either UV space and of course triplanar mapping as well. Properly labeling nodes and networks is crucial for efficiency and readability, especially in a production environment where other artists may need to navigate your scenes.

The majority of textures were sourced from Megascans and customized in a master painter scene with a flat plane geometry to preview texture tiling. The time spent on the individual textures was minimal, as it wasn't the primary focus of the project, and the rendering distance allowed for less detailed textures.

Randomizing colors of the primitives to aid the lookdev process

To introduce color variation to planks, bricks, stones, and other elements within Karma and MaterialX, I had to find a solution since there was no native node available for this purpose (as far as I know). Returning to SOPs, I assigned random colors to all primitives, labeling the attribute as @randCd. Subsequently, I utilized a "prim var reader" node in the material network to interpret the primvar (attributes assigned in SOPS get converted to "primvars" within USD). Once the “randCd” primvar was read into the material network, I just had to turn it into grayscale and then I could randomize the values for all planks, etc. 

The image below illustrates the process: 

Created ramps in SOPs to fetch inside the material network

I used similar techniques to create vertical ramps, generating a color attribute in SOPs and retrieving it within the material network. This time I utilized a Point VOP to create the vertical color ramp. See GIF below:

And finally, below is the final vertical ramp mixed with some noise and ambient occlusion to create masks for grime and dirt on the facade of the house. 

Conclusion

The project took way longer than I had hoped to. It actually started when I was visiting my girlfriend who was studying in Italy at the time, almost 1 year ago. Whilst she was in classes in Florence, I would spend a few hours of the day on my laptop in the hotel room, building my little cottage (and yes I know, I should have been touring the beautiful city instead). I got about 40-50% of the way over the course of a few days. But then as I got home, the reality of life hit me, having a full-time job, relocating, and other random factors just made me lose momentum and not work on it for a while. 

My main goal was to build an HDA and learn more about procedural modeling, and that I succeeded with. But my main takeaway from this project is to keep things simpler when learning things such as these. I could have just built a procedural window generator and probably have learned almost as much. But instead, like I often tend to do, I take on projects way too big that become more of a chore than actually having fun. But I stuck to it and 1 year later I can look back at a lot of valuable lessons from building this procedural cottage.

Advice for Beginners

I could write a whole separate article on this topic. But I’m going to keep it short and sweet. First things first, and just like with every piece of 3D software out there, you have to learn how to navigate around the program. There’s no way of getting around this step. You will feel much more comfortable following more advanced tutorials if you know that you have the proper foundation before jumping in head first.

The YouTube channel NineBetween has some really well-put-together Houdini tutorials. His new YouTube series called “Houdini is Hip” lays out some good foundations in the first chapters which will aid you in becoming more comfortable with the core basics of Houdini. You can find it here.

Watch a ton of tutorials

Another thing that has helped me a lot is to watch a buttload of tutorials. At first, it felt more like a chore, but once I got the hang of the inner workings of Houdini it turned into something very fun. Compared to most other software, Houdini really is just a big puzzle of sorts. So watching someone else solve problems in clever ways becomes very satisfying. And it also helps you to see how you can solve the same problem in many different ways. 

Here are some golden nuggets in terms of tutorials for procedural modeling: 

Forums and Discord servers are your best friend

The official SideFX forums and various Discord channels are some sources of information that I think a lot of people tend to forget about when learning 3D programs. Some good Discord groups that I can recommend for everything procedural are “Think Procedural” and the “CG Lounge”.

Install the SideFX Labs nodes

Make sure to install the Sidefx Labs nodes as soon as possible. It contains a bunch of fun and helpful nodes such as “Labs Edge Damage”, “Labs Cable Generator” and “Labs Auto UV” which can help you with lots of tasks. 

Asking for help

Don’t be afraid of asking too many questions. Something that I've noticed is that Houdini artists love to help people more than any other category of artists. If I ask a modeling question at work I get perhaps 1 to 2 people answering me after a while with a fairly vague answer. But if I post on the Houdini channel I get swarmed with 4-5 people trying to solve the same issue in different ways. And I'd like to think that it goes back to Houdini being a bit like a puzzle.. everyone wants to partake in the puzzle and figure out a way to solve issues in creative ways.

Start out small and work your way up

When starting with Houdini, don't expect to be creating masterpieces within the first weeks. Instead, I would recommend beginning small by utilizing Houdini for tasks like scene management, lighting, and rendering.

And as mentioned earlier in the article, I would also advise against diving into FX if you're a total beginner. This aligns with the idea of starting small and progressing gradually. While I'm not an FX expert at all, I do feel like it demands a deeper understanding of data handling in Houdini. FX often involves caching and managing substantial data sets during simulations, alongside handling numerous attributes simultaneously, which also can be quite taxing on your system. This isn't to discourage those interested in FX but more to highlight that, especially for beginners like I was, it might be overwhelming to tackle all those aspects simultaneously. And I’m only mentioning this because Houdini is the industry standard for simulation work, but probably as you can tell from reading this article, it’s not all it can do!

Once you get more comfortable with Houdini, you can move over to incorporating it into your standard asset pipeline, for example: Perform operations such as edge damage, procedural UV mapping, scattering out dust, and other procedural techniques to your already existing 3D assets.

If you’ve read at least half of what I have said in this article I would say that you’re well on your way to start creating your first HDAs and procedural setups! Good luck and thanks for reading!

Fabian Zackrisson, Lookdev and Modeling Artist

Interview conducted by Arti Burton

Join discussion

Comments 0

    You might also like

    We need your consent

    We use cookies on this website to make your browsing experience better. By using the site you agree to our use of cookies.Learn more