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.67k stars 3.33k forks source link

strokeWeight(1) appears as 2 pixels for a rectangle. #7319

Closed orbitalchicken closed 3 weeks ago

orbitalchicken commented 3 weeks ago

Most appropriate sub-area of p5.js?

p5.js version

1.10

Web browser and version

Firefox 131 on Windows, Chrome 130 on Linux and Windows

Operating system

Windows, Linux

Steps to reproduce this

Steps:

  1. draw a rectangle with a strokeWeight of 1 px.
  2. PR0BLEM: The rectangle have a 2px stroke.

Snippet:

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

  strokeWeight(1)
  rect(50,50,50,50);
}
perminder-17 commented 3 weeks ago

I was working on my Windows system, but I'm unable to replicate the issue. Could you clarify how it's supposed to appear? For me, a 1px stroke appears lighter, while a 2px stroke looks slightly bolder. So, using a strokeWeight of 1px does not produce a rectangle with a 2px stroke.

image

image

orbitalchicken commented 3 weeks ago

@perminder-17 You replicated the issue, in your first screenshot. The problem is that the 1px stroke appears lighter and is as wide as the 2px stroke. The 1px stroke should be black and only 1 pixel wide (half the width of a 2px stroke). You can use the Processing.org editor to compare the resulting image.

image example

Also, the stroke width problem is the same with line().

davepagurek commented 3 weeks ago

Thanks for filing an issue!

The issue, I think, is that lines are centered about the vertices of the rectangle. If you have a 2px wide line, and a vertex is at an integer, then the left and the right side of the line is also at an integer (±1). If you have a 1px wide line, then the edges of the line will both be halfway through a pixel (±0.5), so antialiasing causes it to show up on both pixels, with around half opacity.

The key thing here is to take into account the positioning of lines if you want pixel-precision strokes. Here are two lines, one adjusted so the edges of the stroke are not halfway across a pixel, and the other is misaligned, causing the effect you see:

function setup() {
  createCanvas(400, 400)
  pixelDensity(1)
  background(200)
  line(100.5, 0, 100.5, 400)
  line(300, 0, 300, 400)
}

image (Live: https://editor.p5js.org/davepagurek/sketches/NKkNBNv-R)

Antialiasing of lines is a fundamental aspect of the underlying 2D JavaScript canvas that we can't turn off. For this reason, we aren't currently planning to do any workarounds to match how a non-JavaScript-canvas renderer might look.