How I created the tranquil autumn air within 99 lines of Python code | Taichi Docs

Taichi Lang
Parallel-Programming-in-Python
9 min readMay 16, 2022

--

10 min read

Yuanming Hu, CEO @ Taichi Graphics | Ph.D MIT | Tsinghua Alumni

On a Sunday afternoon about a couple of months ago, when Ye and I were on our way back from a long week of travel, we decided to do something to relax on the train ( to kill time). Since we happened to mention Minecraft and MagicaVoxel, we decided to do a Hackathon, where we use Taichi Lang to create a GPU path tracing voxel renderer. Soon, before we were back home, we had our prototype:

Taichi Lang is embedded in Python and it runs on any operating system and can easily interact with Python. As far as I know, apart from Taichi Lang, there’s no such tooling in the Python ecosystem for generating GPU path tracing voxel renders. With Taichi Lang, one can easily create such a renderer ( https://github.com/taichi-dev/voxel-challenge/blob/main/renderer.py) in around 300 lines of code.

When finishing off the program, we became aware of something more serious: It is much easier for an experienced graphics developer to code a path tracing renderer than to come up with a scene setting for a beautiful image. Considering the huge amount of work involved in developing the UI, if we could only edit voxels one by one, it would take ages to get the intended results!

I’m not a mighty Minecraft developer, but, thankfully, I can program to batch process the voxels. Let’s get started!

The theme

Finding a beautiful theme is half success. Forest is a common theme in many great voxel artworks. Then I found from online the following picture: a quiet forest in the autumn air. Nice!

It must be very interesting to reproduce a tranquil autumn theme with voxels and use ray tracing to render it!

Note: So long as you have basic Python programming knowledge, you will be able to follow the rest of this post. Taichi Lang is a parallel programming language embedded in Python, allowing your program to be accelerated by your GPU. If you are unfamiliar with Taichi Lang, read this: https://docs.taichi-lang.org/docs/.

Program in Python and indulge in the 3D voxel world

When finishing reading this post, you will be able to create your own 3D voxel world. The source code is in Python and compatible with almost all platforms. It runs fine on my Macbook (20 FPS) except for some noises, and the noises subside quickly after you pause. If you are using an ultimate GPU like RTX 3090, it will definitely run much more smoothly.

If you wish to try out the autumn theme for yourself and view the complete source code (91 lines of Python code in total), you can clone my repo at https://github.com/yuanming-hu/voxel-art. If you wish to create your own voxel world, start by using our template repo https://github.com/taichi-dev/voxel-challenge/

Just so you know, Taichi Voxel Challenge 2022 is getting heated. If you are also a voxel art lover, you are very welcome to join! Let’s compare ‘voxels’ and motivate each other! For more information about how to participate, see the Voxel Challenge README at https://github.com/taichi-dev/community/blob/main/events/voxel-challenge/README.md

It has been reported at https://github.com/taichi-dev/taichi/issues/4891 that Taichi Lang v1.0.1 has some compatibility issues with the Vulkan backend in some environments. The next Taichi Lang release will ship the fix. As a workaround, use Taichi Lang v1.0.0 instead:

pip install taichi==1.0.0

Using voxels to create a forest in the autumn air

The autumn theme has three key elements: trees, forest floor covered by fallen leaves, and volumetric fog. Our renderer does not support volumetric fog, but we can simulate autumn sunset with a 45° directional light source ( set_directional_light()) and a yellowish light color ( set_background_color()) instead.

Then you get the following scene:

This is a small cube. I tuned the direction and color of the light to add a touch of the autumn air.

You may have noticed the black edges. Why we still have edges even if we have set voxel_edge to zero? This is due to the float-point precision. Well, they will not be noticed if you don't look close at them...

Base floor

Sectional drawing is the technique commonly used in many masterpiece voxel artworks. In other words, a cross section can help reveal things that cannot been seen otherwise. In our case, it is the base floor (earth of multiple layers):

We can imitate the above cake to make a base floor of earth.

Now we start building the base floor layer by layer, and each layer is virtually a flat block. And we need a function for defining a flat block, which stretches from the point (pos[0], pos[1], pos[2]) and has a size of size[0] x size[1] x size[2]. We also need to add some noise ( color_noise) to its color to make it look more real.

The key here is the use of ti.ndrange. It can iterate over multiple ranges in one for loop.

Using ti.grouped, we pack the three loop variables i, j, and k into a vector I = (i, j, k). Using the create_block() method, we can draw a large block:

There we go:

Then we can loop the create_block() method call for four times to draw a four-layered base floor:

The color is a bit lighter for the ground. Hmm, let’s add a darker surface to it.

Not too bad. By mimicking the layered cake, we have a base floor for holding the trees, fallen leaves, and fences.

Tree and fallen leaves

After finishing reading this session you will know how to create a forest.

One tree does not make a forest, and we have to make it within 99 lines of code. So, first off, we need a function for creating a tree:

The function takes four parameters:

  • pos: Position of the tree.
  • height: Height of the tree.
  • radius: Radius of the tree crown
  • color: Color of the leaves.

Let’s start with something easy, the tree trunk, and we can save some time by recycling the create_block() function:

Now, let’s add some leaves to the bold, boring tree trunk. Here, we define a function called create_leaves(). In this function, we make the following three assumptions:

  • The leaves of the tree are in the shape of a cylinder.
  • Each leaf has a probability of occurrence in the cylinder.
  • A leaf’s probability of occurrence is inversely proportional to its distance to the axis of the cylinder.

Well, it doesn’t look very real, but we can use mathematics and noise to give it some fine tweak:

Though the function looks a bit complicated, the key point is to calculate a probability for each voxel in the ‘leaves’ region. After adding some details like noise, we are almost done with the tree.

Autumn has always been synonymous with fallen leaves. Then, we intersperse the circular ground under the tree with some random voxels:

After calling the create_tree() method a few times, we get a small forest. You probably need to fine-tweak the position, height, and color of each tree:

Fences

The last step is to create fences, which is to add a bar along each direction and insert small supporting sticks at regular intervals:

Now we are done with the base floor, trees, fallen leaves, and the fences. Let's call it a day!

Press W/S/A/D/Q/E to enable panoramic mode and press P for screen capture. Alas! Haven't touched my camera for a long while, but at least I can turn to the 3D voxel world for solace. :-)

Some great entries of Voxel Challenge 2022

Before we move on to the next section, I'd like to share with you some of the very interesting entries of Voxel Challenge 2022, all made within 99 lines of Python code. Do bear with me.

Click bit.ly/3whe1zX for more interesting voxel artworks, along with their source code!

--

--

Taichi Lang
Parallel-Programming-in-Python

The Taichi language is an open-source, imperative, parallel programming language for high-performance numerical computation