Open samreid opened 9 years ago
@jonathanolson & I discussed this:
JO: it would be good to have rounded rectangles to stand-in for control panels, text in the control panel, icons, moving objects (no interaction), changing text. This will let us focus on getting good performance, keeping things look sharp. See if we can do a single draw call or just a few draw calls?
SR: This will help us get a good sense of what performance we can achieve, and we can include free parameters of (a) how many particles (b) how many static elements (c) how many different kinds of elements, etc.
JO: To do everything in one draw call, we would have to use one giant texture. May be impractical if changing every frame. Could use the z-buffer for a large number of levels.
JO: We should also investigate clipping--use the stencil buffer. Clipping could complicate everything we do. Same with alpha compositing. Maybe in the example, the transparency of one object could change? Or something animating (something changing inside it) is partially opaque, which would require render to texture.
SR: Should we compare against pixi?
JO: May be a good idea, but we should definitely create our own hand-coded version. Ideally, we would have our sample test that renders in (a) our hand-written webgl (b) in scenery and optionally (c) with pixi.
Desired example features (togglable on/off):
I started writing an application skeleton to test the ideas above. I'm currently rendering small solid-fill moving triangles using a single drawArrays call every frame, and rates according to Mr. Doob's Stats (just time for the rendering). The canvas is not properly handling the devicePixelRatio on retina devices. I'll report some initial results from fa23d9e59d033c7d90809edb2a18f781e72c3d7c
# triangles | FPS on iPad3/iOS8 | FPS on Nexus 7 |
---|---|---|
3000 | 60 | 60 |
10000 | 57 | 45 |
20000 | 30 | 28 |
It is important to note that there is a "warmup" time before this steady-state frame rate is achieved. For example, on the iPad3/iOS8, it takes about 6 seconds of stuttering, irregular (20-40fps) low performance before the smooth performance is achieved. It may be critical in our simulations to "warm up" the js engine + webgl pipeline before trying to animate anything visual in the sim.
Another critical thing to note is the canvas 2d performance, when just clearing the screen and drawing a moving rectangle (at steady state):
device | FPS |
---|---|
iPad3/iOS8 | 34 |
Nexus 7 | 60 |
This simplified canvas2d test has very laggy/jerky behavior on the iPad3 and suggests that canvas2d is probably inappropriate to use on iPad3/iOS8 as a rendering strategy for our applications.
One other important note: when toggling the @mrdoob stats banner to read out milliseconds, the entire animation becomes much more jerky and sluggish. When reading out frames per second it doesn't seem to be slowing anything down. Here's a modified end
function that will report draw times and ranges every second:
end: function() {
var time = Date.now();
ms = time - startTime;
msMin = Math.min( msMin, ms );
msMax = Math.max( msMax, ms );
frames++;
if ( time > prevTime + 1000 ) {
msText.textContent = ms + ' MS (' + msMin + '-' + msMax + ')';
msMin = ms;
msMax = ms;
fps = Math.round( ( frames * 1000 ) / ( time - prevTime ) );
fpsMin = Math.min( fpsMin, fps );
fpsMax = Math.max( fpsMax, fps );
fpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')';
updateGraph( fpsGraph, Math.min( 30, 30 - ( fps / 100 ) * 30 ) );
prevTime = time;
frames = 0;
}
return time;
}
Something else to note, in c48510dc19e1abc03a758061d86d57abe3ce8556 even though I am oscillating all of the triangles equally, there is some "tearing" or "lag" which I cannot explain.
Note that my work above uses disjoint triangles. But Marcelo Cantos recommends using triangle strip for this and discusses how to use triangle strip to show disjoint triangles: http://stackoverflow.com/questions/3677592/what-is-the-benefit-of-using-triangle-strip-and-triangle-fan-in-rendering
Triangle strips are extremely common, since they can represent surfaces more efficiently than triangle lists. Also, you can stitch together triangle strips that are visually separate so that entire disjoint geometries can be rendered as a single strip. You can do this by duplicating the last vertex of the first strip and the first vertex of the second strip, thus creating two degenerate triangles that bridge the gap but don't render.
Something odd: if I change TRIANGLES to TRIANGLE_STRIP with no other changes, the frame rate remains 60fps on iPad3 but drops to about 13fps on my macbook air and 11fps on Android. These is all for 15,000 vertices and one draw call per frame. Note: this is a lot of thin, tall triangles.
Our latest work on this can be viewed at http://localhost/scenery/tests/webgl/test-webgl-renderer.html
If it uses the same vertex buffer, wouldn't the strip draw many more triangles?
If it uses the same vertex buffer, wouldn't the strip draw many more triangles?
Yes, but it is a question of how many edges are shared in our geometry. In our latest vision of webgl support where we are rendering all shapes in a single draw call, the number of shared edges would be very low.
Ok, so to clarify, going from 6 vertices per rectangle to 4 vertices (and using TRIANGLE_STRIP) takes a performance hit?
If so, even though future shape rendering may have many edges duplicated, it sounds like TRIANGLES would be preferred).
Ok, so to clarify, going from 6 vertices per rectangle to 4 vertices (and using TRIANGLE_STRIP) takes a performance hit?
No, I am using the same number of vertices and rendering many more triangles when switching from TRIANGLES to TRIANGLE_STRIP. This was an isolated test with random geometry (hence the many tall, thin triangles, which I heard are harder for WebGL to optimize).
@jonathanolson has taken the lead on developing WebGL support for scenery, so I'm not sure this standalone module is still necessary. Up to @jonathanolson I think.
At today's developer meeting, @jonathanolson suggested rendering an entire simulation using WebGL but without using scenery. This will allow us to investigate optimizing WebGL rendering, understanding the tradeoffs of different approaches and finding out what the maximal achievable performance to inform our scenery implementation.