Home

๐ŸŒฑ Diorama 3D

Educational library for 3D Creative Coding.

๐Ÿ“‘ Visit the full reference

Technically is a THREE.js wrapper for p5.js mimicking the same direct and artistic approach ๐Ÿค“

Created by Massimo Avvisati

Released under GNU GPL License ver.3

  1. How to use
  2. Getting Started - How to create in 3D
  3. Colors and Materials
  4. Images, Textures and more
  5. More shapes
  6. Environment, Post-processing and UI
  7. Using p5.js together with Diorama
  8. Data utilities

How to use ๐Ÿ”—

Fast and easy ๐Ÿ‘ฉโ€๐Ÿ”ฌ

Visit this โ–บ starting sketch and start playing with it

โš ๏ธ To save you need to be logged in and select File -> Duplicate from p5.js editor menu

Add to a p5.js project ๐Ÿ‘ฉ๐Ÿพโ€๐ŸŽจ

Create a โ–บ new P5.js sketch

Copy the following tag and paste it (between line 5 and 6) inside index.html file:

<script type="module" src="https://dev.codemotionkids.com/libraries/diorama/diorama.js"></script>

Congratulations: Now you are using Diorama 3D inside your sketch!

Getting Started - How to create in 3D ๐Ÿ”—

Just an orange sphere in the center ๐Ÿ”—

Your very first Diorama!

Run this code in your P5.js sketch.

function setup() {
  createCanvas3D(600, 400);
  //Change background color of the scene
  background3D("#333333");
  //Change material color to orange
  diffuse("#ff7d00");
  //Create a sphere in 0, 0, 0 with radius 1
  sphere(0, 0, 0, 1);
}

function draw() {
  // ๐Ÿ” Never create objects here, but don't forget to have it in your code
}

Creating basic shapes ๐Ÿ”—

Getting Started - Other shapes

There are many shapes you can create to compose your scene. Each primitive has its specific parameters. For istance to define a cube(x, y, z, side) or a sphere(x, y, z, radius) you need coordinates and side or radius while to define a box(x, y, z, width, height, depth) you need three dimensions.

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  diffuse("#4895ef");
  
  //capsule(x, y, z, radius, length)
  capsule(-5, 0, 0, 0.25, 1);
  //sphere(x, y, z, radius)
  sphere(-4, 0, 0, 0.5);
  //cube(x, y, z, side)
  cube(-3, 0, 0, 0.7);
  //box(x, y, z, width, height, depth)
  box(-2, 0, 0, 0.2, 1, 0.4);
  //cylinder(x, y, z, radius, height)
  cylinder(-1, 0, 0, 0.2, 1);
  //icosahedron(x, y, z, radius)
  icosahedron(0, 0, 0, 0.7);
  //ellipsoid(x, y, z, width, height, depth)
  ellipsoid(1, 0, 0, 0.5, 1, 2);
  //cone(x, y, z, radius, height)
  cone(2, 0, 0, 0.6, 0.5);
  //torus(x, y, z, radius, tubeRadius)
  torus(3, 0, 0, 0.3, 0.1);
  //octahedron(x, y, z, radius)
  octahedron(4, 0, 0, 0.3);
  //(x, y, z, radius)
  tetrahedron(5, 0, 0, 0.3);
}

function draw() {
  // ๐Ÿ” Never create objects here, but don't forget to have it in your code
}

Move, rotate and scale your objects ๐Ÿ”—

Changing objects after creation - Change properties

You may want to change some properties of your object after you created them. In order to do so a good way is using variables and then calling objects functions like in this example:

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");

  diffuse("orange");
  // We create a thin cylinder
  var straw = cylinder(0, 0, 0, 0.1, 4);
  
  // Now we can move or rotate it
  straw.setPositionY(1); //a bit upper
  straw.setRotationZ(45); //rotated 45ยฐ on Z-axis
  straw.setScale(2); //double scale
}

function draw() {}

Combining shapes using Union, Subtract and Intersect objects ๐Ÿ”—

Getting Started - Union, Subtract and Intersect objects

In this example we create two variables a and b to contain a reference to a torus and a sphere overlapping. Then we use subtract(a, b) to obtain the difference between the two shapes. Order is important subtract(a, b) results in a different shape than subtract(b, c)

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  diffuse("#4895ef");
  
  //change a and b with your shapes
  var a = torus(-1, 0, 0, 1, 0.3);
  var b = sphere(0, 0, 0, 1);
  
  
  diffuse("#dd5a00");
  
  //change a, b order and try union or intersect
  subtract(a, b);
}

function draw() {}

Align objects ๐Ÿ”—

Getting Started - Other shapes

By default shapes are created with the origin in the middle of the geometry (like with align(CENTER)) but if we want to change the alignment we can use align(TOP), align(CENTER), align(BOTTOM).

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  
  //default is align(CENTER)
  diffuse("#ff5c00");
  box(0, 0, 0, 5, 0.1, 1)
  
  
  diffuse("#dd0066");
  
  align(BOTTOM);
  capsule(-2, 0, 0);
  
  align(CENTER);
  capsule(0, 0, 0);
  
  align(TOP);
  capsule(2, 0, 0);
  
}

function draw() {}

Colors and Materials ๐Ÿ”—

You can achieve many different materials using:

  • diffuse("#cc00cc") or diffuse("white") or diffuse(255, 128, 0) to set the color of following objects created
  • roughness(0.5) to set the roughness of following objects created. 0.0 is smooth 1.0 is rough. Default is 1.0
  • opacity(0.5) to set the transparency of following objects created. 0.0 is transparent (invisible) 1.0 is completely opaque. Default is 1.0
  • metalness(1.0) to set the metalness of following objects created. 0.0 is for non metal reflection (dieletric) 1.0 to reproduce metal object. Default is 0.0
  • emissive("#00ff00") to set the emissive color of following objects created. Emissive color is not affected by light. No emissive color (black) by default
  • emissiveIntensity(1.0) to set the power of emissive color. From 0.0 to 1.0. This is multiplied to the emissive color.

Roughness ๐Ÿ”—

Colors and Materials - Three spheres with different roughness

Lets create three spheres with different roughness.

function setup() {
 createCanvas3D(600, 400);
 background3D("#333333");
 diffuse("#ff7d00");
 
 //Very smooth sphere
 roughness(0);
 sphere(-2, 0, 0, 1);
 
 
 //Almost smooth sphere
 roughness(0.3);
 sphere(0, 0, 0, 1);
 
 
 //Fully rough sphere
 roughness(1.0);
 sphere(2, 0, 0, 1);
}

function draw() {}

Metalness ๐Ÿ”—

Colors and Materials - Three spheres with different metalness

Lets create three spheres with different metalness. They are all smooth to appreciate the metalic effect more.

function setup() {
 createCanvas3D(600, 400);
 background3D("#333333");
 diffuse("#ff7d00");
 
 //all spheres are pretty smooth
 roughness(0.2);
 
 //Metalic material
 metalness(1.0)
 sphere(-2, 0, 0, 1);
 
 
 //Almost metalic material
 metalness(0.3);
 sphere(0, 0, 0, 1);
 
 
 //Dieletric (not metalic) material
 metalness(0);
 sphere(2, 0, 0, 1);
}

function draw() {}

Opacity and transparency ๐Ÿ”—

Colors and Materials - Three spheres with different opacity

Lets create three spheres with different opacity.

function setup() {
 createCanvas3D(600, 400);
 background3D("#333333");
 diffuse("#ff7d00");
 
 //all spheres are pretty smooth
 roughness(0.2);
 
 //Opaque (not transparent) material
 opacity(1.0)
 sphere(-2, 0, 0, 1);
 
 
 //Half transparent
 opacity(0.5);
 sphere(0, 0, 0, 1);
 
 
 //Almost invisible
 opacity(0.1);
 sphere(2, 0, 0, 1);
}

function draw() {}

Images, Textures and more ๐Ÿ”—

Load images in a 3D scene ๐Ÿ”—

Images in a 3D scene as planes

First of all you need to upload your image into p5.js and preload it.

Example of loaded image
// ๐Ÿ” You need a "global variable" when loading images
var img; 

function preload() {
  // ๐Ÿฆค always preload your images
  img = loadImage("egyptian.jpg");
}

After this you can use the loaded file many times in your sketch!


function setup() {
  createCanvas3D(600, 400);
  
  background3D("#333333");
  // ๐Ÿ–ผ๏ธ image3D(yourImage, x, y, z, scale);
  image3D(img, -2, 0, 0, 1);
  // ๐Ÿ–ผ๏ธ make it double
  image3D(img, 0, 0, 0, 2);
  // ๐Ÿ–ผ๏ธ Stretch you image by specifying โ†”๏ธ width and โ†•๏ธ height
  //image3D(yourImage, x, y, z, width, height);
  image3D(img, 2, 0, 0, 1, 3);  
}

function draw() {}

Using transparent images ๐Ÿ”—

Transparent image of a cactus

var plant;

function preload() {
  // ๐Ÿ‘ป It must be a png image with transparent background
  plant = loadImage("cactus.png");
}

function setup() {
  createCanvas3D(600, 400);
  
  background3D("#333333");
  
  align(TOP);
  
  //1m tall ๐ŸŒต
  image3D(plant, -2, 0, 1, 1);
  //2m tall ๐ŸŒต
  image3D(plant, 0, 0, 1, 2);
  //3m tall ๐ŸŒต
  image3D(plant, 2, 0, 1, 3);
}

function draw() {}

Textures ๐Ÿ”—

You can use an image as a texture (also called diffuse map) to give to your objects a more realistic looking using diffuseMap(image);

๐Ÿ” Notice that diffuse color will change texture color: add diffuse("white") before diffuseMap() to restore original texture colors ๐Ÿ”

Texture example

var stone;

function preload() {
  // ๐Ÿ–ผ๏ธ A texture is an image
  stone = loadImage("texture_diffuse.png");
}

function setup() {
  createCanvas3D(600, 400);
  
  background3D("#333333");
  // ๐Ÿงฑ All following 3D objects will have this texture! 
  diffuseMap(stone);
  
  cube(-2, 0, 0, 3);
  
  sphere(2.5, 0, 0, 2);
}

function draw() {}

You can stop using a texture by calling noDiffuseMap();

Group of objects ๐Ÿ”—

When you want to create complex objects made of many parts you should enclose them in a group so you can then change its position, rotation and scale all at once!

How to create a group ๐Ÿ”—

Grouping objects

In order to group some 3d shapes you need to create a variable and place all your parts between beginGroup() and endGroup() creating a tree of Groups and Meshes.

This is very important if you need a rig that you can move, rotate and scale:

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  roughness(0.1);
  
  // Start creating a group for both eyes
  var eyes = beginGroup();
  
  // ๐Ÿ‘๏ธ Inside the eyes group we create a group for the left eye
  var leftEye = beginGroup();
  
  diffuse("white");
  // It's important to center your 3D shape to the origin of the group...
  sphere(0, 0, 0, 1);
  diffuse("#ff0066");
  sphere(0, 0, 0.7, 0.5);
  
  endGroup();
  // Move the group not the single parts ๐Ÿ˜
  leftEye.setPositionX(-1.5);
  
  // ๐Ÿ‘๏ธ We do the same for the right eye
  
  var rightEye = beginGroup();
  
  diffuse("white");
  sphere(0, 0, 0, 1);
  diffuse("#9C27B0");
  sphere(0, 0, 0.7, 0.5);
  
  endGroup();
  
  rightEye.setPositionX(1.5);
  endGroup();
  
  //We can now rotate both eyes  
  
  eyes.setRotationX(-40);
}

function draw() {}

Cloning objects and groups ๐Ÿ”—

Cloning a group of cloned meshes

You can clone a group and place it in 3D space:

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  
  var fruit = beginGroup();
  
  diffuse("#FF5722");
  // ๐Ÿ” The orange is centered in 0, 0, 0
  sphere(0, 0, 0, 1);
  
  diffuse("maroon");
  // we only move along the y of orange radius + half height
  cylinder(0, 1.25, 0, 0.1, 0.5);
  
  diffuse("green");
  ellipsoid(0.35, 1.25, 0, 0.7, 0.2, 0.3);
  
  endGroup();
  
  //We can move where we want the original orange
  fruit.setPositionX(3);
  
  //...and create clones in other positions
  
  var fruit2 = clone(fruit, -3, 0, 0);
  var fruit3 = clone(fruit, 0, 0, 0);
  
}

function draw() {}

More shapes ๐Ÿ”—

3D Text ๐Ÿ”—

Before using text you need to preload a font from library provided (UBUNTU) or by providing a JSON file created with Facetype.js

Getting Started - 3D Text example

var ubuntu;

function preload() {
  // ๐Ÿ” You need to preload your font
  ubuntu = loadFont3D(UBUNTU);
}

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  diffuse("#E91E63");

  // ๐Ÿ”  Select the font used and size (height and depth)
  setFont3D(ubuntu, 1, 0.2);

  // ๐Ÿ”ค From here you will create text tall 1 and deep 0.2
  
  text3D(0, 0, 0, "Hello world!");
}

function draw() {}

Creating custom shapes and extrusion ๐Ÿ”—

A shape is a set of vertices in 2D space and absolute coordinates. To create a shape and use it you need to store it in a variable and define each vertex like this:

Example of loaded image
var myShape = beginShape2D();

addVertex(0, 0);
addVertex(-1, 1);
addVertex(1, 1);
addVertex(2, 0);
addVertex(1, -1);
addVertex(-1, -1);

endShape2D();

We can use shape() function to create a 3D shape. We can also specify a depth value to make it thick.

Getting Started - Using Custom Extruded Shapes and Bevels

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  diffuse("#FFEB3B");

  //We create a 2D shape specifying each vertex
  var myShape = beginShape2D();

  addVertex(0, 0);
  addVertex(-1, 1);
  addVertex(1, 1);
  addVertex(2, 0);
  addVertex(1, -1);
  addVertex(-1, -1);

  endShape2D();

  //After having defined the "2D base" we can create our custom shape (thick 0.5m)
  var arrow = shape(myShape, 0, 0, 0, 0.5);
  
  //...and use it as any 3D shape
  arrow.setRotationX(90);
  
}

function draw() {}

You can also use more parameters to create different beveled shapes.

Getting Started - Using Custom Extruded Shapes and Bevels

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  diffuse("#4CAF50");
  roughness(0.1)

  //We create a 2D shape specifying each vertex
  var myShape = beginShape2D();
  addVertex(-0.5, -2.5);
  addVertex(0.5, -2.5);
  addVertex(0.5, 2.5);
  addVertex(-0.5, 2.5);
  endShape();
  
  //No bevel
  shape(myShape, -2, 0, 0, 0.1);
  
  //Using default bevel
  shape(myShape, 0, 0, 0, 0.5, true);
  
  //With all parameters we can generate different bevels
  shape(myShape, 2, 0, 0, 0.1, true, 0.2, 0.2, -0.1, 32);
  
}

function draw() {}

Lathe objects ๐Ÿ”—

For shapes like bottles, glasses or everything obtained by the rotation of a "profile" you can use Lathe objects! A Lathe object is always symmetrical and it is created in the origin (0, 0, 0) so you need to asign a variable from endShape() and change position, rotation, scale or any property of the mesh.

Lathe objects

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  
  diffuse("#17c3b2");
  roughness(0.1);
  
  //We define the "profile" of our Lathe object using 2D points
  beginLathe();
  addVertex(0, 0);
  addVertex(0.5, 0);  
  addVertex(0.5, 0.5);
  addVertex(0.6, 1);
  addVertex(0.7, 1.1);
  addVertex(0.4, 1.15);
  addVertex(0.3, 1.25);
  addVertex(0.3, 2);
  addVertex(0, 2);
  
  //Lathe objects are always created in 0,0,0 so we must change properties later
  // endLathe() returns a reference to the object just created
  var cup = endLathe();
  
  cup.setPosition(0, 0, 2);
}

function draw() {}

Extruded objects ๐Ÿ”—

Extruded objects

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  diffuse("#fca311");
  
  
  beginExtrude(0.05);
  addVertex(0, 0, 0);
  addVertex(0, 0.5, 0);
  addVertex(0, 1, 1);
  var leftObject = endExtrude();
  leftObject.setPosition(-2, 0, 2)
  
  diffuse("#14213d");
  beginExtrude(0.2);
  addVertex(0, 0, 0);
  addVertex(0, 0.5, 0);
  addVertex(0, 1, 1);
  var centerObject = endExtrude();
  centerObject.setPosition(0, 0, 2);
  
  diffuse("#e5e5e5");
  beginExtrude(0.2, 5);
  addVertex(0, 0, 0);
  addVertex(0, 0.5, 0);
  addVertex(0, 1, 1);
  var rightObject = endExtrude();
  rightObject.setPosition(2, 0, 2)
  

}

function draw() {}

๐Ÿงช Extruding can be very powerful if mixed with some math.

Moving the camera position example

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  diffuse("#FF5722");
  quality(HD);
  roughness(0.1);
  
  var frequency = 20;
  var amplitude = 0.25;
  var angleStep = 0.5;
  var radius = 3;
  
  
  beginExtrude(0.2, 4);
  for (var angle = 0; angle <= 360; angle += angleStep){
    var x = cos(angle) * radius;
    var y = sin(angle * frequency) * amplitude;
    var z = sin(angle) * radius;
    addVertex(x, y, z);
  }
  endExtrude();
}

function draw() {}

Camera, Environment, Post-processing and UI ๐Ÿ”—

Camera position ๐Ÿ”—

We can change camera position by using setCamera(x, y, z). Default position is setCamera(0, 1.68, 5)

Moving the camera position example

function setup() {
  createCanvas3D(600, 400);


  //We move the camera from (0, 1.68, 5) to (0, 0, 7)
  setCamera(0, 0, 7);
  
  background3D("#333333");
  
  diffuse("#ff7d00");
  sphere(0, 0, 0, 1);
  
}

function draw() {}

We can also point our camera to an arbitrary point using setCamera(fromX, fromY, fromZ, toX, toY, toZ).

Moving the camera position and loot at

function setup() {
  createCanvas3D(600, 400);
  
  background3D("#333333");
  
  diffuse("#03A9F4");
  sphere(0, 0, 0, 1);
  
  diffuse("red");
  sphere(-5, 0, -5, 1);
  
  //Look at the red ball from (0, 3, 5)
  setCamera(0, 3, 5, -5, 0, -5);
}

function draw() {}

Orthographic perspective (isometric view) ๐Ÿ”—

You can change camera perspective using changeCamera(ORTHOGRAPHIC) as in the following very basic isometric diorama setup.

Isometric view example

function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  changeCamera(ORTHOGRAPHIC);
  
  //placing the floor below the origin makes everything simplier ;-)
  align(BOTTOM);
  
  
  diffuse("white");
  //floor
  box(0, 0, 0, 6, 0.5, 6);
  
  //walls and other object will be on TOP of the floor
  align(TOP);
  
  diffuse("#E0E0E0");
  //walls are 3.5m tall
  box(0, 0, -3, 6, 3.5, 0.5);
  box(-3, 0, 0, 0.5, 3.5, 6);
  
  //this is a good reference of a 1.7m tall person
  diffuse("#8BC34A");
  box(0, 0, 0, 0.5, 1.7, 0.5);
}

function draw() {}

Environment ๐Ÿ”—

We can use special images to create an environment for our scene changing its lights and (optionally) setting a 360 degrees background:

360ยฐ image as environment map

You can generate your 360 degrees background using AI platforms like Blockade Labs' Skybox and then simply upload the file in your sketch.

360 degrees AI generated example of a space lowpoly landscape

You can now load your skybox as usually and pass it as a parameter of environment(mySkybox):

var mySkybox;

function preload() {
  mySkybox = loadImage("toscana.jpg");
}

function setup() {
  createCanvas3D(600, 400);
  //hideGrid();
  background3D("#333333");
  diffuse("white");

  environment(mySkybox);
  
  //To place things on the ground we may want to align them on top
  align(TOP);

  //Let's create three spheres to see the effect
  roughness(0);
  metalness(1);
  sphere(-2, 0, 0, 1);
  
  roughness(0);
  metalness(0);
  diffuse("#FFFFFF");
  sphere(0, 0, 0, 1);

  roughness(1.0);
  metalness(0);
  
  diffuse("#FF5722")
  sphere(2, 0, 0, 1);
}

function draw() {}

360 degrees AI generated environment map

By default will create attach the bottom side of your image to the ground so your 3D scene result on the floor.

// attach the environment map to the ground/grid
environment(mySkybox);

360 degrees AI generated environment map not attached to the ground

But you can easly override this and have your model flying in the center of a spherical skybox!

// don't attach the environment map to the ground/grid
environment(mySkybox, false);

360 degrees AI generated skybox

You can even load a skybox without changing the environment already defined.

// skybox only not attached to the ground
skybox(mySkybox, false);

Preset environment map

NEON environment example

You only need to add environment(NEON) in your setup:


function setup() {
  createCanvas3D(600, 400);
  //hideGrid();
  background3D("#333333");
  diffuse("white");
  // Try CINEMA, ROTUNDA, SUNSET, SWITZERLAND, NIGHT, NEON, VERANDA, STARS or FOREST
  environment(NEON);
  
  //Let's create three spheres to see the effect
  align(TOP)
  roughness(0);
  metalness(1);
  sphere(-2, 0, 0, 1);
  
  roughness(0);
  metalness(0);
  diffuse("#FFFFFF");
  sphere(0, 0, 0, 1);

  roughness(1.0);
  metalness(0);
  
  diffuse("#FF5722")
  sphere(2, 0, 0, 1);
}

function draw() {}

Currently there are those presets CINEMA, ROTUNDA, SUNSET, SWITZERLAND, NIGHT, VERANDA, STARS, FOREST and NEON

CINEMA environment example ROTUNDA environment example SUNSET environment example SWITZERLAND environment example NIGHT environment example VERANDA environment example STARS environment example FOREST environment example NEON environment example

Effects ๐Ÿ”—

You can apply one or more post-processing effects to give your render a touch of special fx.

Normaly this scene would be rendered like this

No effect applied

Simply add pushFX(BLOOM) in your setup and you will get this

With Unreal Bloom

Example code:


function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  hideGrid();
  
  diffuse("#ff7d00");
  
  roughness(0.2);
  
  sphere(-2, 0, 0, 2);
  diffuse("#03A9F4");
  cube(2, 0, 0, 3);
  
  //We apply a BLOOM effect
  pushFX(BLOOM);
}

function draw() {}

There are 5 effect BLOOM, LUMINOSITY, HALFTONE, PIXEL, GLITCH:

With Unreal Bloom LUMINOSITY effect HALFTONE effect PIXEL effect GLITCH effect

Using more pushFX instructions will add layers of effects.

HALFTONE and LUMINOSITY combined

For example you may use this code to have a greyscale halftone:


function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  hideGrid();
  diffuse("#ff7d00");
  
  roughness(0.2);
  
  sphere(-2, 0, 0, 2);
  diffuse("#03A9F4");
  cube(2, 0, 0, 3);
  
  //We apply LUMINOSITY effect and then (over) an HALFTONE effect
  pushFX(LUMINOSITY);
  pushFX(HALFTONE);
}

function draw() {}

You can remove all effects by calling clearFX() or you can remove individual effects by popping them from the effects stack:

var glitching = false;

function setup() {
  createCanvas3D(600, 400);
  //Change background color of the scene
  background3D("#333333");
  hideGrid();
  //Change material color to orange
  diffuse("#ff7d00");
  
  roughness(0.2);
  
  sphere(-2, 0, 0, 2);
  diffuse("#03A9F4");
  cube(2, 0, 0, 3);
  
}

function draw() {}

function keyPressed() {
  //Start glitch or stop if already started
  glitching = !glitching;
  
  if (glitching) {
    pushFX(GLITCH); //add glitch
  } else {

    //remove all effects with clearFX() or...
    popFX(); //remove last effect (glitch)
  }
}

Grid ๐Ÿ”—

By default a white grid 10x10 will appear on your scene to guide you but you can toggle it using hideGrid()/showGrid()

function setup() {
  createCanvas3D(600, 400);

  //Hide the grid
  hideGrid();

  //Create your scene
  background3D("#333333");

  diffuse("#ff7d00");
  sphere(0, 0, 0, 1);
}

function draw() {}

You can implement a keyboard button controlled grid like this:

var showingGrid = false;

function setup() {
  createCanvas3D(600, 400);
  
  background3D("#333333");

  diffuse("#ff7d00");  
  sphere(0, 0, 0, 1);
}

function draw() {}

// when pressing H key we change the showingGrid flag to its opposite and use it as parameter for showGrid()
function keyPressed() {
  if (key == "h") {
    showingGrid = !showingGrid;
    showGrid(showingGrid);
  }
}

Responsive and fullscreen ๐Ÿ”—

Make the canvas as big as possible and responsive:


function setup() {
  createCanvas3D(windowWidth, windowHeight);
  background3D("#666")
  hideToolbox(); //we need to hide buttons
  
  sphere();
  
}

function draw() {}

function windowResized() {
  resizeCanvas3D(windowWidth, windowHeight);
}

To have a real fullscreen the user need to actively do something. For example we can create a button and when we click on it we toggle fullscreen:


var button;
function setup() {
  createCanvas3D(windowWidth, windowHeight);
  background3D("#666")
  hideToolbox();
  
  sphere();
  
  button = createButton('click me');
  button.position(30, 30);
  button.mousePressed(toggleFullscreen);
  
}

function draw() {}

function toggleFullscreen() {
    let fs = fullscreen();
    fullscreen(!fs);
}

function windowResized() {
  resizeCanvas3D(windowWidth, windowHeight);
}

Custom HDRI environment maps ๐Ÿ”—

You can find public domain HDRI images here https://polyhaven.com/hdris And convert into separate PNG files here https://matheowis.github.io/HDRI-to-CubeMap/

Finally load all 6 images in a folder and use the path as parameter.

Folder and file names

Using environment map let you change completely the look and feel of your presentation:

HDRI environment map HDRI environment map HDRI environment map HDRI environment map


function setup() {
  createCanvas3D(600, 400);
  background3D("#333333");
  diffuse("white");
  
  //Place your "cubemap" 6 images in a folder and use the path as parameter  
  environment("./grass/");
  
  
  //Let's create three spheres to see the effect
  roughness(0);
  metalness(1);
  sphere(-2, 0, 0, 1);
  
  roughness(0);
  metalness(0);
  sphere(0, 0, 0, 1);

  roughness(1.0);
  metalness(0);
  sphere(2, 0, 0, 1);
}

function draw() {}

Using p5.js togheter with Diorama ๐Ÿ”—

๐Ÿ’œ Please consider donating to Processing Foundation for the incredible opportunity of having a framework such as p5.js ๐Ÿ’œ

You can use p5.js as usual because over the 3D canvas there is a p5.js canvas ๐Ÿ˜‰

Diorama together with p5.js

โš ๏ธ Limitations and caveats โš ๏ธ

  • Diorama overrides p5 WEBGL 3D function with its owns and is not affected by any p5.js transformations
  • Diorama creates 3D objects and groups so you should pay attention and don't create objects inside draw() or your computer will explode ๐Ÿ’ฅ
  • p5.js canvas is over the Diorama canvas so you probably will have to use clear() instead of background() to see your 3D scene
  • For educational purpose we run angleMode(DEGREES); by default

function setup() {
  createCanvas3D(600, 400);
  //Change background color of the scene
  background3D("#333333");
  
  // CREATE YOUR DIORAMA
  diffuse("#ff7d00");
  sphere(0, 0, 0, 1);
  
  // You may want to disable orbit camera control
  //getOrbit().enabled = false;
  
  // ๐Ÿ” if you use background() you will cover your 3D Diorama!
  
  // DRAW SOMETHING USING p5.js
  fill("#ff0077");
  stroke("white");
  strokeWeight(5);
  circle(100, 100, 50);
  
}

function draw() {
  // ๐Ÿ” You can draw on your p5.js here too: remember to use clear() instead of background()
  
  //clear();
  //circle(mouseX, mouseY, 50);
}

function mousePressed() {
  // This also works as usually
  clear();
  fill(randomColor());
  noStroke();
  var w = random(0, width);
  var h = random(0, height);
  
  rect(mouseX, mouseY, w, h);
}

Data utilities ๐Ÿ”—

You can load Google Sheets public data simply preloading from a URL:

var sheet;

function preload() {
  sheet = loadSheet("https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/edit?usp=sharing")
}

Then you can access data by rows, columns or with cell coordinates:

//using a for loop with row index
for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
  let row = sheet.rows[rowIndex];
  // row is an array of cells ordered by columns so row[0] is the first lest cell
}

//using foreach statement
for (let row of sheet.rows) {
  //do your things using row cells array
}

//using columns
for (let col of sheet.cols) {
  //col is an array of cell from top to bottom
}

//using cells coordinates (like a grid of values) and sheet.get(x, y)
for (let y = 0; y < sheet.rows.length; y++) {
  for (let x = 0; x < sheet.cols.length; x++) {
    let value = sheet.get(x, y);
    // value is the cell correspond to sheet.cols[x][y] or sheet.rows[y][x]
  }
}

In the following example we convert a random grid with 25x25 cells (value range 0.0-1.0) into an histogram.

Starting data Final result

var sheet;

const urlGoogleSheet =
  "https://docs.google.com/spreadsheets/d/1DTh1YWEAFw0_IBg-QnLlxW9zLBTJSU3ezxiEX0J_2pY/edit#gid=0";

function preload() {
  sheet = loadSheet(urlGoogleSheet);
}

function setup() {
  createCanvas3D(600, 400);
  background3D("#333");
  align(TOP);
  
  const baseW = 0.2;
  const baseD = 0.2;

  var histogram = beginGroup();
  
  for (let row = 0; row < sheet.rows.length; row++) {
    for (let col = 0; col < sheet.cols.length; col++) {
      diffuse(randomColor());
      var x = col * 0.2
      var z = row * 0.2
      var value = sheet.get(col, row);
      var h = map(value, 0, 1, 0.1, 2);
      box(x, 0, z, baseW, h , baseD);
    }
  }
  
  endGroup();
  
  histogram.setPosition(-2.5,0, -2.5);
}

function draw() {}