A library for efficiently drawing to a texture in p5 WebGL mode

Overview

p5.Framebuffer

A library for efficiently drawing to a texture in p5 WebGL mode.

A Framebuffer is kind of like a p5.Graphics: it lets you draw to a canvas, and then treat that canvas like an image. A Framebuffer, on the other hand:

  • is faster: it shares the same WebGL context as the rest of the sketch, so it doesn't need to copy extra data to the GPU each frame
  • has more information: you can access the WebGL depth buffer as a texture, letting you do things like write focal blur shaders
  • is WebGL only: this will not work in 2D mode! p5.Graphics should be fine for that.

Read more about the motivation for this and how focal blur shaders work in this blog post on the subject.

Usage

Add the library to your source code, after loading p5 but before loading your own code:

">
<script type="text/javascript" src="p5.Framebuffer.js">script>

Create a Framebuffer in setup and use it in draw:

let fbo

function setup() {
  createCanvas(400, 400, WEBGL)
  fbo = createFramebuffer()
}

function draw() {
  // Draw a sphere to the Framebuffer
  fbo.draw(() => {
    clear()
    push()
    noStroke()
    fill(255, 0, 0)
    rotateX(frameCount * 0.01)
    rotateY(frameCount * 0.01)
    box(50)
    pop()
  })

  // Do something with fbo.color or dbo.depth
  texture(fbo.depth)
  plane(width, height)
}

Notes:

  • draw() uses the same p5 context as the rest of your sketch! Make sure to wrap your callback code in a push() and pop() to ensure your settings don't leak out into your non-Framebuffer code.
  • When you resizeCanvas, the Framebuffer will automatically resize accordingly. You probably will want to clear it and redraw to it if you had a texture cached.

Examples

In this repo:

External:

More coming soon!

Comments
  • Issue with p5.text

    Issue with p5.text

    Hi dev team, I have been using this lib for a couple of weeks now, and I like it a lot.

    But for some reason, I cannot manage to draw some text on the canvas. I have tried a lot of options, like using a dedicated-to-texts frameBuffer inside mine, and nothing. The only message I happen to have is: p5.js says: texture() was expecting p5.Image|p5.MediaElement|p5.Graphics for the first parameter, received object instead. . This message is just a friendly p5 message, and doesn't block anything. I precise, I use this lib in most of my sketches and I have no issues with it (except when I want to draw some text).

    I import the lib in index.html (like all others) like: <script type="text/javascript" src="core/externalLibs/p5/p5.Framebuffer.min.js"></script>

    Worth mentioning:

    p5.js v1.4.0

    I join a code sample down there. I have added an ellipse in the draw function to ensure P5 works.

    First case: I have nothing on screen (except the ellipse and the grey-ish background set as 100).

    let textToShow = "FINALLY SOME TEXT";
    let blockbold;
    let TEXT_FB, F1_FB;
    
    function preload() {
        blockbold = loadFont('assets/fonts/BlockBold.ttf');
    }
    
    function setup() {
        // creates canvas in WEBGL
        CNV = createCanvas(windowWidth, windowHeight, WEBGL);
    
        // build framebuffer objects
        F1_FB = createFramebuffer({ colorFormat: 'float' });
        TEXT_FB = createFramebuffer({ colorFormat: 'float' });
    }
    
    function draw() {
        background(0);
        F1_FB.draw(() => {
            clear();
            background(100);
            push();
            drawSomeTextHere();
            pop();
        });
        push()
        texture(F1_FB.color)
        plane(CNV.width, -CNV.height)
        pop()
    
        push()
        fill(360, 100, 100);
        ellipse(mouseX - CNV.width / 2, mouseY - CNV.height / 2, 50, 50);
        drawSomeTextHere();
        pop()
    }
    
    function drawSomeTextHere() {
        push();
        stroke(255);
        strokeWeight(10);
        textSize(30);
        textFont(blockbold);
        text(textToShow, 0, 0);
        pop();
    }
    

    Second case, I have text on screen when I remove the script import in index.html.

    let textToShow = "FINALLY SOME TEXT";
    let blockbold;
    
    function preload() {
        blockbold = loadFont('assets/fonts/BlockBold.ttf');
    }
    
    function setup() {
        // creates canvas in WEBGL
        CNV = createCanvas(windowWidth, windowHeight, WEBGL);
    }
    
    function draw() {
        background(0);
        push();
        fill(360, 100, 100);
        ellipse(mouseX - CNV.width / 2, mouseY - CNV.height / 2, 50, 50);
        drawSomeTextHere();
        pop();
    }
    
    function drawSomeTextHere() {
        push();
        stroke(255);
        strokeWeight(10);
        textSize(30);
        textFont(blockbold);
        text(textToShow, 0, 0);
        pop();
    }
    

    Thanks for your help 🙏

    opened by akaRicane 3
  • add support for depth of field

    add support for depth of field

    • The blur amount will start to be gained while the depth is outside the given depth of field (dof).
    • The focal target is located in the centre of the depth of field.
    • Use setDof() to set the depth of field.
    • Defaults to 0.
    opened by luyotw 3
  • Support floating point textures

    Support floating point textures

    I'd need to just add gl.getExtension('OES_texture_float') in the constructor and then use gl.FLOAT here: https://github.com/davepagurek/p5.Framebuffer/blob/main/p5.Framebuffer.js#L119

    enhancement 
    opened by davepagurek 1
  • Make fbos come with their own cameras

    Make fbos come with their own cameras

    This will deal with the fact that the projection matrix will need to change when sizes are different: https://github.com/davepagurek/p5.Framebuffer/issues/14

    opened by davepagurek 0
  • Support antialiasing

    Support antialiasing

    This will involve:

    • Creating a WebGL2 context
    • If it's available:
      • Creating an antialiased renderbuffer
      • Blitting that renderbuffer to the framebuffer texture when asked for
    • Otherwise:
      • Doubling the fbo's dimensions to approximate supersampling
    enhancement 
    opened by davepagurek 0
  • Support different widths/heights from the parent canvas

    Support different widths/heights from the parent canvas

    This will involve updating the projection matrix's aspect ratio to match the framebuffer, and managing calls to camera functions that happen within the fbo callback.

    enhancement 
    opened by davepagurek 0
  • Support nesting `draw` calls

    Support nesting `draw` calls

    Right now I think this breaks:

    fbo1.draw(() => {
      fbo2.draw(() => {
        // etc
      })
      texture(fbo2.color)
      rect(0, 0, width, height)
    })
    

    This is because the draw call binds the main canvas when it finishes: https://github.com/davepagurek/p5.Framebuffer/blob/main/p5.Framebuffer.js#L206

    To fix this, it would need to record whatever context is currently bound before it starts, and then re-bind that at the end again instead of binding null (the main canvas.)

    As a temporary workaround, this should be fine:

    fbo2.draw(() => {
      // etc
    })
    fbo1.draw(() => {
      texture(fbo2.color)
      rect(0, 0, width, height)
    })
    
    bug 
    opened by davepagurek 0
  • Make Framebuffer match alpha settings of the parent context

    Make Framebuffer match alpha settings of the parent context

    Fixes https://github.com/davepagurek/p5.Framebuffer/issues/5

    In p5 1.4.1, WebGL graphics/canvases default to not having an alpha channel to make alpha blending less confusing by default (thanks @SableRaf for finding this!) Previously, p5.Framebuffer would always have an alpha channel, leading to unexpected results in p5 1.4.1.

    After this change:

    • The framebuffer will create an alpha channel if and only if the WebGL context it's attached to has one
    • The example sketch calls background(255) after clear(), since the behaviour of clear() looks different from v1.4.0 to v1.4.1 if you don't also set a background color
    opened by davepagurek 0
Releases(v0.0.7)
Owner
Dave Pagurek
Programmer and digital artist. MSc from UBC CS '21, UWaterloo Software Engineering '19.
Dave Pagurek
Command-Line wordle with a usable library

Clordle Command-Line wordle with a usable library! Contents Installation Usage (CLI) Usage (Library) Installation Installing clordle is fairly easy, b

Piero Maddaleni 4 Feb 25, 2022
TypeScript library implementing Chess

Created primarily for our chess React project.

COMP2022 3 Mar 5, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
p5.grain is a p5.js addon for conveniently adding grain and texture overlays to artworks.

?? p5.grain p5.grain is a p5.js addon for conveniently adding grain and texture overlays to artworks. p5.grain was also created with fxhash projects i

meezwhite 39 Dec 24, 2022
Hashmat Noorani 4 Mar 21, 2023
MDN-Dark-Mode - Simple extension to add a dark mode with different themes to the MDN Web Docs website

MDN-Dark-Mode Information Chrome and Firefox extension that adds a dark mode wit

Santiago Galán Barlo 2 Mar 18, 2022
🌓 Add dark mode/night mode custom elements to your website.

dark-mode A custom element that allows you to easily put a Dark Mode ?? toggle. so you can initially adhere to your users' preferences according to pr

小弟调调™ 12 Oct 20, 2022
A JavaScript library dedicated to graph drawing

sigma.js - v1.2.1 Sigma is a JavaScript library dedicated to graph drawing, mainly developed by @jacomyal and @Yomguithereal. Resources The website pr

Alexis Jacomy 10.3k Jan 3, 2023
React + Canvas = Love. JavaScript library for drawing complex canvas graphics using React.

React Konva React Konva is a JavaScript library for drawing complex canvas graphics using React. It provides declarative and reactive bindings to the

konva 4.9k Jan 9, 2023
JavaScript library for object-based canvas drawing

oCanvas - Object-based canvas drawing oCanvas makes canvas development easier to understand and do, by creating a bridge between the native pixel draw

Johannes Koggdal 483 Jan 4, 2023
JavaScript library to make drawing animation on SVG

vivus.js Demo available on http://maxwellito.github.io/vivus Play with it on Vivus Instant Vivus is a lightweight JavaScript class (with no dependenci

maxwellito 14.5k Jan 3, 2023
A simple, no-hassle library for efficiently querying Your Enrollment Services.

@vanderbilt/yes-api A simple, no-hassle library for efficiently querying Your Enrollment Services. Created by Dylan Hanson (jovialis) NOTE: THIS MODUL

Dylan Hanson 2 Jan 25, 2022
Cross provider map drawing library, supporting Mapbox, Google Maps and Leaflet out the box

Terra Draw Frictionless map drawing across mapping providers. TerraDraw centralises map drawing logic and provides a host of out the box drawing modes

James Milner 106 Dec 31, 2022
JustGage is a handy JavaScript plugin for generating and animating nice & clean dashboard gauges. It is based on Raphaël library for vector drawing.

JustGage JustGage is a handy JavaScript plugin for generating and animating nice & clean dashboard gauges. It is based on Raphaël library for vector d

Bojan Djuricic 1.8k Jan 3, 2023
A JavaScript library for drawing network graphs.

Gnet.js Gnet is a JavaScript library for network graph visualization, developed by Goutham. First I want to thank D3.js developers for creating such a

Goutham S 1 May 9, 2021
A renderer agnostic two-dimensional drawing api for the web.

Two.js A two-dimensional drawing api meant for modern browsers. It is renderer agnostic enabling the same api to render in multiple contexts: webgl, c

Jono Brandel 7.9k Dec 31, 2022
React components for efficiently rendering large lists and tabular data

React components for efficiently rendering large lists and tabular data. Check out the demo for some examples. Sponsors The following wonderful compan

Brian Vaughn 24.5k Jan 7, 2023
React components for efficiently rendering large lists and tabular data

react-window React components for efficiently rendering large lists and tabular data React window works by only rendering part of a large data set (ju

Brian Vaughn 13.5k Jan 4, 2023