Page 5: Procedural Textures

CS559 Spring 2023 Sample Solution

The XYZ 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 of the spheres below, 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 shaders/10-05-01.vs and the fragment shaders shaders/10-05-01a.fs and shaders/10-05-01b.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 in 10-05-01.js ( 10-05-01.html). In order to make the objects move, we are using the framework. And we’re 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 you should see at least one XYZ example.

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: shaders/10-05-02.vs and shaders/10-05-02.fs and understand what is happening and how the dots are getting drawn. You may also want to read through 10-05-02.js ( 10-05-02.html) 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.

Notice in the fragment shader that I compute whether I am inside a dot or not using the step function. This returns 0 if we are inside of the dot, or 1 if we are outside of the dot (the distance d is greater than the radius). This “inside the dot” is used to control how the dark and light colors are mixed together (using the mix function). Generally, we prefer to use built-in functions rather than if statements (or more complex expressions) because they are optimized to run fast. However, here, the use of the step/mix combination will make future things easier. Make sure you understand this code before moving on to the next page.

To check that you understand how the dots work, change the shader in shaders/10-05-02.fs so that the dots are different colors - some are blue and some are green. You can choose which ones are which (any individual dot should be all blue or all green, but there needs to be some blue dots and some green dots).

Notice that we added a slider called “segs” that changes the number of triangles used to approximate the sphere. As you raise the number of segments, the sphere gets smoother. (because it is more polygons). The shape changes, but the texture doesn’t.

Next: More Procedural Textures
Page 5 Rubric (5 points total)
Points (5):
Box 10-05-02
5 pt
some dots are blue, some are green