Animating An Ocean With P5.js Perlin Noise in React

ronaldabreu.dev

Hello world! Today I’d like to share with you how I drew and animated an ocean with P5.js Perlin Noise terrain generation in React.

Hopefully after reading you will have an idea of what p5 is all about and if it is something that could be of use to you and in your React project.

Before we jump into it, let’s start with a little context:

The Processing project got started by Ben Fry and Casey Reas in the spring of 2001 with the intention of promoting software literacy among visual artist, and visual literacy among technology professionals.

It was meant to serve as a software sketchbook to teach programming fundamentals within a visual arts context.

“The Processing software is used by thousands of visual designers, artists, and architects to create their works. Projects created with Processing have been featured at the Museum of Modern Art in New York, the Victoria and Albert Museum in London, the Centre Georges Pompidou in Paris, and many other prominent venues.” — https://processing.org/

Since then Processing has evolved into a development tool for professional designers and programmers alike. As well as into the full javascript library P5.js

While it is possible to integrate p5 and react by running:

npm i p5

For the purpose of creating a simple animation I installed the react-p5 package:

npm i react-p5

What I used for the base of this sketch was a procedurally generated 3D terrain.

I imported the p5 component into react with:

import Sketch from "react-p5";

In p5 we have a setup and a draw function, below we are creating a canvas in setup and passing it the windowWidth and windowHeight arguments along with the p5.WEBGL 3D environment.

p5.createCanvas(p5.windowWidth, p5.windowHeight/5, p5.WEBGL)

and our simple draw:

draw={p5 => { background(0) }}

To go about creating the ocean like surface I started by drawing a flat mesh like surface with the help of p5’s TRIANGLE_STRIP method which essentially takes a square and draws a line through it giving it a mesh like look.

to learn more about p5 functions visit https://processing.org/reference/

I created some variables for columns, rows and scales, and movement.

  let cols
let rows
let w = 5600
let h = 600
let scl = 20
let waves = 0

Next I generated z values for our grid using a 2D array:

let ocean = []; // Initialize array
for (let i = 0 ; i < 5500; i++) {
ocean[i] = []; // Initialize inner array
for (let j = 0; j < 9; j++) { // i++ needs to be j++
ocean[i][j] = (Math.random() * 5 | 0) + 6;
}
}

Then I used the p5 noise function for that natural randomness feel and in the end here is what my sketch component looked like:

<Sketch
setup={(p5, parentRef) => {
this.state.p5 = p5
let canvas = p5.createCanvas(p5.windowWidth, p5.windowHeight/5, p5.WEBGL).parent(parentRef);
canvas.position(-50, -50)
canvas.style('z-index', '-1')
canvas.style('position', 'sticky')
cols = w/scl
rows = h/scl
}}
draw={p5 => {
waves -= 0.02
let yoff = waves;
for (let y = 0; y < rows-9; y++) {
let xoff = 0;
for (let x = 0; x < cols; x++) {
ocean[x][y] = p5.map(p5.noise(xoff, yoff), 0, 1, -80, 100)
xoff += 0.05
}
yoff += 0.05
}
p5.rotateX(p5.PI/3)p5.translate(-w/2 , -h/2 + 290)p5.background(255, 255, 255);
p5.stroke(0, 151, 193)
p5.fill(0, 151, 193);
for (let y = 0; y < rows-1; y++) {
p5.beginShape(p5.TRIANGLE_STRIP)
for (let x = 0; x < cols; x++) {
p5.vertex(x*scl, y*scl, ocean[x][y])
p5.vertex(x*scl, (y+0.91)*scl, ocean[x][y+1])
}
p5.endShape()
}
}}
/>

If you are interested in using p5 to generate natural 3D terrains like this one be sure to check out this video on just that which I found extremely useful while sketching this beach/ocean p5 animation.

As with many things programming, the best way to get better at p5 drawing is to try and experiment with it. Change this, change that, and see what happens on your canvas.

To see this sketch live visit ronaldabreu.dev

Thanks so much for reading and remember to follow so you don’t miss new articles like this one!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store