Skip to content

Unable to resize (error thrown when canvas is resized) using p5.Graphics off-screen graphics buffer + WebGL #5814

@jellygatorade

Description

@jellygatorade

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
  • Internalization
  • Friendly Errors
  • Other (specify if possible)

p5.js version

v1.4.2

Web browser and version

Chrome 105.0.5195.127, Firefox 105.0.1, Edge 105.0.1343.50

Operating System

Windows 10 21H1 Build 19043.1889

Steps to reproduce this

Hello 👋 and thanks for your help with this 😊.

I am using the p5.Graphics off-screen buffer in WebGL mode to write a back buffer as exemplified here.

I would like to be able to dynamically resize the p5.Graphics buffer similarly as the method of resizing the main canvas with the browser window:

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

But when my canvas is resized an exception is thrown in the JavaScript console that I assume is related to a problem with resizing my p5.Graphics instance. When I take the p5.Graphics instance out and resize the window this error is not thrown. Here is the stack trace:

Uncaught TypeError: e.setModified is not a function
    at i.default.Texture.update (p5.min.js:3:808990)
    at i.default.Shader.bindTextures (p5.min.js:3:799941)
    at u.default.RendererGL._setFillUniforms (p5.min.js:3:791099)
    at s.default.RendererGL._drawImmediateFill (p5.min.js:3:737282)
    at s.default.RendererGL.endShape (p5.min.js:3:735615)
    at E.default.RendererGL.image (p5.min.js:3:677139)
    at x.default.image (p5.min.js:3:569591)
    at draw (sketch.js:20:14)
    at o.default.redraw (p5.min.js:3:494224)
    at l.default.resizeCanvas (p5.min.js:3:473596)
i.default.Texture.update @ p5.min.js:3
i.default.Shader.bindTextures @ p5.min.js:3
u.default.RendererGL._setFillUniforms @ p5.min.js:3
s.default.RendererGL._drawImmediateFill @ p5.min.js:3
s.default.RendererGL.endShape @ p5.min.js:3
E.default.RendererGL.image @ p5.min.js:3
x.default.image @ p5.min.js:3
draw @ sketch.js:20
o.default.redraw @ p5.min.js:3
l.default.resizeCanvas @ p5.min.js:3
windowResized @ sketch.js:47
o.default._onresize @ p5.min.js:3

I have seen this issue has been discussed previously here and here, but perhaps these instances are not related to WebGL usage of p5.Graphics? The resolutions proposed are not working for me, for example using any of the following within windowResized() :

backbuffer.size(windowWidth, windowHeight); or backbuffer.width = windowWidth; backbuffer.height = windowHeight; or backbuffer.size(width, height);

The same exception as above is thrown when using any of these methods.

So—here is my full code with JS and GLSL:

JavaScript:

let theShader, backbuffer, canvas;

function preload() {
  theShader = loadShader("render.vert", "render.frag");
}

function setup() {
  canvas = createCanvas(windowWidth, windowHeight, WEBGL);

  // create an off-screen canvas to be used as a back buffer
  backbuffer = createGraphics(width, height, WEBGL);
  backbuffer.clear();
}

function draw() {
  // move the image drawn on the main canvas from the previous frame to the back buffer
  backbuffer.clear();
  backbuffer.image(canvas, width * -0.5, height * -0.5, width, height);

  shader(theShader);

  // send the back buffer, where the previous frame was drawn, into the shader program
  theShader.setUniform("buffer", backbuffer);

  // enter a value to calculate according to the current screen size
  theShader.setUniform("res", [width, height]);

  // time as current frame count
  theShader.setUniform("time", [frameCount]);

  // since the mouse coordinates and the position of pixels in the shader are converted into values between 0 and 1, the mouse coordinates are also changed accordingly
  let mx = mouseX / width;
  let my = 1 + (-1 * mouseY) / height;
  theShader.setUniform("mouse", [mx, my]);

  rect(0, 0, width, height);
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  //backbuffer.size(windowWidth, windowHeight);
  //backbuffer.width = windowWidth;
  //backbuffer.height = windowHeight;
  //backbuffer.size(windowWidth, windowHeight);
  //backbuffer.size(width, height);
}

Vertex Shader:

// https://github.com/aferriss/p5jsShaderExamples
// This vertex shader only functions to draw a rectangle to draw the image.

#ifdef GL_ES
precision highp float;
#endif

attribute vec3 aPosition;

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;
}

Fragment Shader:

#ifdef GL_ES
precision highp float;
#endif

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

void main() {
  // gl_FragCoord.xy can be thought of as the position of the pixel
  vec2 st = gl_FragCoord.xy;
  
  vec3 col = vec3(0);
  
  // the pixel position is changing to a value between 0 and 1
  vec2 tc = st / res;
  
  // the pixel position is changing to a value between 0 and 1
  vec2 buffer_tc = st / res;
  // corrected because the back buffer y direction is reversed
  buffer_tc.y = 1. + buffer_tc.y * -1.; 
  
  // get pixel values from the back buffer image with a function called texture2D.
  // texture2D(texture, texture coordinates (between 0 and 1))
  vec3 buffer_samp = texture2D(buffer, buffer_tc).xyz;
  
  // radius of circle
  float r = 0.1;

  // depending on the condition, pixels that meet the criteria of the circle become white.
  float ell = smoothstep(r,r-0.01,length((tc-mouse) * res / res.y));
  
  // adds a darker pixel value from the previous screen to the current screen
  col = vec3(ell) + buffer_samp.xyz * 0.98;

  gl_FragColor = vec4(col, 1.0);
}

Thanks for looking into this. Please let me know if I can give any more information to troubleshoot or if I have missed reading something in the p5.js documentation 😊.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions