Converting PGraphics and Mask from Processing to p5.js

Is there a tag for super beginners? I currently have a simple sketch that uses a mask to reveal an image below another. For some reason once I convert to p5.js, nothing shows up. I think it might have to do with the beginDraw and endDraw, but I am not sure how to fix this…

PGraphics mask;
PImage bgImage, topImage;

void setup()
{
  size(1080, 720);
  
  bgImage = loadImage("Gradient_Test.jpg");
  bgImage.resize(width, height);
  topImage = loadImage("Black Rectangle.jpg");
  topImage.resize(width, height);
  
  mask = createGraphics(width, height);
  mask.beginDraw();
  mask.background(0);
  mask.stroke(255);
  mask.strokeWeight(10);
  mask.fill(255);
  mask.endDraw();
}

void draw()
{
  background(0);
  mask.beginDraw();
  if (mousePressed) 
    mask.line(mouseX, mouseY, pmouseX, pmouseY);
  mask.endDraw();
  
  image(topImage, 0, 0, width, height);
  
  bgImage.mask(mask);
  image(bgImage, 0, 0, width, height);
}

This is the p5.js I have so far:

function setup()
{
  let bgImage, topImage;
  createCanvas(1080, 720);
  
  bgImage = loadImage('Gradient_Test.jpg');
  topImage = loadImage('Black Rectangle.jpg');
  
  mask = createGraphics(width, height);
  mask.beginDraw();
  mask.background(0);
  mask.smooth();
  mask.stroke(255);
  mask.strokeWeight(10);
  mask.fill(255);
  mask.endDraw();
}

function draw()
{
  background(0);
  mask.beginDraw();
  if (mouseIsPressed) {
  mask.line(mouseX, mouseY, pmouseX, pmouseY);
  }
  mask.endDraw();
  
  image(topImage, 0, 0, width, height);
  
  bgImage.mask(mask);
  image(bgImage, 0, 0, width, height);
}

I really appreciate any help!

You don’t need beginDraw/endDraw in p5.js. Also, do you want to upload it on web editor with images so we can test it?

1 Like

Hello, @bdooley, and welcome to the Processing Foundation Forum!

Consider loading the images within a preload() function, as follows:

function preload() {
  bgImage = loadImage('Gradient_Test.jpg');
  topImage = loadImage('Black Rectangle.jpg');
}

As @micuat suggested, if you provide us with those images, we can help with your code.

Hi, Thanks for the help! I uploaded it with images on web editor here: https://editor.p5js.org/bdooley7/sketches/jsmFap5hy

You have this line:

  topImage = loadImage('Black Rectangle.jpg');

However, the actual name of the file on the web editor site is 'Black_Rectangle.jpg', with an underscore in it, rather than a space.

Good catch! The gradient now appears, but I’m getting a message: “You are trying to use setAttributes on a p5.Graphics object that does not use a WEBGL renderer.” Could it be because mask only works with images and not graphics? Maybe adding a function to turn the graphic into an image and then masking?

This is what the sketch looks like in processing.

This discussion on GitHub may help: convert p5.graphics to p5.Image?.

the error you’re getting “settAttributes…” is only related to smooth(). otherwise you can use WEBGL renderer (createGraphics(width, height, WEBGL)) but this is not the main issue.

If you read the doc mask uses alpha channel. So I changed the code like this using clear to set alpha to 0 and lines to 255, but I don’t know why I only see the circle, and lines don’t show up in realtime

let bgImage, topImage;
let mask;

function preload() {
  bgImage = loadImage('Gradient_Test.jpg');
  topImage = loadImage('Black_Rectangle.jpg');
}

function setup()
{
  createCanvas(1080, 720);
  
  mask = createGraphics(width, height);
  mask.clear();
  // mask.smooth();
  mask.stroke(255,255);
  // mask.strokeWeight(10);
  // mask.fill(255);
  mask.circle(100,100,100)
}

function draw()
{
  background(0);
  // if (mouseIsPressed)
  {
  mask.line(mouseX, mouseY, pmouseX, pmouseY);
  }
  
  // image(topImage, 0, 0, width, height);
  
  bgImage.mask(mask);
  image(bgImage, 0, 0, width, height);
}

Oh great! It’s good to know that the mask will work. I’m not sure what to do about the issue with it not drawing in realtime. To test, I wrote the mask layer as a normal image to see if that would work, and it was fine. It must have to do with the mask?

I tried to make a version that converted the p.graphic to a p.image, and it works, although I really would like to draw a continuous lines and not a series of ellipses. Is that possible?

let bgImage;
let mask;
let size = 10;

function preload() {
  bgImage = loadImage("Gradient_Test.jpg");
}

function setup() {
  createCanvas(displayWidth, displayHeight);
  background(0);
  bgImage.resize(displayWidth, displayHeight);
  background(0, 100);

  mask = createGraphics(size, size);
  mask.fill(255);
  mask.noStroke();
  mask.ellipse(size/2, size/2, size);
}

function draw() {
  if (mouseIsPressed) {
  let newImage = createImage(size, size);
  newImage.copy(bgImage, mouseX - size/2, mouseY - size/2, size, size, 0, 0, size, size);

  newImage.mask(mask);
  image(newImage, mouseX - size/2, mouseY - size/2);
  }
}