Language Settings

Creating Custom Geometry in WebGL

p5.js has a number of basic shapes, like box() or sphere(), but p5.js is also capable of rendering complex custom geometry, both from 3D model files or from code. This tutorial will walk through how to import 3D models into p5.js, as well as how to create geometry from scratch.

If you are new to 3D check out the Coordinates and Transformations tutorial.

Loading 3D Models from File

Custom geometry can be imported into p5.js using either OBJ or STL files. These files are usually generated in a 3D modeling tool like Blender, which offers much more control when constructing a 3D scene. This is done using the loadModel() method, which should be used within preload(). Then you can use the model() function to draw the model, as demonstrated in the example below.

A common issue that can come up with custom models is scaling. Depending on how the model is constructed, it might be a much different size when drawn in p5.js, or even be too small to be drawn at all. The loadModel() method includes a normalize parameter that will resize the model to something that works better in p5.js.

Note that there is currently no support for STL files with color, although you can add color using materials or textures, which you can learn about in the Styling and Appearance tutorial.

Creating Basic Procedural Geometry

Geometry can also be defined procedurally using code. This is a great way to create geometry that moves or is formed using your own set of rules. There are a number of methods that can be used to create 3D geometry in a way that is similar to 2D drawing in p5.js. For example, methods like quad(), triangle(), rect(), and circle() each have extra parameters that make it possible to use them in 3D.

There are other methods that offer greater control of the geometry. A shape can be defined point-by-point using beginShape(), vertex(), and endShape(). This following example shows how these methods can be used to construct a 3D shape mathematically.

There is also a powerful class, p5.Geometry, which p5.js uses internally for loadModel() but can also be used to define custom geometry, offering tools that can be helpful in calculating faces and normals.

In 3D, a face refers to a collection of three or four points that make up a surface, giving our geometry the appearance of being solid. A normal is the direction that is perpendicular to the face, which helps p5.js calculate lighting across the surface.

an illustration a collection of three points, constituting a face, and an arrow extending perpendicular to it, the normal

In the following example, p5.Geometry is used to plot a grid of points for the geometry. Then, computeFaces() is used to give the geometry a solid appearance and computeNormals() allows our geometry to have proper lighting.


Now you should be able to create custom geometry, making it possible to create unique shapes, both from other tools and from code. Spend some time working with a variety of 3D modeling tools so you can find the one that works best for you.

Other Tutorials

This tutorial is part of a series about the basics of using WebGL in p5.js. Check out each of these other tutorials below.



Meaning that something is defined mathematically, instead of from stored data, like a file.


A representation of geometry.


STL (most often standing for "standard tesselation language") is a file format for 3D models. It only stores information about the geometry.


OBJ is an open file format that stores geometry data as well as some material and texture data. In p5.js, we are limited to its geometry, although an image can still be mapped to the surface using textures.


The solid surface that is generated between three points.


The direction that is perpendicular to a face, which is often needed when calculating lighting or using materials.


Changing something so that it fits within a standard range.