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?
Asked
Active
Viewed 815 times
1
-
Does this answer your question? https://stackoverflow.com/questions/49715907/masking-or-clipping-mask-with-p5-js – xxMrPHDxx Apr 16 '22 at 22:08
-
No not exactly. That example shows a pre-loaded image() that uses the mask. I'd like to draw a pattern w/ p5 and then have part of that pattern showing through using the mask. – BlakeS Apr 17 '22 at 02:07
-
1Also I'd like to be able to design a shape (using beginShape() / endShape()) for the mask, rather than using one of the basic shapes like the circle in the example. – BlakeS Apr 17 '22 at 02:08
-
2Thank you for surfacing this though. Helpful for my learning. – BlakeS Apr 17 '22 at 02:09
-
Does this answer your question? [masking, or clipping mask with p5.js](https://stackoverflow.com/questions/49715907/masking-or-clipping-mask-with-p5-js) – Rabbid76 Apr 17 '22 at 15:27
1 Answers
1
I would use this 4 step process:
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() }
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) } }
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()
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>

zJorge
- 798
- 2
- 13
- 26