Skip to content

[p5.js 2.0 RFC Proposal]: Renderer system refactor #7016

Closed
@limzykenneth

Description

@limzykenneth

Increasing access

A more flexible renderer system enables p5.js to be used in a larger variety of rendering situation that a user may need, eg. to be print medium, controlling plotter/robot arm, SVG, and more. This enables context in which the default provided renderers of p5.js may not meet some user's specific needs (such as a renderer for Braille display perhaps?)

Which types of changes would be made?

  • Breaking change (Add-on libraries or sketches will work differently even if their code stays the same.)
  • Systemic change (Many features or contributor workflows will be affected.)
  • Overdue change (Modifications will be made that have been desirable for a long time.)
  • Unsure (The community can help to determine the type of change.)

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • Build process
  • Unit testing
  • Internationalization
  • Friendly errors
  • Other (specify if possible)

What's the problem?

p5.js 1.0 is bundled with two renderers: 2D and WebGL. They corresponds to the HTML Canvas 2d and webgl context respectively. However, there had been requests over the years to add additional renderers such as an SVG renderer or a renderer with scene graph capabilities. As the web evolve, we are also seeing new a possible standard renderer being developed, ie. WebGPU.

As currently implemented, adding a new renderer to p5.js is not an easy task which involves many parts that expects to behave differently depending on whether the current sketch is in 2D or WebGL mode.

createCanvas(400, 400, WEBGL);

The constant value to determine whether a canvas is in 2D or WEBGL mode is also not easily extendable by addon libraries.

What's the solution?

With p5.js 2.0, the renderer system is redesigned and tweaked with a few key points.

  1. p5.Renderer class which both p5.Renderer2D and p5.RendererGL classes inherit from will now act more like an abstract class that it is meant to be.
    • The p5.Renderer class will determine a set of basic properties and methods any renderer class inheriting from it should implement, while extra functionalities can still be implemented on top. (eg. all renderers should implement the ellipse() method but the WebGL renderer will also implement a sphere() method that 2D renderers don't need).
    • The p5.Renderer class should never be instantiated directly.
  2. The core will not have implicit knowledge of what renderers are available. Previously the two modes supported (P2D and WEBGL) are harded coded into functions like createCanvas() making creating a new rendering mode difficult without also modifying core functionalities.
    • A list of renderers should be kept under the p5.renderers object with value being the class object of the renderer (that inherits from p5.Renderer class).
p5.renderers = {
  [constants.P2D]: Renderer2D,
  [constants.WEBGL]: RendererGL
};

For an addon library to create a new renderer to work with p5, it will need to first create a class that inherits and implements the p5.Renderer abstract class, then register the renderer under the p5.renderers object.

(function(p5){
  class MyRenderer extends p5.Renderer {
    ellipse(x, y, w, h) {
      // ...
    }

    // ...
  }

  p5.registerAddon((p5, fn, lifecycles) => {
    p5.renderers.myRenderer = MyRenderer;
  });
})(p5);

When a sketch author wants to use the addon provided renderer above, they can use the following code when creating a canvas.

function setup(){
  createCanvas(400, 400, 'myRenderer');
}

For usage that are more similar to p5.js' own renderers, constants registration can be exposed to addon library authors as well. In this case, it is recommended to make the constant value a Symbol matching behavior in the core library itself.

Core question

Part of the motivation for this proposal is to enable a leaner build of the library for users who only use the 2D renderer but not the WebGL renderer and vice versa. If someone uses only the 2D canvas, there is no need for most if not all of the WebGL components to be included.

This creates a question, should p5.js still be bundled with both renderers for distribution? What about new renderers in the future? There are a few options for this:

  • Bundling both 2D and WebGL renderers, bundling also any new renderers if they are included in the library directly.
  • Bundle only 2D renderer. Log a warning message if the sketch author tries to create a WebGL canvas without loading in the WebGL renderer as an addon.
  • Bundle no renderer. All and any renderers should be included as addons.

The third options is probably too extreme and probably should not be considered. Either of the first two options are open for discussions.

Pros (updated based on community comments)

  • It will be much easier to maintain and extend/add renderers to p5.js with the tweaked renderer system
  • Addon libraries will be able to add their own renderers while the users will still be able to use mostly the same p5.js sketching API

Cons (updated based on community comments)

  • Some refactoring on the renderer side of things will be required
  • A more standardized approach to defining what a renderer should include (ie. the p5.Renderer abstract class) will be needed.

Proposal status

Under review

Metadata

Metadata

Type

No type

Projects

Status

Completed

Relationships

None yet

Development

No branches or pull requests

Issue actions