Creating a mask layer in p5js

1k Views Asked by At

I would like to draw a pattern, and then only have that pattern ‘show through’ where it overlaps with a shape that I specify. Similar to how a mask layer works in Photoshop. Does anyone know how I can approach this?

1

There are 1 best solutions below

0
On

I would use this 4 step process:

  1. create your mask with beginShape()/endShape and a beginContour()/endContour() in the middle for the area to be shown. You do this on a buffer.

    function setup() {
      createCanvas(400, 400);
      background(30)
      fill(200,50,60)
      msk = createGraphics(width,height)
      pattern = createGraphics(width,height)
      pixelDensity(1)
      msk.beginShape();
      // Exterior part of shape, clockwise winding
      msk.vertex(0, 0);
      msk.vertex(400, 0);
      msk.vertex(400, 400);
      msk.vertex(0, 400);
      // Interior part of shape, counter-clockwise winding
      msk.beginContour();
        msk.vertex(20, 20);
        msk.vertex(50, 220);
        msk.vertex(120, 380);
        msk.vertex(370, 320);
        msk.vertex(240, 160);
        msk.vertex(350, 40);
      msk.endContour();
      msk.endShape(CLOSE);
      mPixs = msk.loadPixels()
    }
    
  2. Then create a different buffer for the pattern

    for (let c=0; c<9; c++) {
      for (let r=0; r<9; r++) {
        pattern.circle(width/8*c,height/8*r,40)
      }    
    }
    
  3. Now load pixels from the mask and use the alpha value of each pixel on the alpha level of each corresponding pixel on the pattern.

    pattern.loadPixels()
    msk.loadPixels()
    for (let i=0; i < pattern.pixels.length; i+=4){
        pattern.pixels[i+3] = msk.pixels[i+3]
    }
    pattern.updatePixels()
    
  4. Finally, just add the resulting buffer to your main canvas with image(pattern,0,0)

Take a look at this working example carefully coded just for you! :D

let msk, pattern, mPixs
function setup() {
  createCanvas(400, 400);
  background(30)
  fill(200,50,60)
  msk = createGraphics(width,height)
  pattern = createGraphics(width,height)
  pixelDensity(1)
  msk.beginShape();
      // Exterior part of shape, clockwise winding
      msk.vertex(0, 0);
      msk.vertex(400, 0);
      msk.vertex(400, 400);
      msk.vertex(0, 400);
      // Interior part of shape, counter-clockwise winding
      msk.beginContour();
        msk.vertex(20, 20);
        msk.vertex(50, 220);
        msk.vertex(120, 380);
        msk.vertex(370, 320);
        msk.vertex(240, 160);
        msk.vertex(350, 40);
      msk.endContour();
  msk.endShape(CLOSE);
  mPixs = msk.loadPixels()
}

function draw() {
  
  for (let c=0; c<9; c++) {
    for (let r=0; r<9; r++) {
      pattern.circle(width/8*c,height/8*r,40)
    }    
  }
  for (let c=0; c<9; c++) {
    for (let r=0; r<9; r++) {
      let xo=random(-5,5), yo=random(-5,5)
      circle(width/8*c+xo,height/8*r+yo,50)
    }    
  }
  pattern.loadPixels()
  msk.loadPixels()
  for (let i=0; i < pattern.pixels.length; i+=4){
      pattern.pixels[i+3] = msk.pixels[i+3]
  }
  pattern.updatePixels()
  image(pattern,0,0)
}
html, body {
  margin: 0;
  padding: 0;
}
canvas {
  display: block;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    <main>
    </main>
    <script src="sketch.js"></script>
  </body>
</html>