Two.js: How are you handling WebGL?

Created on 16 Feb 2021  路  3Comments  路  Source: jonobr1/two.js

Hi Jono! This library is freaking amazing!

As I've been browsing through the code, I expected a lot of convoluted shaders code in the WebGL renderer鈥攂ut that wasn't the case. I read in some comments that you're using an offscreen canvas, but there doesn't seem to be any extra canvases or WebWorkers. So, if you've got some time, could you go over the general idea of how this works?

Context: I wanted to use three and react-three-flex for rendering some extremely dynamic pages, however, these libraries are quite huge. So, I'm looking for alternatives. Two.js seems to handle all the text rendering without relying on huge text rendering dependencies (like HarfBuzz), but I couldn't understand the implementation as quickly as I thought I would.

Thank you :smile:

question

All 3 comments

Thanks @ImedAdel!

There are actually many extra canvases that are created and stored in memory by Two.js. Here is where the WebGL renderer is storing its: https://github.com/jonobr1/two.js/blob/dev/src/renderers/webgl.js#L32

Overall, you're correct. The WebGL program rendering Two.js scenes is quite simple. Every object that is drawn to the screen in Two.js is represented by a series of 2D planes and each plane has a corresponding texture. The textures are created dynamically in Canvas 2D based on the styles that you give each object in Two.js. You'll find the updateCanvas method for each type of object path, text, etc. is the Canvas 2D rendering of that object. The render function of each object basically applies the texture (if it's changed) and updates it's matrix transformations to make sure it's in the right place.

To be honest though, if you're looking to making something performant Two.js's API is most conducive to Canvas rendering for you to debug / take advantage of. The WebGL renderer is more of a proof-of-concept and unless you make a lot of objects and then only change their translation or rotation properties, the likelihood that the WebGL Renderer runs faster _and_ has the same fidelity of image as the other renderers is low.

That being said there is discussion here describing the desire to move away from Canvas 2D uploading of textures and figure out a solution in the fragment shader.

Hope this helps and best of luck. Please share what you make when / if you use Two.js! Love seeing what people make with the project.

I see! Your comment certainly _shaded_ some light on the obscure parts. It's a really interesting approach. I wanted to see how far one can go with a similar concept and apparently you can even render the actual DOM in WebGL (through the canvas and SVG foreign objects). But of course, the performance is not that good.

To be honest, the 2D canvas is good enough. But the lack of things like letter-spacing is what's making me look for a WebGL alternative.

I think I'll be revisiting these ideas in the future. There are multiple interesting approaches: regl low-level webgl, cairo as a canvas/webgl backend, canvas but with manual font positioning. We'll see :smiley:

Thanks, Jono!

In that case your best bet is to use something like regl and setup a custom SDF font pipeline. I guided this development a few years ago (it's in Three.js), but the general idea is the same in any WebGL rendering environment: https://developers.google.com/web/showcase/2017/within

Was this page helpful?
0 / 5 - 0 ratings

Related issues

caracal7 picture caracal7  路  8Comments

oliver-ni picture oliver-ni  路  7Comments

jinspiration picture jinspiration  路  4Comments

adamdburton picture adamdburton  路  6Comments

Sudhanshu4122 picture Sudhanshu4122  路  6Comments