---
title: Animating Functions of Improved 3D Perlin Noise
date: 2011-10-27
summary: A quick port of Ken Perlin's classical noise in 3 dimensions to WebGL fragment shaders, stepping through the third dimension in time for continuous animation - and a huge performance win over my old CPU implementation.
published: true
image: gpu-perlin4.png
---

![Screenshot of Perlin noise](gpu-perlin1.png#left "Multi-function scene")

## Technical Overview

In this experiment, I made a quick port of Ken Perlin's [classical noise](http://mrl.nyu.edu/~perlin/noise/) in 3 dimensions. Due to its continuity properties, we can take a 2D cross-section and step through the 3rd dimension in time. The end result is a continuous animation.

![Screenshot of Perlin noise](gpu-perlin3.jpg#right "Multi-function scene")

After reading some of Perlin's work, namely some of his early SIGGRAPH slides, I became intrigued with the potential this has for both 3D texturing and the animation of 2D textures. Many of these 2D textures, when animated, can produce some very compelling effects.

I employ fragment shaders to calculate per-pixel Perlin noise. Geometry is minimal, consisting of only 2 triangles that are un-transformed. Texture co-ordinates are generated and used in some animations, but for others only Fragment.xy is used. In all cases, time is used as an index to the Z plane of the 3D noise.

![Screenshot of Perlin noise](gpu-perlin4.png#right "Toon-shaded / Heatmap")

## Benchmarks & Comparisons

All I can say is: Wow. WebGL (or more accurately, GLSL) fragment shaders are a huge step up in terms of performance when we compare to my old CPU implementation.

In the old implementation, on a 1GHz machine:

- Firefox 7 would fail to achieve >30FPS on a 128x128 square.
- Chrome 15 seemed to achieve >30FPS, or if not, the visual stutter wasn't too noticeable.

In the WebGL shader implementation, on a 1GHz machine:

![Screenshot of Perlin noise rendered on a texture mapped cube](gpu-perlin-cube.jpg#small-right "Texture mapped cube")

- Firefox 7 easily seems to achieve >30FPS on a 1680x945 rectangle.
- As it did for the old implementation, Chrome 15 seems to outshine Firefox again.
- Furthermore, both browsers can render arbitrary transforms (the texture mapped cube) of the noise, which is something that I would have considered impossible for real-time in the old implementation.

How do we account for the speed improvements? 99% of it is due to the change from CPU to GPU shaders; programming a highly parallelizable task on the GPU will naturally outperform its corresponding CPU-only implementation. Moreover, the computation of Perlin noise is relatively simple, which makes it a good fit for approximation on the GPU.

## Resources

- [Implementing Improved Perlin Noise (GPU Gems, by S Green)](http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter26.html)
- [Implementing Improved Perlin Noise (GPU Gems, by K Perlin)](http://http.developer.nvidia.com/GPUGems/gpugems_ch05.html)
- [Learning WebGL – Lesson 5](http://learningwebgl.com/blog/?p=507)
