3D art tutorial with p5.js #1 shapes
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.