[Public WebGL] using the same context with multiple canvases

Florian Bösch [email protected]
Wed Mar 25 08:11:17 PDT 2015

The drawImage idea has some issues:

   - It's currently not hardware accelerated (and I'm not sure it can be).
   - It induces a sync stall because you have a sync-point (drawImage) and
   in order for that to work, the browser has to run the GL commands up to
   that point.
   - If you need to render several different resolutions (that's almost
   always the case) you'll end up resizing the canvases drawing buffer several
   times each frame.

I don't think it's an adequate workaround. A proper solution is to be able
to setup drawing buffers to draw to, and to connect them to a canvas, and
whatever you draw while one is bound, is what ends up being displayed in
that canvas.

On Wed, Mar 25, 2015 at 4:02 PM, Ashley Gullen <[email protected]> wrote:

> It's possible to render a WebGL-rendered canvas to a 2D context canvas
> with drawImage(). So it seems to me the workaround is just to have one
> off-screen WebGL context that does all the real rendering, and then
> drawImage the result to a 2D canvas in the document. This seems to me to
> have several advantages:
> - works today (nothing more to be specced)
> - GPU-accelerated copying (assuming it's possible for drawImage() to be
> GPU-accelerated when passed a WebGL canvas, regardless of whether real
> implementations do it today - if they do not then this should be added)
> - no need to share resources between contexts or load resources twice,
> since there is only one context
> - can update multiple canvases per frame simply by rendering multiple
> views in one rAF and copying them out to their respective 2D canvases
> during rendering
> If some canvases are different sizes, then the WebGL context just needs to
> be as big as the largest. It can change its viewport and add a scissor
> rectangle to save fillrate during rendering too, and drawImage can specify
> the source area to render from the source WebGL canvas.
> This seems to work OK to me, but perhaps I have missed something? I can
> see it would be a performance improvement if a single draw call could draw
> to two canvases at once, perhaps from different views, but the above
> solution seems workable and AFAICT in theory can stay GPU-side without any
> readback.
> This does not cover rendering from a worker, which I do still think is a
> valuable addition but appears separate to this particular email thread.
> Ashley
> On 25 March 2015 at 13:52, Javi Agenjo <[email protected]> wrote:
>> I just wanted to say that I rely in the same solution as Florian for my
>> materials editor, I considered for a long time using a secondary canvas,
>> but that implies that I must store the Images of every texture (instead of
>> removing them once uploaded to VRAM) in case another Canvas needs those
>> textures, so that increases the RAM I need for the whole application.
>> I still think that some kind of middle ground solution for those cases
>> would be great, not sharing the same resources but allowing cloning data
>> from one context to another directly, like passing the handler of another
>> texture to the texImage2D even if it those come from the same WebGL
>> Context. (I don't know if anyone has considered that option).
>> On Wed, Mar 25, 2015 at 8:46 AM, Florian Bösch <[email protected]> wrote:
>>> Just yesterday I ran into that problem again (for a PBR material
>>> manager) where I'd like to show previews of materials as rendered on a
>>> sphere.
>>> Since the main canvas is supersampled and fxaa'ed It'd be expensive to
>>> update via readback, so that one is rendered from the context as usual. The
>>> previews are also ssaed, but the thumbnails are only 100x100 pixels, so
>>> each time a user touches any control (slider, color picker etc.) they're
>>> rendered off-screen to an fbo and readback to be put into the thumbnails 2D
>>> canvas.
>>> I could probably substitute the thumbnails "off-line" canvas 2D with a
>>> second GL canvas for the duration of modification of that material. And
>>> while that may work well, it's not a solution to usecases that require more
>>> than 1-2 canvases to be updated simultaneously (and neither is the readback
>>> and copy in solution).
>>> I run into that sort of problem every couple of months. It's quite
>>> annoying.
>>> On Mon, Mar 23, 2015 at 9:29 PM, Aleksandar Rodic <
>>> [email protected]> wrote:
>>>> The workaround I came up with was a canvas wrapper which migrates the
>>>> real canvas and its GL context at render time. The canvases which are
>>>> not rendering show static stand-in canvas with a copy of the image which
>>>> was last rendered.
>>>> This approach works great if you only update one canvas at a time. Rendering
>>>> to multiple canvases simultaneously causes expensive canvas migrations
>>>> (copying image data).
>>>> Aki
>>>> On Mon, Mar 23, 2015 at 11:04 AM Mitchell Williams <
>>>> [email protected]> wrote:
>>>>> If I understand the issue, it sure would be nice if this worked.
>>>>> I tried to render the scene from a camera to another window (such as
>>>>> when 3DS Max can view a scene in perspective view, and that scene contains
>>>>> a camera which we can see the scene from the camera's view in another
>>>>> window).
>>>>> As an alternative, I rendered the scene as a texture map, but all
>>>>> contained within a single canvas.
>>>>> This would be nice to render a scene to multiple canvases.
>>>>> Mitch
>>>>> On Mon, Mar 23, 2015 at 12:06 AM, Florian Bösch <[email protected]>
>>>>> wrote:
>>>>>> The topic of how to draw to multiple canvases from a single context
>>>>>> (from either the JS main thread or a worker) has not yet been resolved
>>>>>> (correct me if I'm wrong).
>>>>>> A possible resolution seems to be the canvas.setContext method.
>>>>>> However, this seems to to be under specified, as just having a WebGL
>>>>>> context is not sufficient, you also need a drawing buffer which carries
>>>>>> attributes such as stencil, depth, bit-depth, MSAA, etc., and the WebGL 2
>>>>>> specification doesn't seem to contain anything about how to create either a
>>>>>> WebGL 2 context or a drawing buffer on its own (It just specifies that a
>>>>>> getContext call needs to do both).
>>>>>> Regardless of specification status or respective completeness, no
>>>>>> implementation of setContext is available, let alone anything to create
>>>>>> WebGL contexts and drawing buffers on their own to be used.
>>>>>> I'll posit that this isn't an acceptable situation. I'll reiterate
>>>>>> that quite frequently applications that do provide any kind of UI (like
>>>>>> sketchfab, verold, goo, fabric) need to put WebGL driven content into many
>>>>>> places inside that UI that isn't a single viewport. That content might find
>>>>>> itself CSS transformed, composited, scrolled in/out of view, inside an
>>>>>> overflow: scroll container, sandwiched between html elements etc. And that
>>>>>> content might need to be updated at each animation frame.
>>>>>> I'm frankly mystified why a topic we've been talking about for well
>>>>>> over 3 years and have been promised specifications/solutions for, that is
>>>>>> widely recognized as an important issue to solve, is nearly unspecified and
>>>>>> completely unsolved.
>>>>> --
>>>>> Mitch Williams
>>>>> Check out my book "*WebGL Hotshot*" available at:
>>>>> https://www.packtpub.com/web-development/webgl-hotshot
>>>>> 310-809-4836 (outside line)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://khronos.org/pipermail/public_webgl_khronos.org/attachments/20150325/ebbe1214/attachment.html>

More information about the public_webgl mailing list