Page 10-5: Procedural Textures

Page 10-5: Procedural Textures

Box 1: Procedural Texture

The idea of a texture is that we will compute a different color for each pixel. Since we can run a fragment shader on each pixel, we can do this.

As with image-based textures, we need to have a good coordinate system. We can use the UV coordinates, or anything else.

Here are two examples: for one, I'll use the world space XYZ as the texture coordinates, and for the second I'll use the object space XYZ as the texture coordinates. You should be able to tell which is which. For both, I'll convert X into the red channel (in a way that makes it go from 0-1) and Z into the green channel.

Notice how one object moves through colors in the world, while the other has the colors attached to it. Read the vertex shader xyz.vs and the fragment shaders xyz1.fs and xyz2.fs to make sure you understand how we're determining colors. Try hacking them to do something different.

You should also read the code for the example 5-1-xyz.js. In order to make the objects move, I am using the framework. And I'm playing with various "features" of JavaScript to define the methods without making a new class. (watch for the use of non-lexical this).

Usually, we'll use texture coordinates (UV) for the coordinates to define our textures. But I wanted you to have at least one XYZ example.

Box 2: A more realistic Procedural Texture

Here's a more "typical" procedural texturing example. Suppose we want a grid of dots. We could use an image texture, but then we would need a new image if we wanted to change the number of dots, the color of the dots, the size of the dots or the size of the dots. Instead, we can write a shader that computes, for every pixel, whether or not it is in a dot. We can make the things we want to control (color, number of dots, size of dot) uniform variables that we can set from our program. Like this:

Read through the shaders: dots.vs and dots.fs and understand what is happening and how the dots are getting drawn. You may also want to read through 5-2-dots.js to see how the uniform parameters are being connected to sliders.

If you look carefully, you will see evidence of "jaggies" - the circles aren't smooth and you can see the pixels, so they look ugly. Dealing with this problem (called aliasing) is an advanced topic - we'll get to it on a future page.

Box 3: Exercise 5-1: Your turn: Checkerboard

It's your turn to make a procedural texture. We'll start with something simple: make a checkerboard pattern. I've started things for you in the files e51-check.vs and e51-check.fs (note: as with all shaders, the shader files are in the Shaders directory). I've also done the JavaScript part for you, including a slider for the number of checks over the 0-1 range (see 5-3-checks.js). You shouldn't have to modify the JavaScript file (but you can). Also, to make things more convenient, we've added a page 5-3-checks.html that is a minimal html page that tests this.

You should make this respond correctly to the checks uniform variable. Look at the dots for inspiration.

Box 4: Exercise 5-2 Your turn: Some other pattern

This time, you pick what pattern/texture you want to make! Something more complicated than a checkerboard. Look at the Book of Shaders for inspiration. Or try to make wood grain, or plaid, or some wallpaper pattern - as long as its more complicated than a checkerboard.

Again, we've given you files to get started. If you need uniform variables, you'll need to make them yourself. The files are e52-proc.vs and e52-proc.fs as well as 5-4-proc.js. And 5-4-proc.html if you want to look at it without this entire page.

Summary: Procedural Textures

Procedural textures are one of the cooler things we can do with shaders. Let's look at a detail of using them on the next page.