Procedural Modeling: Quilling

comments 23
Free Tutorials

What popped up as some random images on my pinterest feed turned out to be a whole universe of an art form in itself: Quilling. The art and craft of rolling and shaping paper to form intricate mosaics depicting a wide variety of subjects.

Of course we decided to rebuild this in Houdini and although we employ a bit of VEX here and there, this project turned out to be pretty much our standard approach when procedurally modeling in Houdini. The linear layout of the node tree gives you a good impression of the straightforward steps we apply to create intricate geometry using a few basic nodes. It struck me how similar this node tree looked to most trees we end up creating in our commercial projects.

Download Project File (.hipnc)

Liked it? Take a second to support Moritz on Patreon!
Become a patron at Patreon!


  1. Christian Stith

    Yowzer. By far my favorite so far. Keep it up guys!

  2. Uli Baier

    Very nice! I like to know how much time you put into this for RnD?

    • Hi Uli,

      frankly R&D for this one was relatively quick. I saw a similar image on Pinterest and then thought about how I’d create the spirals. Actually there was no research involved and the spiralling part of the setup was done in an afternoon. Setting up lights and shaders was a totally different story though – that’s where I disappeared completely into this rabbit hole called Houdini 🙂


      • No matter what I do for lights and shaders I can’t get that effect to look right. Any advice for making it look decent? I used the same lighting setup as your polygonal rembrant tutorial but the paper wont look right

        • Hi Eric,

          paper is kinda hard to shade. The main factor in getting thin paper to look right is translucency. Combine that with a bit of ambient light or a nice HDR and you should be on your way to making this look decent…

          Cheers, Mo

  3. Its absolutely awesome! thank you for this tutorial and inspiration to beginers!

    • Hi Jorge,

      admittedly VEX can be a handful, especially when you’re just starting out. We’ve all been there 🙂 That’s why we provide scene files for you to look up what’s different in your setup than in ours in order to diagnose your scene. In this case when comparing your setup to ours, you’ll notice you have to import the point’s position “P” not “p” – VEX is case sensitive, especially when it comes to attribute names. Maybe a bit frustrating at first but quite useful once you’ve gotten the hang of it 🙂


  4. Jorge Díaz

    Thanks Moritz!

    I’m happy that is a spelling mistake and not a huge fail on the process haha

  5. Hello Moritz. Thank you for sharing your thoughts and techniques with the world. I followed you in this video and I must say that the technique has a lot of potential. I’m by no means a coder, although I’m trying hard to learn. So I watch every tutorial that I can put my hands on. I watched this one several times and noticed some irregularities, in my opinion.

    1. You created a primitive attribute that holds the position value for the center for each primitive and then you never actually use it anywhere down the node tree. When you later need to calculate the distance of every point of a primitive from the center of that prim, you use the native v@P attribute again, so I think the attribute wrangle for setting up the center of the primitive is redundant.

    2. When you calculate the distance of each point of the primitive form the prim center, you start by initializing a float variable with a default value of 1 million. Then in the nested loop, you compare the actual distance of a point with the default value and if it’s smaller, you set the the value to distance. I see no reason for this step. Would it be the same if you just calculated the distance and just write it out to an attribute?! Why the extra step of comparing it to a hard coded value?!

    Here and there I catch a sentence that starts twice, is it because of the heavy editing after the recording session? Sometimes it’s hard for me to follow the logic of your actions, may be it’s just me, but I would understand a lot faster if you teach in some more linear fashion (example, change some lines of the code when you hit a dead end), I loose it when something is not working and you rush to fix it before you actually slow down a bit and think what’s the reason. May be you shouldn’t edit out every mistake you make. I learn a lot by my mistakes. Sometimes the mistake is what really leaves a mark in my memory. Thanks again!

    PS. Another thing, can you please explain why the wrangle node running on detail is not multithreaded? I read this somewhere on the internet, but don’t know the reason why.

  6. Pingback: Procedural pals’ first post | Procedural Pals

  7. Bretislav

    Very Nice, can You help me with random attribute for “paper thickness” on every single spiral ?

  8. Bretislav

    //float width = chf(“Paper_Thickness”);
    float width = rand(@primnum)*0.05+0.01;

    int npts[] = primpoints(0, @primnum);
    int numpts = len(npts);

  9. Hi Mo!
    Awesome tut! I’m trying to render this in Redshift. I’ve tried numerous nodes to call the Cd into the diffuse_color. I’ve tried using both the Particle Attribute and Vertex Attribute set to Cd and it turns black in the Particle Attribute or to the selected color in Vertex Attribute.
    I’m even able to export as .abc and import into C4D and create a material with RS Vertex Attribute w/ name set to Cd, and viola! it works!
    Is there something I’m missing to render out in in RS in Houdini?
    Thanks again, loved this tutorial.

    • Hi Brad,

      make sure you color attribute “Cd” is set on points, then use an RS ParticleAttributeLookup pointed to Cd to import your point colors into an RS shader network. That should be it.

      Cheers, Mo

Leave a Reply