允许更多的 WebGL 上下文

Tre*_*ast 5 javascript google-chrome webgl pixi.js

我目前正在处理一个包含项目列表的网站。每个项目都有一个缩略图,我正在使用PixiJS 为所有项目添加着色器效果。问题是列表上有超过 16 个项目,所以我收到以下错误:

警告:活动的 WebGL 上下文太多。最旧的上下文将丢失。

有没有办法增加这个限制?我无法在 WebGL 上制作整个页面,而且使用非常有限(没有交互,精简效果),我认为更多的 WebGL 上下文不会使页面滞后或其他什么。

gma*_*man 15

Not it is not possible to increase the limit. (well you could write your own browser).

To make a list of items you can use solutions like in this Q&A

Multiple WebGL models on the same page

which are detailed in this article for WebGL and this article for three.js

Here are 3 solutions.

  1. (fastest) Use a single WebGL canvas that covers the page. Use place holder elements to mark where you want to draw things. Loop through those elements calling element.getBoundingClientRect and use the viewport and scissor settings to draw in those places, only drawing the ones that are visible (some may be offscreen and don't need to be drawn). This is the soution shown in the links above.

  2. Use a single offscreen WebGL canvas. Put 2D canvases in your page. Draw each item to the offscreen canvas and use drawImage to draw it to the correct 2D canvas. this solution is slightly more flexible since the 2D canvas elements can be more freely styled but it's slower than the previous solution and uses more memory.

    Note: it's probably best to make the WebGL canvas the size of the largest 2D canvas, then for each 2D canvas, set gl.viewport to the size of that 2D canvas and then use the full form of drawImage to select a portion of the WebGL the correct size portion of the WebGL canvas to draw the current 2D canvas. Resizing a canvas is a heavy operation I believe. In other words something like:

    for each 2D canvas
       webgl canvas size = max(webgl canvas size, 2D canvas size) // for each dimension
       gl.viewport(0, 0, 2D canvas size);
       draw scene for canvas
       ctx.drawImage(
           0, 0, 2D canvas size, 
           0, webgl canvas height - 2d canvas height, 2D canvas size)
    
    Run Code Online (Sandbox Code Playgroud)
  3. Use a virtual webgl context which you can implement on your own or use a library. Not recommended (slowest) but it is a quick solution.

Note: having multiple contexts is not a recommended solution. Textures, vertices, and shaders can not be shared between WebGL contexts. That means if you use the same image in 2 or more contexts it has to be loaded into memory once for each context. Similarly for each context a shader is used it has to be compliled and linked for each context. In other words using multiple contexts uses more memory and increases startup time significantly.

Unfortunately since you tagged your questions both WebGL and pixi.js this answer is probably irrelevant to you. I have no idea if this is possible in pixi.js. I see no documentation to suggest how to do it efficiently.

  • @gman您不必实际交换上下文,您可以重复使用画布并只是移动它们,与虚拟化列表相同。如果您有一个很长的滚动列表,此解决方案可能会起作用,但取决于他的内容/布局设计。我不会推荐这个解决方案,它只是一个可能的替代方案。 (2认同)