Skip to content

Commit 3b59bb3

Browse files
authored
Merge branch 'main' into fix/replace-beta-links
2 parents 2fbffb7 + 60ca87d commit 3b59bb3

22 files changed

Lines changed: 228 additions & 6 deletions

File tree

src/webgl/ShapeBuilder.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,15 @@ export class ShapeBuilder {
189189
this.shapeMode = constants.TRIANGLES;
190190
}
191191

192+
if (
193+
!this.renderer.geometryBuilder &&
194+
this.shapeMode === constants.TRIANGLE_FAN &&
195+
!this.renderer.supportsTriangleFan()
196+
) {
197+
this._convertFanToTriangles();
198+
this.shapeMode = constants.TRIANGLES;
199+
}
200+
192201
if (
193202
this.renderer.states.textureMode === constants.IMAGE &&
194203
this.renderer.states._tex !== null &&
@@ -205,6 +214,46 @@ export class ShapeBuilder {
205214
}
206215
}
207216

217+
_remapVertices(newIndices) {
218+
this.geometry.vertices = newIndices.map(i => this.geometry.vertices[i]);
219+
this.geometry.vertexNormals = newIndices.map(i => this.geometry.vertexNormals[i]);
220+
221+
const remapFlat = (arr, stride) => {
222+
const result = [];
223+
for (const i of newIndices) {
224+
for (let j = 0; j < stride; j++) {
225+
result.push(arr[i * stride + j]);
226+
}
227+
}
228+
return result;
229+
};
230+
231+
this.geometry.uvs = remapFlat(this.geometry.uvs, 2);
232+
this.geometry.vertexColors = remapFlat(this.geometry.vertexColors, 4);
233+
this.geometry.vertexStrokeColors = remapFlat(this.geometry.vertexStrokeColors, 4);
234+
235+
for (const propName in this.geometry.userVertexProperties) {
236+
const prop = this.geometry.userVertexProperties[propName];
237+
const size = prop.getDataSize();
238+
const oldData = prop.getSrcArray();
239+
prop.resetSrcArray();
240+
for (const i of newIndices) {
241+
prop.setCurrentData(oldData.slice(i * size, i * size + size));
242+
prop.pushCurrentData();
243+
}
244+
}
245+
}
246+
247+
_convertFanToTriangles() {
248+
const n = this.geometry.vertices.length;
249+
if (n < 3) return;
250+
const newIndices = [];
251+
for (let i = 2; i < n; i++) {
252+
newIndices.push(0, i - 1, i);
253+
}
254+
this._remapVertices(newIndices);
255+
}
256+
208257
_resetUserVertexProperties() {
209258
const properties = this.geometry.userVertexProperties;
210259
for (const propName in properties){

src/webgl/p5.Framebuffer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class Framebuffer {
9393
this.density = settings.density || this.renderer._pixelDensity;
9494
if (settings.width && settings.height) {
9595
const dimensions =
96-
this.renderer._adjustDimensions(settings.width, settings.height);
96+
this.renderer._adjustDimensions(settings.width, settings.height, this.density);
9797
this.width = dimensions.adjustedWidth;
9898
this.height = dimensions.adjustedHeight;
9999
this._autoSized = false;
@@ -175,7 +175,7 @@ class Framebuffer {
175175
resize(width, height) {
176176
this._autoSized = false;
177177
const dimensions =
178-
this.renderer._adjustDimensions(width, height);
178+
this.renderer._adjustDimensions(width, height, this.density);
179179
width = dimensions.adjustedWidth;
180180
height = dimensions.adjustedHeight;
181181
this.width = width;

src/webgl/p5.RendererGL.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,14 @@ class RendererGL extends Renderer3D {
297297
}
298298
}
299299
} else {
300-
const glMode = mode === constants.TRIANGLES ? gl.TRIANGLES : gl.TRIANGLE_STRIP;
300+
let glMode;
301+
if (mode === constants.TRIANGLES) {
302+
glMode = gl.TRIANGLES;
303+
} else if (mode === constants.TRIANGLE_FAN) {
304+
glMode = gl.TRIANGLE_FAN;
305+
} else {
306+
glMode = gl.TRIANGLE_STRIP;
307+
}
301308
if (count === 1) {
302309
gl.drawArrays(glMode, 0, geometry.vertices.length);
303310
} else {
@@ -441,14 +448,14 @@ class RendererGL extends Renderer3D {
441448
return gl.getParameter(gl.MAX_TEXTURE_SIZE);
442449
}
443450

444-
_adjustDimensions(width, height) {
451+
_adjustDimensions(width, height, density = this._pixelDensity) {
445452
if (!this._maxTextureSize) {
446453
this._maxTextureSize = this._getMaxTextureSize();
447454
}
448455
let maxTextureSize = this._maxTextureSize;
449456

450457
let maxAllowedPixelDimensions = Math.floor(
451-
maxTextureSize / this._pixelDensity
458+
maxTextureSize / density
452459
);
453460
let adjustedWidth = Math.min(width, maxAllowedPixelDimensions);
454461
let adjustedHeight = Math.min(height, maxAllowedPixelDimensions);
@@ -595,6 +602,10 @@ class RendererGL extends Renderer3D {
595602
return 10;
596603
}
597604

605+
supportsTriangleFan() {
606+
return true;
607+
}
608+
598609
viewport(w, h) {
599610
this._viewport = [0, 0, w, h];
600611
this.GL.viewport(0, 0, w, h);

src/webgpu/p5.RendererWebGPU.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,10 @@ function rendererWebGPU(p5, fn) {
13251325
);
13261326
}
13271327

1328+
supportsTriangleFan() {
1329+
return false;
1330+
}
1331+
13281332
viewport() {}
13291333

13301334
zClipRange() {

test/unit/visual/cases/webgl.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,72 @@ visualTest('randomGaussian() in a fragment loop averages to the mean', (p5, scre
16271627
p5.rect(-20, -20, 40, 40, 20);
16281628
screenshot();
16291629
});
1630+
1631+
visualTest('TRIANGLE_FAN with per-vertex fills', function(p5, screenshot) {
1632+
p5.createCanvas(50, 50, p5.WEBGL);
1633+
p5.background(255);
1634+
p5.beginShape(p5.TRIANGLE_FAN);
1635+
p5.fill('red');
1636+
p5.vertex(0, 0);
1637+
const n = 10;
1638+
const r = 20;
1639+
p5.fill('blue');
1640+
for (let i = 0; i <= n; i++) {
1641+
const angle = i/n * p5.TWO_PI;
1642+
p5.vertex(r*p5.cos(angle), r*p5.sin(angle));
1643+
}
1644+
p5.endShape();
1645+
screenshot();
1646+
});
1647+
1648+
visualTest('TRIANGLE_FAN in p5.Geometry with per-vertex fills', function(p5, screenshot) {
1649+
p5.createCanvas(50, 50, p5.WEBGL);
1650+
p5.background(255);
1651+
const geom = p5.buildGeometry(() => {
1652+
p5.beginShape(p5.TRIANGLE_FAN);
1653+
p5.fill('red');
1654+
p5.vertex(0, 0);
1655+
const n = 10;
1656+
const r = 20;
1657+
p5.fill('blue');
1658+
for (let i = 0; i <= n; i++) {
1659+
const angle = i/n * p5.TWO_PI;
1660+
p5.vertex(r*p5.cos(angle), r*p5.sin(angle));
1661+
}
1662+
p5.endShape();
1663+
});
1664+
p5.model(geom);
1665+
screenshot();
1666+
});
1667+
1668+
visualTest('TRIANGLE_STRIP with per-vertex fills', function(p5, screenshot) {
1669+
p5.createCanvas(50, 50, p5.WEBGL);
1670+
p5.background(255);
1671+
p5.beginShape(p5.TRIANGLE_STRIP);
1672+
const n = 6;
1673+
for (let i = 0; i < n; i++) {
1674+
p5.fill(i % 2 === 0 ? 'red' : 'blue');
1675+
p5.vertex(p5.map(i, 0, n - 1, -20, 20), i % 2 === 0 ? -10 : 10);
1676+
}
1677+
p5.endShape();
1678+
screenshot();
1679+
});
1680+
1681+
visualTest('TRIANGLE_STRIP in p5.Geometry with per-vertex fills', function(p5, screenshot) {
1682+
p5.createCanvas(50, 50, p5.WEBGL);
1683+
p5.background(255);
1684+
const geom = p5.buildGeometry(() => {
1685+
p5.beginShape(p5.TRIANGLE_STRIP);
1686+
const n = 6;
1687+
for (let i = 0; i < n; i++) {
1688+
p5.fill(i % 2 === 0 ? 'red' : 'blue');
1689+
p5.vertex(p5.map(i, 0, n - 1, -20, 20), i % 2 === 0 ? -10 : 10);
1690+
}
1691+
p5.endShape();
1692+
});
1693+
p5.model(geom);
1694+
screenshot();
1695+
});
16301696
});
16311697

16321698
visualSuite('3D Primitives', function() {

test/unit/visual/cases/webgpu.js

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ visualSuite("WebGPU", function () {
382382
p5.shader(shader);
383383
p5.plane(20, 20);
384384
await screenshot();
385-
}, { focus: true });
385+
});
386386
});
387387

388388
visualTest('randomGaussian() colors a basic shader (WebGPU)', async function(p5, screenshot) {
@@ -1664,6 +1664,74 @@ visualTest('randomGaussian() in a fragment loop averages to the mean (WebGPU)',
16641664
);
16651665
});
16661666

1667+
visualSuite('2D Shapes', function() {
1668+
visualTest('TRIANGLE_FAN with per-vertex fills', async function(p5, screenshot) {
1669+
await p5.createCanvas(50, 50, p5.WEBGPU);
1670+
p5.background(255);
1671+
p5.beginShape(p5.TRIANGLE_FAN);
1672+
p5.fill('red');
1673+
p5.vertex(0, 0);
1674+
const n = 10;
1675+
const r = 20;
1676+
p5.fill('blue');
1677+
for (let i = 0; i <= n; i++) {
1678+
const angle = i/n * p5.TWO_PI;
1679+
p5.vertex(r*p5.cos(angle), r*p5.sin(angle));
1680+
}
1681+
p5.endShape();
1682+
await screenshot();
1683+
});
1684+
1685+
visualTest('TRIANGLE_FAN in p5.Geometry with per-vertex fills', async function(p5, screenshot) {
1686+
await p5.createCanvas(50, 50, p5.WEBGPU);
1687+
p5.background(255);
1688+
const geom = p5.buildGeometry(() => {
1689+
p5.beginShape(p5.TRIANGLE_FAN);
1690+
p5.fill('red');
1691+
p5.vertex(0, 0);
1692+
const n = 10;
1693+
const r = 20;
1694+
p5.fill('blue');
1695+
for (let i = 0; i <= n; i++) {
1696+
const angle = i/n * p5.TWO_PI;
1697+
p5.vertex(r*p5.cos(angle), r*p5.sin(angle));
1698+
}
1699+
p5.endShape();
1700+
});
1701+
p5.model(geom);
1702+
await screenshot();
1703+
});
1704+
1705+
visualTest('TRIANGLE_STRIP with per-vertex fills', async function(p5, screenshot) {
1706+
await p5.createCanvas(50, 50, p5.WEBGPU);
1707+
p5.background(255);
1708+
p5.beginShape(p5.TRIANGLE_STRIP);
1709+
const n = 6;
1710+
for (let i = 0; i < n; i++) {
1711+
p5.fill(i % 2 === 0 ? 'red' : 'blue');
1712+
p5.vertex(p5.map(i, 0, n - 1, -20, 20), i % 2 === 0 ? -10 : 10);
1713+
}
1714+
p5.endShape();
1715+
await screenshot();
1716+
});
1717+
1718+
visualTest('TRIANGLE_STRIP in p5.Geometry with per-vertex fills', async function(p5, screenshot) {
1719+
await p5.createCanvas(50, 50, p5.WEBGPU);
1720+
p5.background(255);
1721+
const geom = p5.buildGeometry(() => {
1722+
p5.beginShape(p5.TRIANGLE_STRIP);
1723+
const n = 6;
1724+
for (let i = 0; i < n; i++) {
1725+
p5.fill(i % 2 === 0 ? 'red' : 'blue');
1726+
p5.vertex(p5.map(i, 0, n - 1, -20, 20), i % 2 === 0 ? -10 : 10);
1727+
}
1728+
p5.endShape();
1729+
});
1730+
p5.model(geom);
1731+
await screenshot();
1732+
});
1733+
});
1734+
16671735
visualSuite('Feedback', function() {
16681736
visualTest(
16691737
'Drawing accumulates across frames when background is set in setup',
2.2 KB
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"numScreenshots": 1
3+
}
2.2 KB
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"numScreenshots": 1
3+
}

0 commit comments

Comments
 (0)