Skip to content

Commit e447129

Browse files
feat: Add WebGL polygon plotting module and demonstrator
Adds a new `WbglPolygonPlot` class for drawing 2D polygons using WebGL, with an API similar to the existing `WbglLinePlot`. Key features: - Renders filled and stroked polygons. - Supports individual polygon transformations (scale, offset) and global transformations. - Includes helper functions (`createTriangle`, `createSquare`, `createCircle`) to easily generate polygon configurations. - Provides methods to initialize, update, and draw polygons. - GPU performant by batching draw calls for polygons with similar properties where applicable (though current implementation draws one by one in a loop, improvements can be made later if needed). A new benchmark/demonstrator `benchmark/bench-polygonplot.ts` and corresponding `benchmark/bench-polygonplot.html` have been added to showcase the functionality. This includes drawing various shapes with different styles and demonstrating dynamic updates. The module allows for sharing the same WebGL context as other plotting modules like `WbglLinePlot`.
1 parent b0f1597 commit e447129

4 files changed

Lines changed: 749 additions & 1 deletion

File tree

benchmark/bench-polygonplot.html

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>WebGL Polygon Plot Benchmark</title>
7+
<style>
8+
body {
9+
margin: 0;
10+
display: flex;
11+
justify-content: center;
12+
align-items: center;
13+
height: 100vh;
14+
background-color: #f0f0f0;
15+
}
16+
canvas {
17+
border: 1px solid black;
18+
background-color: #ffffff; /* Add a white background to the canvas itself */
19+
}
20+
</style>
21+
</head>
22+
<body>
23+
<canvas id="canvas" width="800" height="600"></canvas>
24+
<!--
25+
Using type="module" and pointing directly to .ts is typical for development environments
26+
that handle TypeScript compilation on the fly (e.g., Vite, Snowpack, or esbuild with a dev server).
27+
For a production build, this would typically point to a compiled .js file.
28+
-->
29+
<script type="module" src="./bench-polygonplot.ts"></script>
30+
</body>
31+
</html>

benchmark/bench-polygonplot.ts

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
import { WebglPlot, WebglPlotConfig } from "../src/webglplot";
2+
import { WbglPolygonPlot, PolygonConfig } from "../src/WbglPolygonPlot";
3+
4+
document.addEventListener("DOMContentLoaded", () => {
5+
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
6+
if (!canvas) {
7+
console.error("Canvas element not found!");
8+
return;
9+
}
10+
canvas.width = 800;
11+
canvas.height = 600;
12+
13+
const webglPlotConfig: WebglPlotConfig = {
14+
antialias: true,
15+
transparent: false,
16+
powerPerformance: "default",
17+
preserveDrawing: false, // Corrected property name
18+
};
19+
20+
const wglp = new WebglPlot(canvas, webglPlotConfig);
21+
22+
// Initialize WbglPolygonPlot
23+
// The maxPolygons parameter in constructor is not strictly used by current WbglPolygonPlot logic
24+
// if initPolygons is the primary way to set polygons, but kept for consistency with subtask.
25+
const polygonPlot = new WbglPolygonPlot(wglp, 100);
26+
27+
// Create Polygon Configurations
28+
const polygonConfigs: PolygonConfig[] = [];
29+
30+
// Triangle examples
31+
polygonConfigs.push(WbglPolygonPlot.createTriangle({
32+
center: [-0.8, 0.7],
33+
radius: 0.1,
34+
fillColor: [1, 0, 0, 0.5], // Red, semi-transparent
35+
isFilled: true,
36+
isStroked: true,
37+
strokeColor: [0,0,0,1],
38+
strokeWeight: 2,
39+
}));
40+
41+
polygonConfigs.push(WbglPolygonPlot.createTriangle({
42+
center: [-0.6, 0.7],
43+
radius: 0.08,
44+
rotation: Math.PI / 4, // 45 degrees
45+
fillColor: [1, 0.5, 0, 0.7], // Orange
46+
isFilled: true,
47+
isStroked: false,
48+
offset: [0, 0.1] // Shifted up slightly
49+
}));
50+
51+
// Square examples
52+
polygonConfigs.push(WbglPolygonPlot.createSquare({
53+
center: [-0.2, 0.5],
54+
size: 0.2,
55+
fillColor: [0, 1, 0, 0.6], // Green
56+
isFilled: true,
57+
strokeColor: [0.1, 0.1, 0.1, 1],
58+
strokeWeight: 3,
59+
isStroked: true,
60+
}));
61+
62+
polygonConfigs.push(WbglPolygonPlot.createSquare({
63+
center: [0.1, 0.5],
64+
size: 0.15,
65+
rotation: Math.PI / 6, // 30 degrees
66+
isFilled: false, // Stroke only
67+
isStroked: true,
68+
strokeColor: [0, 0, 1, 1], // Blue
69+
strokeWeight: 4,
70+
scale: [1.5, 1] // Stretched horizontally
71+
}));
72+
73+
// Circle examples
74+
polygonConfigs.push(WbglPolygonPlot.createCircle({
75+
center: [0.5, 0.6],
76+
radius: 0.1,
77+
fillColor: [1, 0, 1, 0.7], // Magenta
78+
isFilled: true,
79+
isStroked: true,
80+
strokeColor: [0.2, 0.2, 0.2, 1],
81+
strokeWeight: 1,
82+
}));
83+
84+
polygonConfigs.push(WbglPolygonPlot.createCircle({
85+
center: [0.8, 0.6],
86+
radius: 0.07,
87+
segments: 8, // Octagon
88+
fillColor: [0.5, 0.5, 1, 0.8], // Light blue
89+
isFilled: true,
90+
isStroked: false,
91+
offset: [0, -0.1],
92+
enabled: true,
93+
}));
94+
95+
// A larger, more complex polygon (e.g., a star or custom shape)
96+
const starPoints = new Float32Array([
97+
0.0, 0.3, // Top point
98+
0.07, 0.1,
99+
0.25, 0.1,
100+
0.1, -0.05,
101+
0.15,-0.25,
102+
0.0,-0.15,
103+
-0.15,-0.25,
104+
-0.1, -0.05,
105+
-0.25, 0.1,
106+
-0.07, 0.1,
107+
].map(p => p*0.7)); // Scaled down a bit
108+
109+
polygonConfigs.push({
110+
points: starPoints,
111+
fillColor: [1, 1, 0, 0.7], // Yellow
112+
isFilled: true,
113+
strokeColor: [0.5, 0.5, 0, 1],
114+
strokeWeight: 2,
115+
isStroked: true,
116+
offset: [-0.5, -0.3], // Positioned
117+
scale: [1,1]
118+
});
119+
120+
// Initialize Polygons in WbglPolygonPlot
121+
polygonPlot.initPolygons(polygonConfigs);
122+
123+
// Render Loop
124+
function animate() {
125+
// wglp.update(); // Assuming this clears the canvas or handles viewport updates
126+
// For now, WebglPlot doesn't have a clear or explicit update per frame by default.
127+
// Clearing is usually done by the browser before drawing or by setting preserveDrawingBuffer = false.
128+
// If individual plots need clearing, that would be part of their draw() or a specific clear method.
129+
130+
// Let's clear the canvas manually for this benchmark if preserveDrawingBuffer is true,
131+
// or rely on preserveDrawingBuffer:false.
132+
// For simplicity with current WebglPlot, if preserveDrawingBuffer is false (default for this demo),
133+
// clearing should be automatic. If it were true, we'd need:
134+
// const gl = wglp.webgl;
135+
// gl.clearColor(0.1, 0.1, 0.1, 1); // Example clear color
136+
// gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
137+
138+
polygonPlot.draw();
139+
140+
requestAnimationFrame(animate);
141+
}
142+
143+
// Start the animation
144+
animate();
145+
146+
// Example of updating a polygon after a delay (optional for initial demo)
147+
setTimeout(() => {
148+
if (polygonConfigs.length > 0) {
149+
polygonPlot.updatePolygonStyle(0, { fillColor: [0, 1, 1, 0.7] }); // Change first polygon's fill to cyan
150+
// Note: draw() needs to be called again to see the update.
151+
// In the animation loop, this will happen automatically.
152+
153+
// Example of changing transform - this requires re-setting uniforms in the draw call.
154+
// The current updatePolygonTransform only updates the config.
155+
// The draw call reads from this config.
156+
polygonPlot.updatePolygonTransform(1, [1.5, 1.5], polygonConfigs[1].offset || [0,0]);
157+
polygonConfigs[1].scale = [1.5,1.5]; // also update the source array if we re-init later
158+
159+
// To update points, which is more involved as it changes buffer data:
160+
// const firstPolygon = polygonConfigs[0];
161+
// if (firstPolygon && WbglPolygonPlot.createTriangle) { // Check if it was a triangle
162+
// const newTrianglePoints = WbglPolygonPlot.createTriangle({
163+
// center: [-0.8, 0.65], // slightly moved
164+
// radius: 0.12, // slightly larger
165+
// fillColor: firstPolygon.fillColor,
166+
// }).points;
167+
// polygonPlot.updatePolygonPoints(0, newTrianglePoints);
168+
// }
169+
console.log("Updated first polygon style and second polygon transform after 2 seconds.");
170+
}
171+
}, 2000);
172+
173+
});
174+
175+
// Basic HTML (conceptual - assumed to be in bench-polygonplot.html)
176+
/*
177+
<!DOCTYPE html>
178+
<html lang="en">
179+
<head>
180+
<meta charset="UTF-8">
181+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
182+
<title>WbglPolygonPlot Benchmark</title>
183+
<style>
184+
body { margin: 0; overflow: hidden; background-color: #333; }
185+
canvas { border: 1px solid white; }
186+
</style>
187+
</head>
188+
<body>
189+
<canvas id="canvas"></canvas>
190+
<script src="bench-polygonplot.js"></script> <!-- Assuming compiled JS -->
191+
</body>
192+
</html>
193+
*/

0 commit comments

Comments
 (0)