diff --git a/src/webgl/p5.RendererGL.Immediate.js b/src/webgl/p5.RendererGL.Immediate.js index 31ce48f630..c9fe4db1f0 100644 --- a/src/webgl/p5.RendererGL.Immediate.js +++ b/src/webgl/p5.RendererGL.Immediate.js @@ -436,6 +436,32 @@ p5.RendererGL.prototype._tesselateShape = function() { this.immediateMode.geometry.vertexNormals[i].z ); } + + // Normalize nearly identical consecutive vertices to avoid numerical issues in libtess. + // This workaround addresses tessellation artifacts when consecutive vertices have + // coordinates that are almost (but not exactly) equal, which can occur when drawing + // contours automatically sampled from fonts with font.textToContours(). + const epsilon = 1e-6; + for (const contour of contours) { + for ( + let i = p5.RendererGL.prototype.tessyVertexSize; + i < contour.length; + i += p5.RendererGL.prototype.tessyVertexSize + ) { + const prevX = contour[i - p5.RendererGL.prototype.tessyVertexSize]; + const prevY = contour[i - p5.RendererGL.prototype.tessyVertexSize + 1]; + const currX = contour[i]; + const currY = contour[i + 1]; + + if (Math.abs(prevX - currX) < epsilon) { + contour[i] = prevX; + } + if (Math.abs(prevY - currY) < epsilon) { + contour[i + 1] = prevY; + } + } + } + const polyTriangles = this._triangulate(contours); const originalVertices = this.immediateMode.geometry.vertices; this.immediateMode.geometry.vertices = []; diff --git a/test/unit/visual/cases/webgl.js b/test/unit/visual/cases/webgl.js index 2f36feb806..ae6a2f80a7 100644 --- a/test/unit/visual/cases/webgl.js +++ b/test/unit/visual/cases/webgl.js @@ -141,4 +141,36 @@ visualSuite('WebGL', function() { screenshot(); }); }); + + visualSuite('Tessellation', function() { + visualTest('Handles nearly identical consecutive vertices from textToContours', async function(p5, screenshot) { + p5.createCanvas(200, 200, p5.WEBGL); + p5.background(255); + p5.fill(0); + p5.noStroke(); + + const font = await p5.loadFont('unit/assets/Inconsolata-Bold.ttf'); + const contours = font.textToContours('p', 0, 0, 60); + + if (contours && contours.length > 0) { + p5.translate(-p5.width / 4, -p5.height / 4); + p5.beginShape(); + for (let contourIdx = 0; contourIdx < contours.length; contourIdx++) { + const contour = contours[contourIdx]; + if (contourIdx > 0) { + p5.beginContour(); + } + for (let i = 0; i < contour.length; i++) { + p5.vertex(contour[i].x, contour[i].y, 0); + } + if (contourIdx > 0) { + p5.endContour(); + } + } + p5.endShape(p5.CLOSE); + } + + screenshot(); + }); + }); }); diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/arc/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/arc/000.png new file mode 100644 index 0000000000..b0732e0093 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/arc/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/arc/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/arc/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/arc/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/ellipse/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/ellipse/000.png new file mode 100644 index 0000000000..9351dc2adf Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/ellipse/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/ellipse/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/ellipse/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/ellipse/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/rect/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/rect/000.png new file mode 100644 index 0000000000..59aab0876f Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/rect/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/rect/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/rect/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Negative dimensions/rect/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CENTER/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CENTER/000.png new file mode 100644 index 0000000000..d624061419 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CENTER/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CENTER/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CENTER/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CENTER/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNER/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNER/000.png new file mode 100644 index 0000000000..d624061419 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNER/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNER/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNER/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNER/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNERS/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNERS/000.png new file mode 100644 index 0000000000..d624061419 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNERS/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNERS/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNERS/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode CORNERS/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode RADIUS/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode RADIUS/000.png new file mode 100644 index 0000000000..d624061419 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode RADIUS/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode RADIUS/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode RADIUS/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape arc/Mode RADIUS/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CENTER/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CENTER/000.png new file mode 100644 index 0000000000..7324222906 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CENTER/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CENTER/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CENTER/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CENTER/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNER/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNER/000.png new file mode 100644 index 0000000000..7324222906 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNER/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNER/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNER/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNER/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNERS/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNERS/000.png new file mode 100644 index 0000000000..7324222906 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNERS/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNERS/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNERS/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode CORNERS/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode RADIUS/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode RADIUS/000.png new file mode 100644 index 0000000000..7324222906 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode RADIUS/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode RADIUS/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode RADIUS/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape ellipse/Mode RADIUS/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CENTER/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CENTER/000.png new file mode 100644 index 0000000000..5c096e42bb Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CENTER/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CENTER/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CENTER/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CENTER/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNER/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNER/000.png new file mode 100644 index 0000000000..9e6ecdcd59 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNER/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNER/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNER/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNER/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNERS/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNERS/000.png new file mode 100644 index 0000000000..5c096e42bb Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNERS/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNERS/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNERS/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode CORNERS/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode RADIUS/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode RADIUS/000.png new file mode 100644 index 0000000000..5c096e42bb Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode RADIUS/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode RADIUS/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode RADIUS/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Shape Modes/Shape rect/Mode RADIUS/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default font/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default font/000.png new file mode 100644 index 0000000000..0b90be44db Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default font/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default font/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default font/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default font/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default monospace font/000.png b/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default monospace font/000.png new file mode 100644 index 0000000000..3d541b4e16 Binary files /dev/null and b/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default monospace font/000.png differ diff --git a/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default monospace font/metadata.json b/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default monospace font/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Tessellation/Typography/textFont() with default fonts/With the default monospace font/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file