processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.56k stars 3.31k forks source link

Consider updating noSmooth() reference #5472

Open KevinWorkman opened 2 years ago

KevinWorkman commented 2 years ago

Most appropriate sub-area of p5.js?

Details about the bug:

I'm trying to draw aliased shapes by calling noSmooth(), but the shapes are still anti-aliased.

For example, I expected this code to draw purely black lines:

function setup() {
  createCanvas(300, 300);
}

function draw() {
  noSmooth();

  background(220);
  strokeWeight(1);
  stroke(0);

  for(let i = 0; i < width; i+=5){
   line(i, 0, i, i); 
  }
}

But instead the lines were gray due to anti-aliasing:

gray lines

I also noticed the reference has the same issue: https://p5js.org/reference/#/p5/noSmooth

I would expect the code on that page to show one anti-aliased circle and one aliased circle, but instead they are both anti-aliased. Here's a zoomed-in picture to show what I mean:

anti-aliased circles

From these related issues:

...it sounds like this is a known limitation of the underlying browsers. So although this might not be a bug in p5.js, I think we should consider updating the reference to mention this known issue.

aferriss commented 2 years ago

I might be wrong, but I think noSmooth() will only work in webGL mode. Maybe we could add something to the docs here to clarify this.

I think for images you can also try canvasCtx.imageSmoothingEnabled = false;

limzykenneth commented 2 years ago

noSmooth() does work in 2D as well but only on resized images (it is using imageSmoothingEnabled).

function setup() {
  createCanvas(400, 400);

  let pg = createGraphics(100, 100);
  pg.line(0, 0, 100, 100);
  noSmooth();
  image(pg, 0, 0, 400, 400);
}
reejuBhattacharya commented 2 years ago

Hi, if this issue is free, can I work on it?

orgicus commented 2 years ago

@limzykenneth I still see anti-aliasing artefacts when running your example in the p5 web editor.

I did get the expected aliased output by:

let pg;

function setup() {
  createCanvas(300, 300);
  noSmooth();

  pg = createGraphics(100, 100, WEBGL);
  pg.noSmooth();
  pg.pixelDensity(1);// OSX retina display ?
  pg.noFill();
  pg.stroke(0);
}

function draw(){
  // update low res
  pg.background(255);
  pg.rect(1, 0, 49, 49);
  pg.line(0, 0, 50, 50);
  pg.line(0, 50, 100, -50);
  pg.circle(25, 25, map(sin(frameCount * 0.025), -1.0, 1.0, 9, 30));
  // render high res
  background(0);
  image(pg, -width, -height, width * 2, height * 2);
}

Maybe I'm missing some tricks here ? (Was expecting your simpler snippet to look aliased)

limzykenneth commented 2 years ago

That is because of pixelDensity() as p5 is actually doing some behind the scenes stuff to make the same set of coordinates work regardless of the screen pixel density so in this case it ended up not having as pronounced an effect. If you toggle the noSmooth() on and off you should see a difference (reduce the p5.Graphics size to see a more pronounced difference).

If you needed absolutely no smoothing at all you would probably want to use pixelDensity(1) anyway. I can't say much about mixing a webgl graphics in a 2D canvas though.

jbakse commented 2 years ago

Hello All,

Intro

I'm working on a sketch in which I want to disable all antialiasing, ran into the limitations of noSmooth() and found this issue.

I agree that the noSmooth() documentation probably needs to be updated. I think it is currently misleading about what noSmooth() can and can't do.

Examples I've made some example sketches (v1.4.1) that might be helpful.

Aliasing in P2D image

Aliasing in WEBGL image

Notes Here are a handful of notes:

Suggestion

With all that in mind, noSmooth() is currently most useful for scaling up images without bilinear filtering. It would probably help to have the example code show scaled-up images instead of ellipses.

Workaround

p.s. you can get pixelated images in WEBGL mode like this...

testTexture = p5.instance._curElement.getTexture(testImage);
testTexture.setInterpolation(NEAREST, NEAREST);

...but I needed to dip into some undocumented bits (p5.instance._curElement), I'm not sure if there is a "correct" way to get the current render?

Nomzy-kush commented 1 year ago

I'm really excited to talk to you about p5.js and its amazing noSmooth feature! As someone who loves using p5.js for creative coding projects, I understand the importance of properly documenting its features. And that's why I'm reaching out to you today.

I think it would be great to work on documenting the noSmooth feature in detail. This feature is useful for creating pixelated or retro-style graphics in your projects. By disabling the smoothing of edges and lines, you can achieve a unique and nostalgic look that's perfect for certain types of art and design.

I'd love to help write up a comprehensive guide to using noSmooth in p5.js, complete with examples and practical tips. Whether you're a beginner or an experienced user, this guide will help you understand how to leverage this feature to create stunning visuals that really stand out.

So what do you say? Are you interested in collaborating on this project with me? Let's work together to make p5.js documentation even better!

Qianqianye commented 1 year ago

Thank you all for you input. I'm inviting @nickmcintyre, who's updating the p5.js reference page as part of Seasons of Docs program, to take a look at this issue. Is this issue addressed in this commit?

nickmcintyre commented 1 year ago

Thanks for including me @Qianqianye!

@jbakse your examples helped me to understand this function better. I'll revise the documentation for noSmooth() and tag you and @Nomzy-kush to get your feedback.