20

I am trying to draw the same WebGL scene using two canvases side-by-side. Is it possible? So far I haven't been lucky.

The idea goes as follows:

  1. I load my geometry
  2. I set up two gl context, one per canvas
  3. I call drawElements on the first context passing my geometry
  4. I call drawElements on the second context passing my geometry

Results: Only the first invocation is successful. The second context executes gl.clear correctly but no geometry is displayed.

What am I missing? is this a spec constrain? or a limitation in the Firefox and Safari's implementations?

Thanks,

Diego
  • 605
  • 1
  • 4
  • 14
  • I thought I should leave a link to this solution: http://stackoverflow.com/a/33180165/128511 In particular [this webgl solution](http://twgljs.org/examples/itemlist.html), and [this three.js solution](http://threejs.org/examples/webgl_multiple_elements.html) – gman Mar 22 '17 at 19:50

3 Answers3

27

Yes, you can have more than one WebGL context on a page, but each context must manage it's own resources. You cannot create buffers or textures on one context and then use them on the other, so to use this approach if you wanted to render the same scene you would need to load all your resources twice.

That's certainly doable, but it will be very memory intensive (as you might imagine). A better solution would be to create a context that is 2x the width you need and use gl.viewport and gl.scissor to render to half of it for each view of the scene.

Or, make a full viewport size canvas and use the scissor/viewport settings to match other html elements. See this Q&A: How can we have display of same objects in two canvas in webgl?

gman
  • 100,619
  • 31
  • 269
  • 393
Toji
  • 33,927
  • 22
  • 105
  • 115
  • I had thought of the viewport option too. But I like to complicate things just to see what can be done. lol. thanks. – Diego Feb 16 '12 at 01:31
3

That should have thrown an error. As Toji said, two WebGLContexts cannot share resources. There is, however, a proposal for this. Check here. I suspect we'll see something similar in WebGL soon.

Chris Broadfoot
  • 5,082
  • 1
  • 29
  • 37
  • Ooh! Nice! I didn't know that was on the table. – Toji Feb 09 '12 at 01:16
  • Extension proposal here: https://www.khronos.org/registry/webgl/extensions/WEBGL_shared_resources/ – prideout Nov 04 '14 at 16:12
  • 4
    FYI that proposal was abandoned. I know as I wrote it, I also implemented it and in doing so realized it was the wrong solution. The new solution is `OffscreenCanvas` though it hasn't shipped yet – gman Jul 13 '17 at 08:45
1

I use multiple WebGL contexts on a single page by assigning the same class to the canvasses that should render the WebGL content, and putting something specific in the canvas inner html:

function specific(what) {
    switch (what) {
    case 'front':
        //do something
        break;
    case 'side':
        //do something else
        break;
    }
}

function webGLStart() {
    var canvasArray = document.getElementsByClassName("webGLcanvas");
    for (var index = 0; index < canvasArray.length; ++index) {
        initWebGlContext();
        specific(canvasArray[index].innerHTML);
    }
}

</script>
</head>

<body onload="webGLStart();">
    <canvas class="webGLcanvas">front</canvas>
    <canvas class="webGLcanvas">side</canvas>
</body>

You can find a working example here.

As earlier answers (Toji and Chris Broadfoot) explained, you need to keep in mind that you cannot share resources between WebGL contexts.

edit: code is now available on github.

Danny Ruijters
  • 3,411
  • 2
  • 18
  • 21