在多个画布上显示共享资源的不同场景 [英] Display different scenes sharing resources on multiple canvases

查看:265
本文介绍了在多个画布上显示共享资源的不同场景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用three.js创建了一个交互式web应用程序,并且遇到了一些绊脚石:



我有许多画布在页面上可拖动div。在每个画布中,我希望显示应用了不同材质的未照明3D对象(每种材质都使用自定义着色器)。所有这些材料都具有相同的纹理(一种可能是蓝色的,一种可能是去饱和的等)。



页面上的画布数量可能会有所不同,但我预计这个数字通常会达到或超过20个画布,因此这种共享资源(尤其是对于大尺寸纹理)将是非常有益的。

到目前为止,我拥有一直使用多个渲染器,相机和场景,直到我开始尝试在多个场景中使用相同的纹理。

大多数材质共享制服和属性以避免不得不复制这些信息,并且也要保证所有材料保持同步(例如,当一些材料随时间变化时,它们应该都以相同的方式改变)。

我想知道是否有一种方法可以在场景/渲染器/画布之间共享纹理?当我尝试时,我得到以下错误:

  WebGL:INVALID_OPERATION:bindTexture:object not this context 

code>

在我的研究中,试图找到解决这个问题的方法,但是我发现这个问题可以通过创建多个视口来解决,但是我不知道如何在不同的画布上显示不同的视口。

  TL / DR; 

我可以:


  • 在不同的场景,渲染器和/或画布上使用相同的制服(包括纹理制服)?
  • $ b
  • 在不同的画布上显示相同的场景? $ b


预先感谢!

Griffork

遗憾的是,你仍然无法在画布之间共享资源。一些选项


  1. 渲染同一画布不同部分中的不同视口。



    示例: http://webglsamples.org/multiple-views/ multiple-views.html

  2. 建立一个覆盖整个窗口的画布,使用占位符元素来确定绘制位置,使用getClientBoundingRect设置视口&剪刀设置在每个元素中绘制场景

    示例:是否可以在THREE.js中启用无限数量的渲染器?


  3. 将场景渲染到屏幕外画布,然后将其绘制到可见的画布中。

     < canvas id = C1 >< /画布> 
    < canvas id =c2>< / canvas>
    < script>
    var webglCanvas = document.createElement(canvas);
    var canvas1 = document.getElementById(c1);
    var ctx1 = canvas1.getContext(2d);
    var canvas2 = document.getElementById(c1);
    var ctx2 = canvas1.getContext(2d);

    ...从一个视图中将场景绘制到webglCanvas中...

      //将场景复制到canvas1 
    ctx1.drawImage(webglCanvas,0,0);

    ...从另一个视图中将场景绘制到webglCanvas中...

      //将场景复制到canvas2 
    ctx2.drawImage(webglCanvas,0,0);



    以下是一个实例(注意:Chrome26和FF20的Windows速度很慢,希望将在未来的浏览器中修复)

  4. 使用OffscreenCanvas,transferToImageBitmap等...(注意:此功能自2018年1月1日起未在任何浏览器中发货) 8,但它在Firefox上的一个标志后面)

  5. data-hide =truedata-console =truedata-babel =false>

      const one = document.getElementById(one)。getContext(bitmaprenderer); const two = document.getElementById(two)。getContext(bitmaprenderer); const offscreen = new OffscreenCanvas(256,256); constr gl = offscreen.getContext('webgl'); // ...一些绘图第一个使用gl上下文的画布... gl.clearColor(1,0,0,1); gl.clear(gl.COLOR_BUFFER_BIT); //提交渲染到第一个小薄片bitmapOne = offscreen.transferToImageBitmap(); one。 transferImageBitmap(bitmapOne); // ...使用gl上下文为第二个画布绘制更多... gl.clearColor(0,1,0,1); gl.clear(gl.COLOR_BUFFER_BIT); //提交渲染到第二个画布让bitmapTwo = offscreen.transferToImageBitmap(); two.transferImageBitmap(bitmapTwo);  

     < canvas id =one>< / canvas>< canvas id =two>< / canvas>  


I'm using three.js to create an interactive web application, and I've run into a little stumbling block:

I have a number of canvases contained in draggable divs on the page. In each canvas I hope to display an unlit 3D object with a different material applied (each material is using custom shaders). All of those materials work off the same texture (one might be blue-tinted, one might be desaturated, etc.).

The number of canvases on the page can vary, but I expect the number to commonly reach/exceed 20 canvases, and as such sharing resources (particularly for large textures) would be very beneficial.

Up until now I have been using multiple renderers, cameras and scenes which has worked fine until I started trying to use the same texture in multiple scenes.

Most of the materials share uniforms and attributes to avoid having to duplicate the information, and also so that all of the materials stay in sync with one another (e.g. when some of the materials change over time they should all change in the same way).

I was wondering if there was a way I would be able to share textures between the scenes/renderers/canvases? When I try I get the following error:

WebGL: INVALID_OPERATION: bindTexture: object not from this context 

In my research trying to find a solution for this problem I came across the suggestion that this could be solved by creating multiple viewports, however I do not know how to display different viewports over different canvases.

TL/DR;

Can I either:

  • Show the same scene across different canvases?
  • Use the same uniforms (including a texture uniform) across different scenes, renderers and/or canvases?

Thanks in advance!

Griffork

解决方案

Unfortunately you can not (yet) share resources across canvases. A couple of options

  1. Render the different viewports in different parts of the same canvas.

    Example: http://webglsamples.org/multiple-views/multiple-views.html

  2. Make a canvas that covers the entire window, use place holder elements to figure out where to draw, use getClientBoundingRect to set the viewport & scissor settings to draw scenes in each element

    Example: Is it possible to enable unbounded number of renderers in THREE.js?

  3. Render the scene to an offscreen canvas then draw it into a visible canvases.

    <canvas id="c1"></canvas>
    <canvas id="c2"></canvas>
    <script>
    var webglCanvas = document.createElement("canvas");
    var canvas1 = document.getElementById("c1");
    var ctx1 = canvas1.getContext("2d");
    var canvas2 = document.getElementById("c1");
    var ctx2 = canvas1.getContext("2d");
    

    ... draw scene into webglCanvas from one view...

    // copy scene to canvas1
    ctx1.drawImage(webglCanvas, 0, 0);
    

    ... draw scene into webglCanvas from another view...

    // copy scene to canvas2
    ctx2.drawImage(webglCanvas, 0, 0);
    

    Here's a live example (note: It's slow on Windows in Chrome26, FF20, Hopefully that will be fixed in future browsers)

  4. Use OffscreenCanvas, transferToImageBitmap etc... (note: this feature has not shipped in any browser as of 2018/1/8 but it's available behind a flag on Firefox)

const one = document.getElementById("one").getContext("bitmaprenderer"); 
const two = document.getElementById("two").getContext("bitmaprenderer");

const offscreen = new OffscreenCanvas(256, 256);
constr gl = offscreen.getContext('webgl');

// ... some drawing for the first canvas using the gl context ...
gl.clearColor(1,0,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);

// Commit rendering to the first canvas
let bitmapOne = offscreen.transferToImageBitmap();
one.transferImageBitmap(bitmapOne);

// ... some more drawing for the second canvas using the gl context ...
gl.clearColor(0,1,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);

// Commit rendering to the second canvas 
let bitmapTwo = offscreen.transferToImageBitmap();
two.transferImageBitmap(bitmapTwo);

<canvas id="one"></canvas>
<canvas id="two"></canvas>

这篇关于在多个画布上显示共享资源的不同场景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆