3D art tutorial with p5.js #1 shapes

Warren George
7 min readMar 9, 2024

--

In my previous article I explained how you can get started with Coding with p5.js: Getting Started

In p5.js, WEBGL is one of the two available rendering modes, allowing you to create 3D graphics and interactive experiences alongside its default 2D mode. Key features of WEBGL in p5.js:

3D shapes: Draw basic shapes like boxes, spheres, cones, cylinders, and more using functions like box(), sphere(), etc.

Custom geometry: Create complex models from code or load them from 3D file formats like OBJ and STL.

Materials and lighting: Define materials like basicMaterial() or specularMaterial() and use lights like ambientLight() to affect object appearance.

Camera control: Change the viewpoint using functions like perspective(), ortho(), and rotate the camera with rotateX(), rotateY(), rotateZ().

Textures: Add textures to surfaces for enhanced realism and detail.

Shaders: For advanced users, write custom shaders to achieve unique visual effects.

We will draw some of the basic shapes and learn about the co-ordinates, translation and rotation. There are a number of very key differences between the default 2D and the 3D environment

Sketch 1.1 basic sketch

Starting with our bog standard sketch of a canvas 400 by 400 pixels and with a slightly grey background.

function setup() 
{
createCanvas(400, 400)
}

function draw()
{
background(220)
}

Sketch 1.2 WEBGL

The first thing to notice is that we have the third argument in the createCanvas() function. WEBGL

function setup() 
{
createCanvas(400, 400, WEBGL)
}

function draw()
{
background(220)
}

Sketch 1.3 let’s draw a box

Let’s draw a box, dimensions of 100 pixels by 100 pixels by 100 pixels

function setup() 
{
createCanvas(400, 400, WEBGL)
}

function draw()
{
background(220)
box(100)
}

Notes

One thing you will notice is that I have not specified where to draw it, I have given it no co-ordinates, yet it has drawn it in the centre of the canvas. Also it doesn’t look very 3D…ish. To the first point, the centre of the canvas is in the centre in all three dimensions, the x, y and z axis. Secondly we need to rotate it to see it.

Sketch 1.4 rotating

We cannot simply rotate it, we have to specify which axis, whether it is the x, y or z axis by some angle (measured in radians). The functions we use are: rotateX(), rotateY() and rotateZ() which I hope are self explanatory. Let’s rotate the box along the x axis by 2 radians.

Sketch 1.5 45˚ rotation

To make life a little easier to understand I will change the angle mode to degrees which is a bit more intuitive.

Add angleMode() and rotateX()

function setup() 
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(45)
box(100)
}

Sketch 1.6 the x and y axis

To show how 3D it is we are going to rotate along the y and the z axis also. Add rotateY and rotateZ

function setup() 
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(45)
rotateY(45)
rotateZ(45)
box(100)
}

Sketch 1.7 incrementing the rotation

Even better still we can animate the rotation by introducing a variable and incrementing. Replacing the hard coded 45˚ with angle

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
box(100)
angle++
}

Sketch 1.8 let’s draw a cuboid

That was just a box we can add other dimensions to make it a cuboid

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
box(100, 150, 50)
angle++
}

Sketch 1.9 let’s draw a plane

Let’s draw another shape, a simple plane where it has two dimension. Do you notice that there is a line going across it? This is because all the shapes will be made up of triangles.

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
plane(100, 150)
angle++
}

Sketch 1.10 let’s draw a cylinder

A cylinder has two dimensions, one for the diameter and the other the length.

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
cylinder(100, 150)
angle++
}

Sketch 1.11 let’s draw a sphere

Here is a sphere with a single dimension.

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
sphere(100)
angle++
}

Sketch 1.12 let’s draw a an ellipsoid

Now an ellipsoid, this is like a sphere but has two dimension.

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
ellipsoid(100, 50)
angle++
}

Sketch 1.13 let’s draw a torus

Now for a torus (doughnut), this also has two dimensions. An outer and inner diameter.

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
torus(100, 50)
angle++
}

Sketch 1.14 let’s draw a cone

A cone which has two dimensions also, the first is the diameter and the second is the length (or height) of the cone.

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(220)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
cone(100, 150)
angle++
}

Sketch 1.15 adding a bit of colour

Let’s go back to our simple box. We can add colour just as before.

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(0, 200, 200)
fill(200, 200, 0)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
box(100)
angle++
}

Sketch 1.16 translate

We are going to move it from the centre (0, 0) to the bottom right hand corner. To do this we don’t give the box (or any shape) co-ordinates as we did with 2D shapes, we have to translate, but remember that the origin (0, 0) is in the centre of the canvas.

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(0, 200, 200)
fill(200, 200, 0)
translate(100, 100)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
box(100)
angle++
}

Sketch 1.17 translate again

Translating it to the top left hand corner

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(0, 200, 200)
fill(200, 200, 0)
translate(-100, -100)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
box(100)
angle++
}

Sketch 1.18 translate along the z axis

But what about the z axis. Let’s translate along the z axis only, we still need all three arguments for translate. This has moved it a lot closer

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(0, 200, 200)
fill(200, 200, 0)
translate(0, 0, 500)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
box(100)
angle++
}

Sketch 1.19 translate the other way

Now further away

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(0, 200, 200)
fill(200, 200, 0)
translate(0, 0, -500)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
box(100)
angle++
}

Sketch 1.20 more than one shape

But what happens if you have more than one shape occupying the same co-ordinates. Let’s find out. Remove the translate. We will add a cone and a torus to the box.

let angle = 0

function setup()
{
createCanvas(400, 400, WEBGL)
angleMode(DEGREES)
}

function draw()
{
background(0, 200, 200)
fill(200, 200, 0)
rotateX(angle)
rotateY(angle)
rotateZ(angle)
box(100)
cone(100, 300)
torus(100, 50)
angle++
}

This is a tutorial based on the eBooks ‘The Joy of Coding’, visit www.elegantAI.org for more information or go straight to amazon to get one of the eBooks, along with the app, splitting your monitor so that you can code along.

--

--

Warren George

www.elegantAI.org. Fascinated by how things work especially humans. Also love coding especially relating to AI and Robotics.