cytoscape / cytoscape.js

Graph theory (network) library for visualisation and analysis
https://js.cytoscape.org
MIT License
10.09k stars 1.64k forks source link

Test Performance of Text Rendering and Bezier Curve drawing with WebGL #113

Closed ghost closed 12 years ago

ghost commented 12 years ago

Recent tests showed that WebGL using Three.js can potentially reach high framerates even with large numbers of nodes. Three.js shows some promise over competitors by the size of its user base and activity, indicated by the comparatively high number of GitHub watchers (http://stackoverflow.com/questions/6762726/scenejs-vs-three-js-vs-others, second answer).

However, one possible limitation could be text rendering. The nodes drawn in the test have relatively low polygon counts (about 15 triangles per node). Text drawn using polygons would likely have higher polygon counts. Text drawn using textures mapped onto quadrilateral shapes, although somewhat fast, has not been tested for performance.

Another limitation could be the time it takes to load the scene. In the test with high node and edge counts (3000 each), the page seemed to take more than 20 seconds to load. With 2000 nodes and 2000 edges, the page took about 7 seconds to load. This time is probably used to create the many instances of Javascript objects related to drawing. The test uses straight lines; Bezier curves would probably take longer to make.

maxkfranz commented 12 years ago

Does it not have native text (font) drawing support with 2D graphics?

I'm not concerned about page load as much, because your scripts are blocking. The page doesn't render until the script is done. Normally, the page would render, Cytoscape Web waits until document.ready, and then the renderer is initialised and elements loaded.

The client can show a loader on the cy div until it's loaded.

An alternative: The renderer could be a webworker, since we're already using a similar messaging system. That way, the renderer would never block the UI thread when it's doing calculations and so on.

ghost commented 12 years ago

It contains some support for drawing text using triangles. The library has features that make use of premade font data to get coordinates for the triangles that make up the text, such as ones here: https://github.com/mrdoob/three.js/tree/master/examples/fonts. This seems to be the method of drawing text that is most associated with Three.js.

I think using a loader and putting time-intensive calculations in a web worker to keep the UI responsive are both good ideas. Some of the font script files are larger than 100 kb, a loader would indicate that the application has not frozen or stopped working while it loads scripts and creates object instances.

ghost commented 12 years ago

I just did a test using the triangle-based text rendering, with a mild slowdown at 400 nodes and 400 edges. A different approach is to use 2 canvas objects, stacking them together, and using the top one as regular 2D canvas to render text.

ghost commented 12 years ago

I did another test using canvas 2D context to render text, and Three.js WebGL for the nodes and edges. Performance was much better, with acceptable framerates with 2000 nodes and 2000 edges. Looks like using the 2D context to produce text is one way to go. A third way to display text is to use HTML div elements containing text and put them on top of the WebGL canvas.

maxkfranz commented 12 years ago

Rather than divs, I'd use SVG to render text if we want to go that way. I'd stick to using the 2D canvas context to render text so things are more together.

ghost commented 12 years ago

That sounds good. I could also do a final test using textures created by canvas that contain text. For this method, canvas is only involved when the text changes, and all the remaining drawing is done by WebGL.

maxkfranz commented 12 years ago

Rendering as textures will most likely be more expensive than just drawing the fonts directly using the 2D canvas context and its native font rendering methods.

maxkfranz commented 12 years ago

Here's some code you can copy to test things out: http://www.spoonofdeath.com/delph/webgltext.html

ghost commented 12 years ago

I did do a similar test with Three.js that uses canvas 2D to make textures. The speed was a bit lower than just using canvas 2D to draw text. However, it could be still worth another try to test on the direct-WebGL implementation.

maxkfranz commented 12 years ago

I'd forgo that and just use a 2D canvas on top of the WebGL one.

ghost commented 12 years ago

Sounds good. I've gotten the direct WebGL implementation working with basic node picking and node dragging. The framerate is decent with 4000 nodes and 4000 edges with canvas 2D text rendering. The scene draws in about a second. Perhaps I could start integrating with the core?