Cass-E Design

Design, Experiments, Games, Resources

p5.js WordPress Legacy Update

Someone contacted me recently about the p5.js WordPress Plugin I created for this site, and I've started looking into a rework that's both Gutenberg friendly & supports more features. In the meantime, I've decided to update and publish the current version of my plugin under the title 'p5js-wp-legacy'.

To recap, this plugin creates a Shortcode, [p5jswp]. This shortcode allows users to embed a p5.js script safely alongside other content, using an iframe like the p5.js web editor. Included with the plugin is a copy of p5.js. Other libraries can be included per p5.js sketch via the shortcode.

The plugin is currently available on GitHub, under GPL v2 or later. Once I've tested it and I'm fully comfortable it's in a release state I'll upload it to the Plugin Directory.


Somehow last time I did this, I missed out on the srcdoc attribute, which explicitly exists to let you specify the content of an iframe on the server/parent side. Just about every browser supports it besides Internet Explorer, which means all the browsers - and maybe more - that p5.js supports.

Data on support for the iframe-srcdoc feature across the major browsers from

So I've dropped the complicated iframe-isolation-url-passing-stuff I was doing before in favour of the srcdoc attribute, and been able to add a few more features. This is far from everything I could want, but it's significantly better than it was before.

New Features

For an in-depth description of features & usage guide, check the GitHub. I'm updating the documentation and changelog there as the plugin evolves. This is a description of how I've made certain features work rather than a usage guide.

Inline JavaScript

Inline JavaScript has been tricky, but it's feature I consider largely necessary for using something as convenient as p5.js with WordPress. There were two barriers in the way, but they solved eachother.

  • The content of the attributes of a shortcode is stored as HTML instead of plaintext. Any multiline attribute contains <br> and <p> tags.
    • The only way to strip this out, short of parsing the JavaScript, is to strip all <br> and <p> tags, even any that might be there intentionally.
  • WordPress (WP) doesn't like special characters, so all the special characters have to be encoded.
    • WP will encode any unencoded content on save. But if WP has to do so, it will unencode "s, which will break Shortcode parsing.
    • Browsers don't support HTML Entities as valid JavaScript characters.

Helpfully, the iframe will decode HTML entities naturally when it interprets the srcdoc attribute. And because everything is encoded in the editor, the only raw HTML present on the server side is created by WordPress and can safely be stripped out.

I'd still like not to require the user encoding their scripts manually / in the editor, but ironically it might make things harder.

Other New Features

  • Inline CSS Inline CSS for the interior of the iframe, much like Inline Javascript.
  • Libraries Include multiple JavaScript libraries via URL in the head.
  • Manual Width/Height Specify the HTML width/height attributes.

Other Classic Features

  • Not Inline JavaScript: JavaScript file(s) can be included in the body via URL via the script attribute.
  • Caption: The p5.js script is placed inside a figure, so this attribute specifies a caption. Supports HTML.

You can find more usage information on the GitHub page. You can find my original post about the plugin here.

Go forth and make p5.js wordpress content!

Other fun stuff!

Autoptimize Compatibility: When first released, I found a "bug" that Autoptimize stole CSS/JS out of iframe srcdocs. See issue #356 on the Autoptimize GitHub. I've updated the plugin with the recommended workaround, so it should be compatible with Autoptimize.

p5.js Off Axis Projection

p5.js Off Axis Projection

I started playing with p5.js & off axis projection recently, and I wanted to put together my demo and thoughts. Using Off Axis Projection, we can render content on a screen which appears to be truly 3-dimensional to the viewer. In order to give the impression of true 3D, we need to match the content to the user's perspective. My goal here has been to do this as accessibly as possible, using portable code anyone can run in a browser.

My demo is down below! I created a scene in Blender, and baked the lighting & textures using the Cycles renderer. Then I exported the scene to render in p5.js. This means that the content of the scene is more or less constrained to be static, but a regular browser should be able to explore relatively high fidelity scenes. It's a work in progress.

You'll probably have to click on the sketch to get any response, and if you don't have a camera, you'll have to uncheck the 'tracking' box underneath to use your mouse instead.


Space Image out the window credit to Felix Mittermeier on Pexels

Details: The project contains a second canvas that displays an overview of the contents, along with a representation of the viewer position. It also contains 3 sliders and a checkbox.

  • Checkbox is used to enable/disable head tracking, allowing you to simulate the head position with the cursor.
  • Sliders are X, Y, and Z respectively, and allow the user to offset the view from the head tracking position

I used the JavaScript library headtrackr (see dependencies), which is an older head tracking library. It cleverly aimed to make head tracking more performant on the browser by only performing actual head tracking occasionally, and using cheaper tracking every tick for greater fidelity.

What Is Projection

Projection in rendering is the process of creating a 2d representation for coordinates in a 3d world. Typically on computers we render 3d scenes with perspective or orthographic projection. As Wikipedia points out, these are really categories, but I've seen these words used most often to describe the same basic ideas.

Perspective rendering is the one you're probably most familiar with. It represents objects more or less like a camera. There's usually one vanishing point, and distant things recede in size according to the Field of View. Most video games take advantage of perspective rendering. More on Wikipedia

Orthographic is the second most common. It's like perspective, but with no adjustment over depth. It's frequently used to generate to-scale plans, charts, diagrams, or even 3D decals, that want for an image without perspective warping. More on Wikipedia

These aren't the only ways that people represent 3D space. There are other methods and subcategories of projection, and also 'faked' 3d styles included in games or rendering environments that don't truly support 3D.

Off Axis Projection

The Problem: How do you render something so that it looks 3d to the viewer. Typical projection is designed to make things appear 3d relative to eachother, and not the medium itself. These also almost always considers the screen the origin, or assumes that the viewer will be in a same basic position in front of the screen. As Robert Kooima points out in his paper Generalized Perspective Projection (see citations) this is usually good enough, although not in our case. He goes on to describe in general terms the concept of Off Axis Projection, with his use case of multiple screens for Virtual Reality.

The Solution: Anamorphosis, and viewer tracking. Anamorphosis is creating an image that looks correct from one position, or requires other special viewing conditions (ie. special glasses). One well known and entertaining example of Anamorphosis is The Ambassadors by Hans Holbein the Younger, painted in 1533. You've probably heard of it:

The Ambassadors, Hans Holbein the Younger, 1533
Image credit Wikipedia
When the painting is viewed from the correct position
Image credit Wikipedia

There's a fun (unsubstantiated) story about The Ambassadors being hung in a narrow stairway, so that the skull would seem to jump out when the viewer position became perfect, and scare the daylights out of them. The painting's Wikipedia page mentions it.

So if we can create an image that looks 3D from the correct position, and match that correct position to the viewer's position, we can do it! The technique to do this has been explored by Robert Kooima & others - the creators of headtrackr used it to make a game as Øygard notes in his tumblr post on the subject (see citations).

Off Axis Projection is essentially unlinking the vanishing point from the center of perspective rendering, so that you can move the camera and perspective around to match the user while still rendering the same content.

Michal Szkudlarek & Maria Pietruszka's paper Head-Coupled Perspective in Computer Games (see citations) was integral to my understanding of how to set up the projection matrix I needed in the time I had available, and my related algorithms in the code are modified versions of theirs.

Why p5.js? Live Rendering

My goal with this project has been to make this runnable in as many places (and for as many people) as possible. This technology requires live tracking the viewer and rendering to match their perspective, and therefore live rendering. I believe p5.js fits that goal best for now. It's quick to load, accessible on many mobile devices, and relatively cheap in terms of performance. With this setup you can (in theory) tape a tablet to the wall, and you have a gallery installation.

To get this running on as many devices as possible, we process everything we can beforehand. Lighting & textures are baked and compressed, so all the script has to do is track the viewer, project the scene, and display it. This allows us a lot of flexibility in how we do these steps, and it gives us extra performance budget for head tracking, which isn't cheap. In addition, the actual content & quality of the scene is relatively independent from the way we display it, so it could be ported to other engines like three.js or even Unity.

Because of this work, I hope my demo should run in your browser right now! Although the head tracking might be a bit laggy on some phones. If it doesn't, please feel free to contact me with any information you can provide so I can try to address the issue.


As I've noted elsewhere, this technology has several severe limitations.

  • With the use of head tracking, this only really works from the perspective of one viewer (and perhaps other viewers standing exceptionally close).
  • Head tracking is expensive, and limited to what can be recognized by the system's camera, which is limited by lighting in the environment, quality of the camera, etc. It works best at short-medium ranges.
  • The fidelity of the content and the quality of the head tracking are limited by the resources of the system.


This project would not have been possible without a pre-existing javascript Head Tracker I could pair it with. I was lucky to find @auduno's headtrackr, and lucky that it worked so well for my purposes.


Kooima, R. (2009). Generalized perspective projection. J. Sch. Electron. Eng. Comput. Sci, 6. src

Øygard, A. M. (2012, June 15). Head Tracking with WebRTC. src

Szkudlarek, M., & Pietruszka, M. (2013). Head-coupled perspective in computer games. src

More Reading


I use p5.js to create procedural, interactive artwork that's accessible and readable by the user.

p5.js is a javascript library designed to make using the html <canvas> element easy and accessible. It's used in a lot of intro coding classes, especially where art is involved. It makes rendering (even 3d perspective rendering) easier to develop and more accessible on the web. Find out more at, which has examples, resources on getting started, and more information.


Static gifs and videos 'loop' by definition. There's always a skip, repeating element, or something that proves that that the experience is entirely predefined. I've always been compelled to find those places. I find 'evidence' that something isn't really interactive. I feel like I have to find the boundaries of the algorithm, to prove that I've 'completed it' or experienced all it has to offer. For this reason, I prefer live wallpapers on my phone. They feel more alive.

In some of my procedural/interactive pieces like this one, every raindrop or snowflake or odd geometric artifact may be unique for the viewer who experiences it, on their device. That matters a lot to me. It makes art feel more 'present'.

Source Code

Everyone who views this site can view the source behind my p5.js creations. Viewers can see how I put something together. I feel that it gives more back than a gif, especially if I've done something special (or incredibly stupid) in a particular post.


I use a custom WordPress plugin to display p5.js sketches on this site! You can find out more here.

Click here to see all posts tagged p5js

p5.js Pixel Summer Storm

p5.js Pixel Summer Storm

WARNING: Flashing lightning! I would not expect this to be dangerous because it shouldn't happen too often and it's not very sharp. You should still know about it in advance!

The height of a storm we had here, made in the p5js library.
Press keys or click/tap to make the lightning flash! if It's not working, try clicking on the piece first.

Edit April 2021: Apparently a change somewhere along the lines has doubled the resolution of the live sketch. The preview thumbnail shows its original resolution. I'm not sure why yet.

I had a lot of fun with this!

This is my first time exploring fake lighting and the illusion of 3D space in p5js. I've done fake shadows, and I've changed the entire colours of objects based on light, but I haven't ever tried to create highlights around the edges of shapes, or tried for a really '3D' space rather than just stylized 2.5D.

p5.js WordPress Plugin

Update March 2021: I polished and published the plugin. Find out more here: p5.js WordPress Legacy Update or head straight to the GitHub.

This custom plugin allows me to embed p5.js projects in my WordPress posts/pages using a shortcode!

I use it in posts like AnAbstractHug, Pixel Summer Storm, and more!

As always if you're interested in one of my plugins, please contact me! I haven't released this officially yet because the code is unpolished, but if you're interested I can give it another pass!

The Grand Story

I started trying with a plugin called ProcessingJS for WordPress by Rolf van Gelder - Which was for ProcessingJS and not p5js! p5js scripts seem to require a blank document, with p5js and the script placed in the header.

My answer was an iframe, which lets you embed a mini-webpage into another page - this way, multiple p5js scripts can be added to posts!

I couldn't find a way to specify the contents of an iframe in-line in php, because iframes embed pre-existing content. I created a php template file for all p5js scripts called p5js-iframe.php for this.

Because the iframe was an independent document, I couldn't tell it directly what scripts to include, so I passed the script file locations via GET request / query string in the source url:

<!-- the iframe source url with file locations passed -->
iframe src="p5js-iframe.php?p5js=/wp-content/plugins/p5js-wp/js/p5.min.js&src=/media/AnAbstractHug.js"
<!-- the php document translating those into script embeds -->
<script type="text/javascript" src="<?php echo $_GET['p5js']; ?>"></script>
	<?php if (isset($_GET['src'])) { ?>
		<script type="text/javascript" src=<?php echo $_GET['src']; ?>></script>

This means I can't embed the script contents directly in the post. I can't pass the script to the iframe directly because urls have a max length on some platforms, so it might work inconsistently. This means I need to pass the link to an external file into the iframe for it to reference. I upload these like you would an image, and it seems to work fine. It's much cleaner than trying to edit the code inside the post anyhow.

Thanks for reading and I hope you found it interesting!