Three.js: WebGL2Renderer

Created on 29 Oct 2016  ·  84Comments  ·  Source: mrdoob/three.js

This week Chrome announced their intent to ship WebGL 2.0 so I guess it's about time to start adding support!

There are already some PRs that add support to WebGLRenderer for some of the new features but, somehow, it didn't feel it was good idea to make WebGLRenderer support both webgl and webgl2.

Say hello to WebGL2Renderer! https://github.com/mrdoob/three.js/commit/2ff9d410753b72a5e43b211dc3be26f0f0ab8a0e 👋

A new renderer not only will save us from tons of conditionals but also will give us the chance of cleaning things up; starting with only supporting BufferGeometry ✌️

Sorry for all the people which PRs didn't got merged because of my indecision! 😔

Enhancement WebGL2

Most helpful comment

Planning to start looking into all this next week! ✌️

All 84 comments

Very nice. :) I was actually a bit worried as to how to handle the complexity of WebGL 2 and 1.

It would be great to prefer to use UBO. :) And I love the idea only supporting BufferGeometry - that should simplify things tremendously.

It would be cool to support mostly same shaders though if we stick with forward rendering (which seems to be what UE4 is doing for speed for VR.) I think we can likely swing that? What do you think?

I guess I would like to maintain shader compatibility so that if WebGL2 isn't available we can fall back to something that looks similar, just slower.

@mrdoob Hip hip hooray! And great to hear that BufferGeometry will be exclusively used. 👍

I second @bhouston's suggestion of preferring UBOs.

Would it be possible to also more fully decouple lighting and shadow handling from the renderer, too? The defaults are really handy, but when you want complete control over lighting and shadow logic, WebGLRenderer and co. feel like they put up a fight.

And while I'm listing wishlist-y type items, could sort algorithms be made 'pluggable'? I have sorting needs that are outside of the scope of three, and it seems unnecessarily difficult to override the sorting functions in the current WebGLRenderer. Perhaps this could be an optional setting when creating the renderer object?

I almost wonder if one should just modify WebGLRenderer 1 and remove support for anything but BufferGeometry objects. That may be an easier way forward. If there is a simple function for converting Geometry to BufferGeometry that one forces people to call...

I guess I say this because I am worried about trying to maintain feature parity between WebGLRenderer and WebGLRenderer2. It is easier to evolve a single code base rather than maintain two in parallel.

I almost wonder if one should just modify WebGLRenderer 1 and remove support for anything but BufferGeometry objects. That may be an easier way forward. If there is a simple function for converting Geometry to BufferGeometry that one forces people to call...

There is a function like that already. But is not that simple...

I think it's better to build WebGLRenderer2 from scratch so we can reconsider the API and the supported features.

Firefox 51 now has WebGL 2 support: https://www.mozilla.org/en-US/firefox/51.0/releasenotes/

Can't wait for this!

Chrome 56 supporting WebGL 2.0 was released!
https://developers.google.com/web/updates/2017/01/nic56

Good time to move WebGLRenderer2 forward? XD

Should we also create a WebGLDeferredRenderer2?

Planning to start looking into all this next week! ✌️

Any chance you already had some time to look into it! Soooo looking forward to it! (3D textures)

@mrdoob
Any updates?
If you have some concerns, please share with us!
We can discuss and help ;D

Haven't had time yet. Soon soon! 😇

Any updates? I am especially interested in 3D textures for volume rendering some medical images. I am also willing to help to make this pull request succeed.

The current three.js webgl2 sandbox doesn't work :( https://threejs.org/examples/webgl2_sandbox.html
Might be a three.js version build issue?

If online <script type="module"> had been implemented already...
https://groups.google.com/a/chromium.org/d/msg/blink-dev/uba6pMr-jec/tXdg6YYPBAAJ

At least Mozilla is working on it https://bugzilla.mozilla.org/show_bug.cgi?id=1240072

@mrdoob, Does this mean we can expect Three.js API to take advantage of <script type="module"> when updated to WebGL 2.0? ;)

BTW I think it is easiest in the mean time to just add WebGL 2.0 support to WebGLRenderer. I think that this would allow incremental adoption and we can do feature detection to see if we can use WebGL 2 features. I don't think it is the hardest thing to do. I know it leads to a little complexity as opposed to a pure WebGL 2 renderer, but it is the easiest path in near and medium term. And we slowly evolve where we eventually leave behind WebGL 1 once WebGL 2 has somewhere above 90% adoption.

Khronos just had a webinar on webgl2:
https://docs.google.com/presentation/d/11-mTDNmSJzJnRVGu9Vu6AUzOt34yV3PO7oqw4E5wc2o/edit#slide=id.gd15060520_0_38
The media will be out shortly, but the presentation was mainly voice-over of the slides and associated demos in the slides.

Its pretty clear that this requires a new start, not "updating" from the existing WebGLRenderer.

In terms of es6 modules, I think the current approach of the source being es6 modules, then using rollup for a bundle is still the way to support a "dual build".

I've done this now for a week or so, testing modules on Safari Tech Preview and the bundle on all browsers. Really results in build/ having the source tree as well as the current bundle. One-liner Rollup as you currently have, and a copy of the source tree for module use.

@bhouston tempting...

Latest status?

I've got somehow mixed feeling about this. Initially I was thinking about the same path as @bhouston proposed, going incrementally adding webgl2 features to the current WebGLRenderer. But that would make the renderer more complex and hard to deal with features that differ the most between the two version ending up with a messy code full of branches and condition checks.
One option could be to clone the WebGLRenderer as the starting point for WebGL2Renderer and keep removing/adding features without messing with the original renderer.
If we take a look at engines like Playcanvas, which is probably the one out there with the earliest webgl2 support, we can see that it even doesn't take the advantage of the new webgl2 features like UBO or VAO because it's something that will modify many parts of the engine.

I strongly believe that if we try to mix both versions on the same renderer we'll end up with a harder to maintain code and as soon as webgl2 will get fully support we'll need to refactor this anyway as I guess we'll be forced to follow a design to keep that compatibility, instead of design it from scratch having webgl2 in mind.

So my vote is to start WebGL2Renderer from scratch even if we'll go slow (we still have room for improvement until webgl2 will get close to 100% support out there).

Some files other than just the renderer itself must be modified, for example textures, programs and so on. Should we create a subfolder renderer\webgl2 and keep adding the files that will be specifically created for that renderer?

We could create an issue with the list of changes we should do to have a webgl2 fully compatible renderer to have them in mind when writing the renderer, and also create a list of features we would like to have for MVP to focus our effort on discuss these in this initial state to kick off a deeper conversation on the implementation.

Any updates on its development?

Not yet. I was giving priority to WebVR this month.

I tried a quick'n'dirty in-place conversion to WebGL2 and ES3 shader language, as suggested by @fernandojsg above. Here is the squashed diff: https://github.com/tstanev/three.js/compare/master...tstanev:traian/webgl2 Actually, it doesn't look nearly as bad as I expected initially. It's almost looking like it would not be super ugly to support both via some strategically placed ifdefs.
[Edit: Updated link.]

@tstanev Do you have a working example?

The bundled three.js examples in the linked branch are working (as you can see in the diff, I converted the ones that required extensions previously). You can clone the repo/branch and run them locally.

@tstanev How about making performance comparison for webgl2 changes online?) Would be nice to see it. (three.js vs three.js on webgl2)

hi
thanks you for this best idea.
I wants to use webgl2renderer in my program but I couldn't use it in precompile version(r86) so I get the source and uncomment the webgl2rendrer in three.js importing and then build it.
now my code and your example (webgl2-sandbox) will run without any error but they show nothing

EDIT: I had test them in firefox 54 and chrome 60
my example using bufferGeometry and ShaderMaterial and will be work correctly in webglrenderer

no one answer me? what is the problem of webgl2renderer now?

@MHA15 presumably it's not included in the build because it's not ready for production yet.

Hey guys, how is the WebGL2Renderer development going?
I know that the decision was made to recreate it from scratch. But it has been a while and the development is kind of slow on this topic as it is a great amount of work to recreate it I believe.

At this point, can we reconsider making a clone of WebGLRenderer and change it into WebGL2 instead like what @mattdesl did in https://github.com/mrdoob/three.js/issues/8125 ?? We can then modify the renderer based on some new features like UBO as @fernandojsg said. Eventually, we will remove all of those webgl 1 legacy codes.

In my opinion, creating the renderer from scratch requires a huge amount of work and ideally it can only begin with a few contributors. This conversation was started a year ago. And unless we got to the point we have a savior who would spend a few months full-time building it from scratch, I believe we will probably be on the same page next year.

In my opinion, creating the renderer from scratch requires a huge amount of work and ideally it can only begin with a few contributors.

That it's true. But even then, I think that's easier than making WebGLRenderer harder to maintain by adding conditionals everywhere. I've spent most of my last 5 years trying to make WebGLRenderer easier to read and maintain.

Also, I think @fernandojsg was planning on giving it a go in the coming weeks.

That's awesome. Looking forward to great work from @fernandojsg!!

P.S. I gotta say.. Thank all of the contributors of this project for widening my horizon of the computer graphics. Hoping I will be able to contribute some examples in the future.

I agree with @mrdoob that it will be easier to create a new renderer from scratch than modified the current one.
As he said, I wanted to give it a try in the following weeks. My approach is to start creating just what it's needed for a simple box on the screen and keep adding features to it step by step, instead of taking what is already there and try to refactor it.
As an example just take a look at the current state of the WebGLRenderer, there have been lot of discussions about making it more modular and customizable but still even if the internal code keeps improving over the time, outside from there it's just a black box.
As soon as I'll have something working I'll open a PR so we could keep discussing there the next steps.

While we are at it... 5f889ce296aaf447ec5992a6df726691098a9110 8aab6e0382cd6ba8fd3fb943e7f65141bf3a50bc
webgl2_sandbox works again (requires es6 modules though).

@mrdoob do you have any rough estimate when will it be available in master / release? :) I'm happy it is happening! :)

@wdanilo Not really... What features from WebGL2 do you need?

@mrdoob the biggest improvements would come from the Uniform Buffer Objects and the Sampler2DArray. The texture array would be seriously beneficial to my current project because we're up against texture unit limits as I'm using a complex shader that layers multiple materials masked by alpha maps.

@mrdoob New keywords like flat in glsl would be very helpful too.

My project needs 3D textures.

Interesting...
Super helpful to be aware of the specific cases people need WebGL 2.0 for.
Keep them coming!

3D Textures is also the big feature for us. I think we also use some shader features.

Sometimes I want MRT

+1 for multiple render targets too

Multiple render targets is already supported in WebGL1 via an extension, and there's even a PR for it in ThreeJS: https://github.com/mrdoob/three.js/pull/9358 (demo).

I think multisample render targets is my favourite feature. Most clients request post-processing (bloom, LUTs, etc) but they are disappointed in the lack of proper anti-aliasing once the post FX are implemented. With MSAA render targets we can finally have a nicely anti-aliased _and_ post-processed scene.

I agree. Workaround shaders for anti aliasing on post processed scenes with effects composer do not suffice for true anti aliasing.

+1 for draw feedback. Or is it already supported as webgl1 extension in
three?

On Thu, Dec 14, 2017 at 9:45 PM Kyle notifications@github.com wrote:

I agree. Workaround shaders for anti aliasing on post processed scenes
with effects composer do not suffice for true anti aliasing.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/mrdoob/three.js/issues/9965#issuecomment-351815640,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AHTX1RhYdGuTVSpmOy1ka-6gy1eslHQAks5tAXrFgaJpZM4Kj_9l
.

I've got couple of use cases here:

  1. I need MRT - currently I'm rendering the same shader 4 or 5 times, changing an attribute just to get different buffers.
  2. Rendering to texture with antialiasing is an important feature for us - we make an "node editor" with visualisation preview. Each visualisation is just a texture we draw something too and no proper antialiasing is a pain here.
  3. The "flat" keyword - I'm now indexing geometry with an float attribute, which obviously is sub-optimal - worse than indexing with uint one. I'm passing this attribute from vertex to fragment shader and I cannot use uint now, because we lack the support of "flat" kwrd.
  4. (smaller) 3D textures are great for high end visualisations that we would like to support in near future.

Using anti-aliasing and post-processing together is the most important one for me.

@mrdoob My top 3 WebGL 2 Features/Use cases (in order of importance):

  1. Multisampled Render Targets: For proper (MS)AA in post-processing.
  2. Integer Textures: For doing image based algorithms like Signed Distance Fields, as well as using more exotic texture based data like DEM (Digital Elevation Models).
  3. Transform Feedback: For doing particle systems.

@mrdoob by the way, do you know why #9358 PR was not merged? As @mattalat have written, it brings multitarget rendering to threejs. Was commited 2 years ago, fixed several times to keep up to date with other changes and until now it's not there :(

I'm asking about it because I've got a scene heavily using SDF shape descriptions. Each shape outputs 6 different outputs, so now I compute it 6 times passing to the shader numbers from 0 to 5. It would be much nicer to use mutliple outputs and it will bring simply 5x performance boost.

@wdanilo It was probably not the right time (many moving things in the renderer at the time). Also, seems like it included the builds which cause conflicts easily. Anyone up for doing a new PR?

/cc @edankwan

We need 3D Textures and Multisample Render targets.

I'm looking to use it so i can set depthTexture.type = THREE.FloatType.. unless there is another way to currently do such a thing.

Is there a hope that LineThickness other than 1 would be working on Windows and WebGL 2.0 ? If yes, it would improve some of our outputs.

And here I reply to myself. Reading thickness-of-lines-using-three-linebasicmaterial on SO I understood that thick lines will need a geometry in the future anyway.

@Richard004 This has nothing to do with WebGL 2. We already have a PR for this feature request, see #11349 👍

Hi @mrdoob and @Mugen87
I need bit manipulations inside the fragment shader as well as dynamic array indexing. The first one is probably not very common, but I need it regardless because I'm trying to port a CUDA kernel over to WebGL (GLSL) and other shader languages allow bit manipulations, but WebGL 1.0 (GLSL) does not.

The second one I think a lot of developers could benefit from: that is, accessing an array element with a variable. Currently in WebGL 1.0 (GLSL), a program like this will fail:

int myData[200];
int x = 3; // 'x' might change later based on my lookup needs
int requestedData = myData[x];

However in WebGL 2.0, you can do this. It is often needed inside a loop, where you need to get different values from an array, but you can't just do an iterative loop (0 to 199 in the example above for instance), because then you would need to check every single element and that's really slow.

Antialiasing in Postprocessing would definately be beneficial.

Under all this is the question: is it time for a new architecture for Three?

I recently started using D3, version 4. It was a complete redesign. Es6
modules. And far more important, 30 modules, each of which was its own
repo. I really recommend looking at the D3 architecture.

I'm not saying we need this for Three, but I think we could consider a
major version bump. Partially due to webgl2. But also due to need for
sub-modules.

An example: There is a D3 "selections" repo/sub-module. It's your basic
jQuery DOM module but with all the verbosity of the DOM hidden in a
functional, chaining design. It can be used as-is without using the rest of
D3.

Wouldn't you love a Three independent module that made all the webgl
verbosity disappear? Maybe even multiple sub-modules for webgl ctx/shader
management, buffer management, and so on. Indeed, the buffer geometry is a
lot like this. Ditto for shader creation from parts.

Just a thought.

@fetox74 Pretty sure you can do AA already https://threejs.org/examples/?q=fxaa#webgl_postprocessing_fxaa

@elunty the FXAAShader doesn't produce a good enough result compared to original antialiasing, I've used it in the wild.

i'm mostly interested in VAOs and writing to mipmaps which i hope is possible under that spec.

@pailhead Related #8705 :wink:

Looking forward to the native support for EXT_shader_texture_lod.
It may resolve the artifacts being generated while using MeshStandardMaterial and MeshPhysicalMaterial on most of the Android devices and MS Edge and Internet Explorer

@mrdoob are there any plans from you or your team to update Threejs to Webgl 2.0? This thread takes literally years and nothing really changes while all other frameworks already moved forward. I’ll have a hard decision soon, we would probably have to migrate over Babylon or something and I would really like to stay with Three. I will, if there would be any, just any plans for its modernization.

@wdanilo if WebGL 2.0 is a priority for your project I would recommend you to migrate over to Babylon. I know some three.js contributors are planning on working on it, but I'm personally focused on WebVR and artists workflows (svg support, etc).

@mrdoob I really appreciate your fast answer here. I'd really like not to abandon three.js. I like how the lib is constructed under the hood and its assumptions to be "general" framework, not "game-focused" etc. Anyway, thank you for the information and keeping this clear.

(Thanks again @takahirox, I was aware of this thread). I just made a pull request #13692. I understand that the focus is not on it but for our purposes, it's been working well.

Related #13702

I made WebGL2 base branch following #9965 and #12250

Repo: https://github.com/takahirox/three.js/tree/WebGL2Base
Examples: https://rawgit.com/takahirox/three.js/WebGL2Base/examples/index.html

You can start WebGL2.0 + Three.js with it.

(Sorry conflicting with @yoshikiohshima work)

@mrdoob Can we have a branch for WebGL2Renderer like three.js/dev-2.0? Or can we merge it into dev tho there still be a lot of duplicated codes between for webgl1 and for webgl2?

I am new to the past development on this issue. @takahirox, can you summarize the strategy you are taking in and what are supported by https://github.com/takahirox/three.js/tree/WebGL2Base? (and again sorry for my ignorance) but I did not see the need for a lot of duplicated code to support WebGL2. What are the issues?

@mrdoob Can we have a branch for WebGL2Renderer like three.js/dev-2.0? Or can we merge it into dev tho there still be a lot of duplicated codes between for webgl1 and for webgl2?

Not sure why this would need a new branch. Why would there be duplicated code?

Seems no conflicts. There're two demands for WebGL2.0 now.

  1. Making WebGL2Renderer to support full WebGL2.0 features and optimizing well
  2. Adding webgl2 support to existing WebGLRenderer. But we don't fully support WebGL2.0 features on it and don't optimize for WebGL2.0 because we don't wanna make renderer messed. So basically this's just for early access of Three.js + WebGL2.0 + GLSL3.0

Mine is for 1. His work is for 2. We don't have duplicated code and don't need to make a new branch for 2.

@takahirox I think it would be better to work in the same branch for the time being.

If you improve...

https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGL2Renderer.js

and the webgl2 examples import classes directly (not needing builds)...

https://github.com/mrdoob/three.js/blob/dev/examples/webgl2_sandbox.html#L39-L47

there shouldn't be conflicts.

You can forget my WebGL2Base so far because it seems we start WebGL2.0 support in one WebGLRenderer.

Are we still thinking about implementing a WebGL2Renderer?
I have been looking a lot lately to add WebGL2 support, and I am waiting for takahirox changes to rebase mine. But after doing some changes, I started to think that rewriting the renderer would be a really good idea, as well as the WebGLTextures object. If it is still topical, I would be glad to participate.

I think so yes. I think adding basic webgl 2.0 support to the current WebGLRenderer is just to have something while we work on WebGL2Renderer.

Feel free to start rewriting the renderer and send PRs (ideally step by step).

Apologies if asking the obvious, but after reading this whole issue, with the last post being half a year ago, and finding a few references to webgl2 in both the master source code and examples, I still can't seem to quite figure it out.

Wonder if webgl2 is any usable in its current state in Three.js? (even if just rendering simple buffergeometry meshes) Would the EffectComposer work with a webgl2-context-enabled renderer? Would the render target have to be adjusted in any way?

The biggest question, of course, is whether it's currently possible to get proper antialiasing when using composer with custom passes?

Seems like in the end we just ended up adding WebGL 2.0 features to WebGLRenderer.
WebGPU will sure need a WebGPURenderer though.

Was this page helpful?
0 / 5 - 0 ratings