Shaders

What are Shaders?

Shaders are small programs that run on your GPU (Graphics Processing Unit) instead of your CPU. They're used to calculate how pixels should be colored on the screen. What makes shaders special is that they run in parallel - processing thousands or millions of pixels simultaneously on the GPU rather than one at a time on the CPU.

Shaders in Three.js

In Three.js, there are two main types of shaders:

  1. Vertex Shaders: Determine where the points (vertices) of a 3D object should be positioned
  2. Fragment Shaders: Determine what color each pixel should be

Let's start with a simple example using Three.js to create a shader that animates colors.

Understanding the Shader Code

Let's break down what's happening in our fragment shader:

uniform float u_time;

void main () {
   vec2 uv = gl_FragCoord.xy / vec2 (${ width }.0, ${ height }.0);
   
   // Create a pulsing effect based on time
   float r = 0.5 + 0.5 * sin (u_time + uv.x * 6.0);
   float g = 0.5 + 0.5 * sin (u_time + uv.y * 6.0);
   float b = 0.5 + 0.5 * sin (u_time + uv.x * 2.0 + uv.y * 2.0);
   
   gl_FragColor = vec4 (r, g, b, 1.0);
}

Here's what each part does:

  1. uniform float u_time; - a uniform is a value we pass from JavaScript into our shader. Here we're passing in the current time, in seconds.

  2. vec2 uv = gl_FragCoord.xy / vec2(${width}.0, ${height}.0); - this creates normalized coordinates (0 to 1) across our canvas. gl_FragCoord.xy gives us the pixel position.

  3. The r, g, and b variables - we use time-driven sinusoids to create pulsing color values. The * 6.0 parts change how quickly the colors cycle across the screen.

  4. gl_FragColor = vec4 (r, g, b, 1.0); - This sets the final color of the pixel. The 1.0 at the end is an alpha value.

Adding Interactions

Let's make a shader that responds to mouse movement:

More Advanced - 3D with Shaders

Now let's apply a custom shader to mutate the geometry of a 3D object:

Key GLSL Language Features

GLSL (OpenGL Shading Language) has some useful features for this sort of work:

Data Types

Operations

You can perform operations on entire vectors at once:

vec3 color1 = vec3 (1.0, 0.0, 0.5);
vec3 color2 = vec3 (0.0, 1.0, 0.5);
vec3 mixedColor = color1 + color2; // Results in (1.0, 1.0, 1.0)

Built-in Functions

GLSL has many useful built-in functions:

Shaders in p5.js

p5.js also supports shaders! Let's make a shader work in p5.js:

In this p5.js example:

  1. we create a p5.js sketch with the instance mode
  2. we define both vertex and fragment shaders as strings within our JavaScript code
  3. we use p5.js's createShader () function to compile the shader
  4. we pass uniforms to the shader using setUniform ()
  5. the shader creates gradient background with animated circles and mouse interaction

This approach makes shader programming accessible to those who would prefer to use p5.js.

Creating Moiré Effects with Shaders

Moiré patterns are the interference effects that occur when two similar patterns are overlaid with slight differences.

1. Concentric Circles

This example creates a moiré pattern by overlaying two sets of concentric circles:

2. Rotating Grid Patterns

This example creates a moiré effect by overlaying two grid patterns, with one rotating over time.

3. Radial vs Linear Patterns

This example creates a moiré effect by combining radial lines with moving linear lines.

How Moiré Patterns Work

Moiré patterns occur when two similar patterns are overlaid with a slight difference in angle, spacing, or position. The key principles to remember:

  1. Pattern Similarity - The two patterns should be similar but slightly different (two grids, two sets of concentric circles, etc.)

  2. Interaction Methods:

    • Multiplication - Multiply the two pattern values together
    • Addition - Add the pattern values and then normalize
    • Subtraction - Take the absolute difference between patterns
  3. Movement - Animate one pattern relative to the other by:

    • Rotating one pattern
    • Scaling one pattern
    • Moving one pattern's center
    • Changing one pattern's frequency

Code and Concept References

The examples in this tutorial draw from several sources, including:

Resources for Learning More

More resources: