Author: Zhou Zhichuang Reading time: 10~15 minutes

Before noise, my knowledge of randomness was limited to Math.random. It’s useful, like the simple lottery program in H5, or picking a card at random… However, in my recent work, I need to implement some random image effects, so I found that this function can do very limited things. Then I came across noise as a random form, and it solved my problem perfectly. So I want to write this article, hoping to let some front-end students, especially those whose work involves more effect reduction, know about noise, maybe after this, you will have more ideas about these random elements in the designer’s design draft.

Designers often add an element of randomness to their designs, which is a great design technique. But for the front-end implementation, this kind of design element reduction is mostly a bumble because the base Api provides regular geometric shapes (circles, rectangles, etc.). Often, in the end, these effects had to be compromised by using cutmap restoration. We couldn’t do more optimization, let alone show more design ideas by adding animation, which has been the blank area of front-end restoration for most students.

The images above are taken from actual design drafts, where it’s easy to find the random elements I’m talking about that add mystery and technology to the design, but they seem hard to make with traditional front-end design reduction techniques. And that’s perfectly suited to noise.

Noise algorithm has been very mature after years of development, and there are many kinds of classification of Perlin noise, Simplex noise, Wavelet noise. The default noise in this article refers to Perlin noise, and the specific noise algorithm will not be deeply introduced. The main purpose is to provide a heuristic introduction to students who have not been exposed to this field.

A random line

Let’s start with a simple problem: draw an arbitrary line. It seems simple enough, we use Math.random to generate a series of points and then connect them

for (let i = 0; i < POINTCOUNT; i++) {
  const y = HEIGHT / 2 + (Math.random() - 0.5) * 2 * MAXOFFSET;
  const point = {
    x: i * STEP, y }; POINTS.push(point); }... ctx.moveTo(POINTS[0].x, POINTS[0].y);

for (let i = 1; i < POINTS.length; i++) {
  const point = POINTS[i];
  ctx.lineTo(point.x, point.y);
}
ctx.stroke();
Copy the code

But there’s nothing special about it. It’s like a deliberately drawn line chart. Straight lines make our image very stiff, so let’s make a little improvement. We take two control points between two random points and use Bezier curves to connect the random points again:

for (let i = 0; i < POINTS.length - 1; i++) {
  const point = POINTS[i];
  const nextPoint = POINTS[i + 1];

  ctx.bezierCurveTo(
    controlPoints[i][1].x, 
    controlPoints[i][1].y, 
    controlPoints[i + 1] [0].x, 
    controlPoints[i + 1] [0].y,
    nextPoint.x,
    nextPoint.y
  );
}
ctx.stroke();
Copy the code

It’s a lot more natural this time, and what we’re doing here is crucial, and it’s not the noise algorithm per se, but the idea is the same. The random points in the above example can be understood as random features, and individual random features are meaningless. Then we connect them with straight lines, and they still don’t look connected as a whole, but when we connect them smoothly, they form a complete pattern in front of each other, which gives a natural random effect. This is also my subjective understanding of noise after learning it — noise mainly solves the problem of making some smooth transition or connection between unrelated random features.

Ok, here we stop and think about nature and relax. Think of clouds, rivers, mountains… These are all random events in nature, accumulated over a long period of time to create. The key here is “accumulation over time”, which means that a cloud doesn’t just appear, a river doesn’t just appear, they all evolve bit by bit, so they are “smooth” in these random events.

The perlin noise

In modern games and movies, it is already possible to reproduce these natural elements realistically. They are not and cannot be made using a lot of modeling software, but they are generated in code, and the key technique is noise algorithms. An important part of this algorithm is the interpolation algorithm in the random features, where the values in the middle of the random features can be smoothed over to mimic the results of this evolution in nature.

Ken Perlin, who was working on Disney’s TRON animated film in 1983, came up with Perlin noise to achieve this natural texturing effect. Perlin noise was so successful that he won an Academy Award for scientific achievement.

Our example above overuses Bessel curves for smoothing between random features, while perlin noise uses a more scientific and complex interpolation method:

f(t)=t*t*t*(t*(t*6-15)+10)
Copy the code

You can check the implementation details for yourself. Berlin noise has evolved into many variant implementations, including a later optimized version of Berlin noise, Simplex noise. This article focuses on the use of noise, and some of the following implementations are used by default as Berlin noise.

Use of noise functions

Noise functions are used by taking a point and returning a result of -1 to 1. The random feature length is in units of 1, so you need to pay attention to the unit conversion before using noise functions. For example, if you have a 1000 x 1000 canvas and want to use a random value of noise for each pixel, you first define how many random squares you want to apply. If you apply n x N squares, you need to transform the coordinates before you can get the random value

scale = 1000 / n;

nx = x / scale;
ny = y / scale;

pointRandom = noise2D(nx, ny);
Copy the code

Js implementation of noise tools: github.com/josephg/noi… Github.com/jwagner/sim…

Random set

Noise takes the same parameters and always returns the same result, so a random set is usually preset in order to generate fixed random feature points, and then the smooth random result will be interpolated among these random feature points. Some noise tools already have a random set by default, but you can also customize different seeds to generate different random effects. The previous noise tool, NoisEJs, can be defined as follows:

noise.seed(Math.random());
Copy the code

A one-dimension noise

One-dimensional noise can be simply understood by assigning the random set to the integer bits on the X-axis and calculating the random value of the continuous transformation by smoothing interpolation function. This may not be exactly the same as Perlin noise, but the basic idea can be understood this way

The simple result is that given a coordinate, you will get a random value, and given continuous coordinates, you will get continuous random values, rather than random values that are unrelated to each other like math.random ().

One-dimensional noise example

The following example is the effect of an egg made with one-dimensional noise. First, fixed points are taken on the circle, which are equally divided. They get a random offset by noise respectively, and then combine with time to make the offset change smoothly with time:

Codepen. IO/chiunhauyou…

For example, the fire effect below, the offset of the flame tail flickering effect, is a combination of one-dimensional noise and time offset

Codepen. IO/gnauhca/pen…

The time-shifting effect of one-dimensional noise can also be achieved by using time as the y parameter of the two-dimensional noise function.

Two dimensional noise

Two-dimensional noise by defining a two-dimensional grid, step on the definition of stationary random assembly are distributed on the grid vertex, and the random characteristic of each vertex is a gradient vector, and then calculate box around four vertices to a point in the grid (also is the need for noise value point, in the image below yellow point) of the vector, and gradient vector dot product with them, Finally, the random noise value corresponding to the point is obtained by interpolation function.

The following image was generated using webGL with a 2D noise function, white for 1 and black for -1, which is the effect of a 5 × 5 square. We don’t have to worry about WebGL here, we just have to worry about defining the squares that apply to our problem and getting the corresponding continuous random values.

Here focuses on the introduction of noise use, specific implementation methods can be click on the following reference link to understand. How to use it is simple:

// Divide by 100 to apply a noise grid in units of 100 pixels
let randomValue = noise.simplex2(x / 100, y / 100); 
Copy the code

Two-dimensional noise example

The noise function takes the random value freely and can be used to define any variable you want, such as the following example, where the random value is smoothly used to define the particle’s velocity vector to achieve both random and continuous motion:

function calculateField() {
  for(let x = 0; x < columns; x++) {
    for(let y = 0; y < rows; y++) {
      let angle = noise.simplex3(x/20, y/20, noiseZ) * Math.PI * 2;
      let length = noise.simplex3(x/40 + 40000, y/40 + 40000, noiseZ) * 0.5; field[x][y].setLength(length); field[x][y].setAngle(angle); }}}Copy the code

Generate the vector a random Angle, and the length of the vector, using Simplex3 for 3d noise and actually the third parameter is the offset that is being used as a 2d

Codepen. IO/DonKarlsson…

If you leave traces of movement, you can get a much cooler effect

// Use translucent clear canvas
function drawBackground(alpha) {
  ctx.fillStyle = `rgba(0, 0, 0, ${alpha || 0.07}) `;
  ctx.fillRect(0.0, w, h);
}
Copy the code

Codepen. IO/DonKarlsson…

Two-dimensional Noise Example (SVG)

By superimposing several Perlin noises of different frequencies, a technique called fractal noise, more textures can be achieved, such as water and mountains. There is an application of this noise filter in SVG, feTurbulence, which is easy to ignore, but it can achieve many unexpected effects:

<feTurbulence type="turbulence" baseFrequency="0.01 .1" numOctaves="1" result="turbulence" seed="53" />
Copy the code
  • NumOctaves noise stack number
  • Seed Random seed
  • Type Noise type

FeTurbulence is actually noise values applied to each pixel to get color values, and then you can combine that with other filters to convert those random colors into other random representations, like pixel offsets, and you can use the feTurbulence filter to get some natural textures, as well as reflections.

Codepen. IO/yoksel/pen /…

Wow.techbrood.com/fiddle/3165…

The noise superposition here has certain constraints on frequency and amplitude, which are self-similar, see thebookofshaders.com/13

The three-dimensional noise

In fact, 3d noise is just adding a latitude on the basis of 2D noise. Define a 3D random vertex set, and the 3D coordinates in the 3D grid will get a corresponding noise value, which is also continuous.

The random value obtained by 3d noise can be converted into the deviation of a 3D point in its normal vector direction, so as to realize a random undulating deformation. In webGL, this step is usually done in the vertex shader, which executes on all defined vertices:

float addLength = maxLength * cn(normalize(position) * 2.9 + time * 0.9); // Compute random values
vec3 newPosition = position + normal * addLength; // Convert to offset in the normal vector direction
Copy the code

Codepen. IO/gnauhca/pen…

In the slice shader, you can use noise to create textures:

Codepen. IO/timseverien…

As mentioned above, noise is designed to simulate natural effects in movies/games, so it is natural to use webGL to produce ocean, mountain and river effects: Codepen. IO/Matikbird/P…

Of course, this requires not only skillful use of noise, but also master of webGL. Although we introduced the use of noise in Canvas/SVG at the beginning, now webGL has been widely supported by computers and mobile browsers. Combined with webGL, noise can play its greater value.

conclusion

Noise is widely used as an important knowledge in the field of graphics and plays an important role in 3d programs. However, noise is not exclusive to the field of THREE-DIMENSIONAL graphics. Learning to use noise and applying it to basic front-end technologies such as Canvas SVG AND CSS can also achieve some unexpected effects. When a designer outputs an effect drawing with similar random features one day, it is advisable to directly contact the designer for communication. Perhaps these effects were created using noise in some image processing software. If you get the generated parameters, it’s possible to do that on the front end, too, and by combining time offsets, you might get a nice animation.

The resources

Blog.csdn.net/qq_34302921…

Codepen. IO/DonKarlsson…

thebookofshaders.com/13/?lan=ch


Pay attention to [IVWEB community] public number to get the latest weekly articles, leading to the top of life!