# Backbuffer in p5js

**URL:** <https://discourse.processing.org/t/backbuffer-in-p5js/29769>\
**Category:** p5.js\
**Created:** [May 1, 2021, 12:36am UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769 "2021-05-01T00:36:45Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![BigBigRed](https://avatars.discourse-cdn.com/v4/letter/b/d6d6ee/32.png) [@BigBigRed](https://discourse.processing.org/u/BigBigRed)\
**Post date:** [May 1, 2021, 12:36am UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/1 "2021-05-01T00:36:45Z")

</div>

I found a shader on the GLSL Sandbox website that I want to use. (It might be their e#375.15.)

This shader wants to use WebGL’s backbuffer feature. It seems from a Google search that p5js does not allow reference to backbuffer. The p5js example that i did find uses creategrahics (same dimensions as the canvas) and ‘backbuffer.image(canvas, width \* -0.5, height \* -0.5, width, height)’ to populate it in the sketch’s draw function, so my question is ‘Is this (using createGrahics) really what I have to do in p5js when a shader wants to use additional buffers?’.

After extensive diagnostics and try this(es), it seems that on createGraphics there is a problem with the alpha part of the color, additionally everything ends up with Y values reversed and the canvas does not work right (but it will do something at least).

Thanks

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [May 1, 2021, 7:26am UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/2 "2021-05-01T07:26:01Z")

</div>

Short answer is yes.

p5.js’ webgl is work in progress and not all the features are complete. I’m sure you can fix the issues you mentioned by tweaking parameters but it may be more straightforward to use other libraries like three.js if you are just using fragment shaders.

Now the question is if you want to share what you did; otherwise we can only give you high level comments 🙂

---

<div class="post-metadata">

**Author:** ![BigBigRed](https://avatars.discourse-cdn.com/v4/letter/b/d6d6ee/32.png) [@BigBigRed](https://discourse.processing.org/u/BigBigRed)\
**Post date:** [May 1, 2021, 5:31pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/3 "2021-05-01T17:31:38Z")

</div>

I worked on this some more. I found that the initial p5js sketch that i started with, was passing frameCount rather than elapsed time on to the frag shader. After changing, I am now getting much better results.(altho what I have produces very different results than what is on GLSL Sandbox).

My frag shader (below) will seem very odd to you. I basically added the GLSL Sandbox code to the top of the P5js Frag shader ( The original shader is still functional within here.)

ifdef GL\_ES  
precision highp float;  
#endif

uniform float pixel\_density;  
uniform vec2 res;  
uniform sampler2D buffer;  
uniform float time;  
uniform vec2 mouse;

void main() {  
// gl\_FragCoord.xy

```
float positionX = gl_FragCoord.x / res.x;
float positionY = 1.0 - (gl_FragCoord.y/ res.y);
vec2 position = vec2(positionX, positionY);
vec2 pixel = 1./res;
vec4 me = vec4 ( 1.0);
me = texture2D(buffer, position);

```

vec4 source;  
vec2 wilbur;

```
vec2 rnd = vec2(mod(fract(sin(dot(position + time * 0.001, vec2(14.9898,78.233))) * 43758.5453), 1.0), mod(fract(sin(dot(position + time * 0.001, vec2(24.9898,44.233))) * 27458.5453), 1.0));

vec2 nudge = vec2(12.0 + 10.0 * cos(time * 0.03775), 12.0 + 10.0 * cos(time * 0.02246));

vec2 rate = -0.005 + 0.02 * (0.5 + 0.5 * cos(nudge * (position.yx - 0.5) + 0.5 + time * vec2(0.137, 0.262)));

float mradius = 0.004;// initially 0.007
if (length(position-mouse) < mradius) {
	me.r = 0.5 + 0.5*sin(time * 1.234542);
	me.g = 0.5 + 0.5*sin(3.0 + time * 1.64242);
	me.b = 0.5 + 0.5*sin(4.0 + time * 1.444242);
    me.a = 1.0;
} else {
	rate *= 6.0 * abs(vec2(0.5, 0.5) - mouse);
	rate += 0.5 * rate.yx;
	vec2 mult = 1.0 - rate;
	vec2 jitter = vec2(1.1 / res.x,
	                   1.1 / res.y);
	vec2 offset = (rate * mouse) - (jitter * 0.5);
	// wilbur = position * mult + offset + jitter * rnd;
  source = texture2D(buffer, position * mult + offset + jitter * rnd);
	
	me = me * 0.05 + source * 0.95;
}

```

// This is where the original p5js backbuffer sketch starts  
vec2 st = gl\_FragCoord.xy;  
vec3 col = vec3(1.0);  
vec2 tc = st / (res \* pixel\_density);  
vec2 buffer\_tc = st / (res \* pixel\_density);  
buffer\_tc.y = 1. + buffer\_tc.y \* -1.;

// texture2D  
vec3 buffer\_samp = texture2D(buffer, buffer\_tc).xyz;  
buffer\_samp = vec3(1.0) - buffer\_samp;

float r = 0.03; // Initially 0.20  
float ell = smoothstep(r,r-0.01,length((tc-mouse) \* res / res.y));

col = vec3(1.0 - ell) - buffer\_samp.xyz \* 0.98;  
if (col.x \> 0.93) {col = vec3 (1.0);}

gl\_FragColor = vec4(col,1.0); // For the original p5js backbuffer sketch

vec4 localColor = vec4(me.r, me.g, me.b, 1.0);  
gl\_FragColor = (localColor); // Comment this out and you get the original sketch  
// gl\_FragColor = vec4((wilbur), 0.0, 0.8);  
}

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [May 1, 2021, 6:34pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/4 "2021-05-01T18:34:23Z")

</div>

thanks but please format the code!

[https://www.khm.de/~n.hieda/discourse-code.mp4](https://www.khm.de/~n.hieda/discourse-code.mp4)

---

<div class="post-metadata">

**Author:** ![BigBigRed](https://avatars.discourse-cdn.com/v4/letter/b/d6d6ee/32.png) [@BigBigRed](https://discourse.processing.org/u/BigBigRed)\
**Post date:** [May 2, 2021, 3:36pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/5 "2021-05-02T15:36:43Z")

</div>

I want to thank you for trying to help me here. I am sorry but I simply do a copy from the p5js Web editor of my fragment shader, I paste it here and somehow, we end up with greyed areas and the a scrolly bar and I have no idea how to control whatever autoformat is taking over.

#ifdef GL\_ES  
precision highp float;  
#endif

uniform float pixel\_density;  
uniform vec2 res;  
uniform sampler2D buffer;  
uniform float time;  
uniform vec2 mouse;

void main() {  
// this is a fork (or port) of [GLSL Sandbox](http://GLSLSandbox.com/e#375.15). I did not see that its author gave any real name or internet persona or anything.  
// gl\_FragCoord.xy

```
float positionX = (gl_FragCoord.x / res.x);
float positionY = 1.0 - (gl_FragCoord.y/ res.y);
// vec2 buffer_tc = st / (res * pixel_density);
// buffer_tc.y = 1. + buffer_tc.y * -1.; 
vec2 position = vec2(positionX, positionY);
vec2 pixel = 1./res;
vec4 me = vec4 ( 1.0);
me = texture2D(buffer, position);

```

vec4 source;  
vec2 wilbur;

```
vec2 rnd = vec2(mod(fract(sin(dot(position + time * 0.001, vec2(14.9898,78.233))) * 43758.5453), 1.0), mod(fract(sin(dot(position + time * 0.001, vec2(24.9898,44.233))) * 27458.5453), 1.0));

vec2 nudge = vec2(12.0 + 10.0 * cos(time * 0.03775), 12.0 + 10.0 * cos(time * 0.02246));

vec2 rate = -0.005 + 0.02 * (0.5 + 0.5 * cos(nudge * (position.yx - 0.5) + 0.5 + time * vec2(0.137, 0.262)));

float mradius = 0.02;// initially 0.007
if (length(position-mouse) < mradius) {
	me.r = 0.5 + 0.5*sin(time * 1.234542);
	me.g = 0.5 + 0.5*sin(3.0 + time * 1.64242);
	me.b = 0.5 + 0.5*sin(4.0 + time * 1.444242);
    me.a = 1.0;
} else {
	rate *= 6.0 * abs(vec2(0.5, 0.5) - mouse);
	rate += 0.5 * rate.yx;
	vec2 mult = 1.0 - rate;
	vec2 jitter = vec2(1.1 / res.x,
	                   1.1 / res.y);
	vec2 offset = (rate * mouse) - (jitter * 0.5);
	// wilbur = position * mult + offset + jitter * rnd;
  source = texture2D(buffer, position * mult + offset + jitter * rnd);
  source *= vec4( 1.0001, 1.0001, 1.0001, 1.02);;
	
	me = me * 0.05 + source * 0.95;
}

```

// This is where the original p5js backbuffer sketch starts  
vec2 st = gl\_FragCoord.xy;  
vec3 col = vec3(1.0);  
vec2 tc = st / (res \* pixel\_density);  
vec2 buffer\_tc = st / (res \* pixel\_density);  
buffer\_tc.y = 1. + buffer\_tc.y \* -1.;

// texture2D  
vec3 buffer\_samp = texture2D(buffer, buffer\_tc).xyz;  
buffer\_samp = vec3(1.0) - buffer\_samp;

float r = 0.03; // Initially 0.20  
float ell = smoothstep(r,r-0.01,length((tc-mouse) \* res / res.y));

col = vec3(1.0 - ell) - buffer\_samp.xyz \* 0.98;  
if (col.x \> 0.93) {col = vec3 (1.0);}

gl\_FragColor = vec4(col,1.0); // For the original p5js backbuffer sketch

vec4 localColor = vec4(me.r, me.g, me.b, 1.0);  
// gl\_FragColor = (localColor);  
// gl\_FragColor = vec4((wilbur), 0.0, 0.8);  
}

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [May 2, 2021, 3:44pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/6 "2021-05-02T15:44:13Z")

</div>

can you check my post above? there is `</>` button to format your code.

---

<div class="post-metadata">

**Author:** ![BigBigRed](https://avatars.discourse-cdn.com/v4/letter/b/d6d6ee/32.png) [@BigBigRed](https://discourse.processing.org/u/BigBigRed)\
**Post date:** [May 2, 2021, 5:13pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/7 "2021-05-02T17:13:22Z")

</div>

```auto
#ifdef GL_ES
precision highp float;
#endif

uniform float pixel_density;
uniform vec2 res;
uniform sampler2D buffer;
uniform float time;
uniform vec2 mouse;

void main() {
  // this is a fork (or port) of GLSLSandbox.com/e#375.15. I did not see that its author gave any real name or internet persona or anything.
  // gl_FragCoord.xy
  
    float positionX = (gl_FragCoord.x / res.x);
    float positionY = 1.0 - (gl_FragCoord.y/ res.y);
    // vec2 buffer_tc = st / (res * pixel_density);
    // buffer_tc.y = 1. + buffer_tc.y * -1.; 
    vec2 position = vec2(positionX, positionY);
	vec2 pixel = 1./res;
    vec4 me = vec4 ( 1.0);
	me = texture2D(buffer, position);
  vec4 source;
  vec2 wilbur;

	vec2 rnd = vec2(mod(fract(sin(dot(position + time * 0.001, vec2(14.9898,78.233))) * 43758.5453), 1.0), mod(fract(sin(dot(position + time * 0.001, vec2(24.9898,44.233))) * 27458.5453), 1.0));
  
	vec2 nudge = vec2(12.0 + 10.0 * cos(time * 0.03775), 12.0 + 10.0 * cos(time * 0.02246));
  
	vec2 rate = -0.005 + 0.02 * (0.5 + 0.5 * cos(nudge * (position.yx - 0.5) + 0.5 + time * vec2(0.137, 0.262)));

	float mradius = 0.02;// initially 0.007
	if (length(position-mouse) < mradius) {
		me.r = 0.5 + 0.5*sin(time * 1.234542);
		me.g = 0.5 + 0.5*sin(3.0 + time * 1.64242);
		me.b = 0.5 + 0.5*sin(4.0 + time * 1.444242);
        me.a = 1.0;
	} else {
		rate *= 6.0 * abs(vec2(0.5, 0.5) - mouse);
		rate += 0.5 * rate.yx;
		vec2 mult = 1.0 - rate;
		vec2 jitter = vec2(1.1 / res.x,
		                   1.1 / res.y);
		vec2 offset = (rate * mouse) - (jitter * 0.5);
		// wilbur = position * mult + offset + jitter * rnd;
      source = texture2D(buffer, position * mult + offset + jitter * rnd);
      source *= vec4( 1.0001, 1.0001, 1.0001, 1.02);;
		
		me = me * 0.05 + source * 0.95;
	}
  
  // This is where the original p5js backbuffer sketch starts
  vec2 st = gl_FragCoord.xy;
  vec3 col = vec3(1.0);
  vec2 tc = st / (res * pixel_density);
  vec2 buffer_tc = st / (res * pixel_density);
  buffer_tc.y = 1. + buffer_tc.y * -1.; 
  
  // texture2D
  vec3 buffer_samp = texture2D(buffer, buffer_tc).xyz;
  buffer_samp = vec3(1.0) - buffer_samp;
  
  float r = 0.03; // Initially 0.20
  float ell = smoothstep(r,r-0.01,length((tc-mouse) * res / res.y));
  
  col = vec3(1.0 - ell) - buffer_samp.xyz * 0.98;
  if (col.x > 0.93) {col = vec3 (1.0);}
  
  gl_FragColor = vec4(col,1.0); // For the original p5js backbuffer sketch
  
  vec4 localColor = vec4(me.r, me.g, me.b, 1.0);
  gl_FragColor = (localColor);
  // gl_FragColor = vec4((wilbur), 0.0, 0.8);
}

```

type or paste code here

```auto

```

---

<div class="post-metadata">

**Author:** ![BigBigRed](https://avatars.discourse-cdn.com/v4/letter/b/d6d6ee/32.png) [@BigBigRed](https://discourse.processing.org/u/BigBigRed)\
**Post date:** [May 2, 2021, 5:15pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/8 "2021-05-02T17:15:09Z")

</div>

It looks like that worked.

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [May 2, 2021, 5:52pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/9 "2021-05-02T17:52:33Z")

</div>

cool, but can you also post the js code?

---

<div class="post-metadata">

**Author:** ![BigBigRed](https://avatars.discourse-cdn.com/v4/letter/b/d6d6ee/32.png) [@BigBigRed](https://discourse.processing.org/u/BigBigRed)\
**Post date:** [May 2, 2021, 6:11pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/10 "2021-05-02T18:11:19Z")

</div>

The vertex shader below. Sketch.js is a little further down.  
the mouse movements do not go the shader, Sketch.js autogenerates movements so I can just watch it go.

```auto
// https://github.com/aferriss/p5jsShaderExamples
// 여기서 버텍스 쉐이더는 이미지를 그려줄 직사각형을 그리는 기능만 하고 있다.

#ifdef GL_ES
precision highp float;
#endif

attribute vec3 aPosition;

// Always include this to get the position of the pixel and map the shader correctly onto the shape

void main() {

  // Copy the position data into a vec4, adding 1.0 as the w parameter
  vec4 positionVec4 = vec4(aPosition, 1.0);

  // Scale to make the output fit the canvas
  positionVec4.xy = positionVec4.xy * 2.0 - 1.0; 

  // Send the vertex information on to the fragment shader
  gl_Position = positionVec4;

// This is sketch.js code
}type or paste code here// 쉐이더로 그려주는 부분
let sh_render;
let sketchRotator =0;
let XYSizer = 50; 

// 백버퍼 (이전 프레임을 기록하는 화면에 실제로 그려지지는 않는 캔버스)
let backbuffer;
// 메인 캔버스
let canvas;

function preload() {
  sh_render = loadShader("shaders/render.vert", "shaders/render.frag");
}

function setup() {
  pixelDensity(1);
  
  //canvas = createCanvas(windowWidth, windowHeight, WEBGL);
  canvas = createCanvas(1360, 730, WEBGL);
  
  backbuffer = createGraphics(width, height, WEBGL);
  backbuffer.clear();
  backbuffer.background(130);
}

function draw() {
  backbuffer.clear();
  backbuffer.image(canvas, width * -0.5, height * -0.5, width, height);
  
  clear();
  
  shader(sh_render);
  sh_render.setUniform("buffer", backbuffer);
  sh_render.setUniform("res", [width, height]);
  sh_render.setUniform("pixel_density", [pixelDensity()]);
  sh_render.setUniform("time", millis()/ 400);
  
  let mx = mouseX / width;
  mx = (0.3 + cos(sketchRotator) * .15) * (1 + abs(cos(sketchRotator * 3)));
  let my = 1 + (-1 * mouseY / height); 
  my = (0.3 + sin(sketchRotator) * .15) * (1 + abs(sin(sketchRotator * 3))); 
  // print("MX is "+round(mx,2)+", MY is "+round(my,2));
  sh_render.setUniform("mouse", [mx, my]);
  
  rect(0, 0, width, height);
  
  if (frameCount % 600 == 200) {
    // print("Frame Rate "+round(frameRate(),2));
  }
  sketchRotator += 0.005;
}

function keyPressed() {
  if (keyCode == ALT) {
 let fs = fullscreen();
    fullscreen(!fs);
    noCursor();
  }
  if (key == 'x') {print("this should work");}
}

```

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [May 3, 2021, 4:45pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/11 "2021-05-03T16:45:41Z")

</div>

I tested it and it seems working but is there any issues or are you simply sharing your work?  
[https://editor.p5js.org/micuat/sketches/dRJzZK5gu](https://editor.p5js.org/micuat/sketches/dRJzZK5gu)

---

<div class="post-metadata">

**Author:** ![BigBigRed](https://avatars.discourse-cdn.com/v4/letter/b/d6d6ee/32.png) [@BigBigRed](https://discourse.processing.org/u/BigBigRed)\
**Post date:** [May 3, 2021, 5:41pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/12 "2021-05-03T17:41:10Z")

</div>

I have no unresolved issues with this sketch right now.

My original question was whether I had to use ‘createGraphics’ when a shader that I was trying to replicate wanted to use WebGL’s backbuffer… And you did answer that question. I know that p5js can use some javascript things like ‘forEach’ and prototype (and those are not included in the p5js website’s reference area). I thought that maybe there was a way to use WebGL backbuffer and I just did not know how. … I am not even halfway through my second year with p5js, so I am definitely challenged on some things.

Thanks

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [May 3, 2021, 8:45pm UTC](https://discourse.processing.org/t/backbuffer-in-p5js/29769/13 "2021-05-03T20:45:57Z")

</div>

That is great and indeed this is a difficult example to make by yourself!

One suggestion would be to use two p5.Graphics objects. Right now you copy `canvas` to `backbuffer` then render `canvas`. This works perfectly in your case. But this becomes problematic if you want to use more layers - for example, if you draw a text on top of the `canvas`, this will affect the `backbuffer` in the next frame. If you prepare, say, `backbuffer0` and `backbuffer1`, you can do something like this (I haven’t tested the code)

```javascript
function draw() {
  backbuffer0.shader(sh_render);
  sh_render.setUniform("buffer", backbuffer1);
  ...
  backbuffer0.rect(0, 0, width, height);

  image(backbuffer0, width * -0.5, height * -0.5, width, height);

  [backbuffer0, backbuffer1] = [backbuffer1, backbuffer0]; // swap
}

```

this is so-called ping-pong (because it’s like a ping-pong rally) and useful because, as I mentioned above, they are not dependent on what is drawn on `canvas`.
