Tutorial 05: Textures and Exterior Calculus

In today’s lesson, we will learn to work with textures and start using SciPy to build sparse matrices.

This image has an empty alt attribute; its file name is earth_close_up.gif
This mesh has a very low resolution but we still get to see so many colors.

Environmental lights

First of all a small note on environmental lights. Environmental lightmaps can really help to make your objects look realistic. They basically simulate a weak light source from all over the place, just like in real life where everything in the surrounding casts/reflects/manipulates light somehow on your object. Everything matters, just like you.

You have already learned to use Houdini’s skylight nodes. They give you a sun for a light source as well as an environmental map with the colors of the sky.

However, you can really go online and search for these 360° photos and use them as environmental lights. Here is a really professional website with free lightmaps.

This image has an empty alt attribute; its file name is image-23-1024x553.png
Look at all these nice maps!

Inside Houdini you can then import this map in the environment light node.

This image has an empty alt attribute; its file name is image-35.png


Textures are the go-to method to apply high-resolution data on lower resolution meshes. It is a fantastic method to work in between the triangles. The main application is for coloring surfaces.

Imagine a triangle. Each vertex of the triangle is given a texture coordinate (uv). These coordinates are then used to find the triangle on an image that is to be projected onto the triangle we are working with. See this image for clarification:

Image result for texture coordinates
The three texture coordinates are (0,0), (0,1), and (1,1).

Textures in Houdini

It is really simple. Any image can be a texture. Just create a material (e.g. principle shader) and go to the texture tab and select what texture it should have.

This image has an empty alt attribute; its file name is image-28-1024x247.png

Later we will also add more special textures (e.g. reflectivity texture, bump texture). All kinds of texture are applied through the material options. Multiple textures can be used on one material.

Example: Bunny

Here we have a bunny .obj mesh and a texture of it. This .obj file already came with uv-coordinates for each point and this texture image was explicitly made for this .obj. Applying the texture onto the surface then colors in the bunny nicely. So cute! ( this is the LSCM Standford bunny by the way.)

This image has an empty alt attribute; its file name is image-25.png+This image has an empty alt attribute; its file name is image-27.png
=This image has an empty alt attribute; its file name is image-26.png

(Note: for some reason we had to flip over the v-coordinate to make sense.)

Example: Earth

Textures can do so much more than just bring in colors. Here, for example, we have multiple property maps. We have (left to right, top to bottom):

  • A night texture of the earth
  • A bump map showing the heights
  • A cloud transparency map
  • A day texture of the earth
  • A specular map to determine reflections
  • (A background image of stars, not needed here)


Each of these textures can now manipulate our surface during render time in order to get really realistic images. This is very powerful, which is why there is a lot of research for generating nice texture layouts from geometry. Conformal mappings for example often speak of texture mapping with as little shear as possible.

In order to place the uv-coordinates onto your sphere, we use the UV texture node. This will allow us to select “polar” coordinates as the method to compute uv-coordinates. After that, we can directly apply the texture.

This is what these textures can look like in action:

This image has an empty alt attribute; its file name is earth-and-bunny-1.gif
Notice how only the ocean reflects the sun but not the land? This is because of a specular map (texture map specifying reflectivity).

This is the source page for the textures of this earth model. You can google many free textures and also use this handy site to find nice material textures.

This image has an empty alt attribute; its file name is image-24-1024x576.png
Look at all these nice textures with so many properties!

Example: flat texture

Let us use a texture from the site above as our floor. This texture comes packed with an ambient occlusion map (secondary reflections), a diffuse map (color), a displacement map (height), a normal map (fine details), and a roughness map (reflection property).

This image has an empty alt attribute; its file name is image-30.png

We can then apply all these materials to a single square grid with orthogonally projected texture coordinates and thus get a beautiful tiling of the plane!

This image has an empty alt attribute; its file name is 0001-3-1024x576.png
The floor is just a single rectangle. All the details come from carefully crafted texture maps. Pretty *#§$ing cool!

But bunnies don’t belong on the street!

Exercise 1: Render the bunny on some nicer surface than this street above. Go to texturehaven.com and find a more suitable surface for the bunny and apply it.

Exercise 2: Go online and find some free mesh with textures, download it and render it to understand it.

Exercise 3: Download another planet from the astronomy texture page linked above and make the planet orbit around the bunny.

SciPy and sparse matrices

Scipy exist and is really good! Its main feature that we are going to use a lot is its sprase matrix library:

Look at this picture to understand what sparse matrix data is about:

Image result for sparse matrix
Thanks: https://ukacademe.com/ Left: normal matrix full of data. Right: sparse matrix where only non zero data is specified with locations.

With sparse matrices, we only focus on the non-zero values of the matrices. For our discrete exterior calculus differential operator $d_0\in\mathbb{R}^{nEdges\times nPoints}$ for example (d on 0-forms) we only care about entries $(i,k)$ where point $i$ is connected to edge $k$. This way we reduce the amount of memory we need from $\mathcal{O}(n^2)$ down to $\mathcal{O}(n)$, awesome!

The way to build these matrices will be the following:

  1. Every point has an index $i \in \{1, \ldots , nEdges\}$
  2. Every edge has an index $k \in \{1, \ldots , nPoints\}$
  3. “row” is a list (array) in which the $l$th entry specifies the row index of the $l$th non-zero value.
  4. “col” is a list (array) in which the $l$th entry specifies the column index of the $l$th non-zero value.
  5. “val” is a list (array) in which the $l$th entry specifies the value of the $l$th non-zero value.
  6. Specify the dimensions of the matrix $D = (nEdges , nPoints)$.
  7. Your_sparse_matrix = scipy.sparse.csr_matrix( ( val , ( row , col ) ),(nRows, nCols))

But wait! We are working with half edges in Houdini, not edges. Do we have to change anything? Surprisingly, for now, we don’t! This is because it is kind of handy that half edges already come with an orientation.

Your next homework will be to build exactly this differential operator so that it becomes used in the heat flow simulation.

Print Friendly, PDF & Email