Description
Increasing Access
Although WebGL lines are now more similarly featured compared to 2D lines, the extra processing required means sketches with lots of lines are likely to run more slowly than the equivalent 2D code. This will be especially noticeable on mobile or lower end hardware. If we can improve this performance without changing the user-facing API at all, we can bring a better viewing experience to everyone.
Most appropriate sub-area of p5.js?
- Accessibility
- Color
- Core/Environment/Rendering
- Data
- DOM
- Events
- Image
- IO
- Math
- Typography
- Utilities
- WebGL
- Build Process
- Unit Testing
- Internalization
- Friendly Errors
- Other (specify if possible)
Feature enhancement details
When drawing WebGL lines, we need to convert from the line edges to polygons that can be rendered.
One of the biggest bottlenecks in WebGL line drawing is the fact that we compute many aspects of the vertices of lines on the CPU and then send them to the GPU: we have to make at least two copies of the original points, one for each side of the stroke, so that we can push the sides of the stroke away from each other and make a polygon with some thickness.
p5.js/src/webgl/p5.Geometry.js
Lines 363 to 378 in 9ee0fa7
Although the actual distance is calculated in a shader, WebGL doesn't give us a way to make copies of the vertices in a shader, so we do that on the CPU. This data needs to be sent from the CPU to the GPU, which is a big bottleneck. This can slow down large scenes, and disproportionately affects mobile (#5975).
Now that we have support for WebGL2 in p5, we can maybe take advantage of instanced rendering: we can get the GPU to combine a fixed set of points to draw one segment in a default position with buffers with our vertex positions rather than doing it ourselves on the GPU. Effectively, rather than passing 2 * numEdges * numPointsPerSegment
points from the CPU to the GPU, we'd pass 2 * numEdges + numPointsPerSegment
, which has the potential to be a big performance gain. A similar approach is described in this article: https://wwwtyro.net/2019/11/18/instanced-lines.html
Some unique issues we'd have to address for this to work:
- Do we also have to keep the existing system in place for WebGL1 contexts? Can we combine as much code as possible to not have two totally separate implementations?
- Vertex data is stored in
p5.Geometry
right now. One could potentially have multiplep5.Graphics
, some of which set to WebGL1 and some set to WebGL2, and then one could try to draw the same geometry to both. We'd maybe have to store non-instanced vertex buffers separately from instanced vertex buffers so that one could use the same object in both contexts.