使用three.js遮挡现实世界的对象

时间:2022-07-07 03:37:56

I’m using three.js inside an experimental augmented-reality web browser. (The browser is called Argon. Essentially, Argon uses Qualcomm’s Vuforia AR SDK to track images and objects in the phone camera. Argon sends the tracking information into Javascript, where it uses transparent web pages with three.js to create 3D graphics on top of the phone video feed.) My question is about three.js, however.

我在一个实验性的增强现实Web浏览器中使用了three.js. (浏览器称为Argon。实际上,Argon使用Qualcomm的Vuforia AR SDK来跟踪手机摄像头中的图像和对象.Argon将跟踪信息发送到Javascript,在那里它使用带有three.js的透明网页来创建3D图形。手机视频输入。)我的问题是关于three.js。

The data Argon sends into the web page allows me to align the 3D camera with the physical phone camera and draw 3D graphics such that they appear to align with the real world as expected. I would also like to have some of the things in the physical world occlude the 3D graphics (I have 3D models of the physical objects, because I’ve set the scene up or because they are prepared objects like boxes that are being tracked by Vuforia).

Argon发送到网页的数据允许我将3D相机与物理手机相机对齐并绘制3D图形,使其看起来与预期的现实世界一致。我还想让物理世界中的一些东西遮挡3D图形(我有物理对象的3D模型,因为我已经设置了场景,或者因为它们是准备好的对象,如Vuforia正在跟踪的盒子)。

I’m wondering if folks have suggestions on the best way to accomplish this occlusion with three.js. Thanks.

我想知道人们是否有关于使用three.js完成此遮挡的最佳方法的建议。谢谢。

1 个解决方案

#1


6  

EDIT: it appears that the next version of three.js (R71) will have a simpler way to do this, so if you can use the dev branch (or just wait), you can do this much more easily. See this post: three.js transparent object occlusion

编辑:似乎下一个版本的three.js(R71)将有一个更简单的方法来做到这一点,所以如果你可以使用dev分支(或只是等待),你可以更容易地做到这一点。看到这篇文章:three.js透明对象遮挡


MY ORIGINAL ANSWER (without using the new features in R71):

我的原始答案(不使用R71中的新功能):

I think the best way to do this is (to avoid extra work by creating new rendering passes for example) to modify the WebGL renderer (src/renderers/WebGLRenderer.js) and add support for a new kind of object, perhaps call them “occlusionObjects”.

我认为最好的方法是(通过创建新的渲染过程来避免额外的工作)来修改WebGL渲染器(src / renderers / WebGLRenderer.js)并添加对新类型对象的支持,也许称之为“ occlusionObjects”。

If you look in the renderer, you will see two current object lists, opaqueObjects and transparentObjects. The renderer sorts the renderable objects into these two lists, so that it can render the opaque objects first, and then the transparent objects after them. What you need to do is store all of your new objects into the occlusionObjects list rather than those two. You will see that the opaque and transparent objects are sorted based on their material properties. I think here, you may want to add a property to an object you want to be an occluder (“myObject.occluder = true”, perhaps), and just pull those objects out.

如果查看渲染器,您将看到两个当前对象列表,opaqueObjects和transparentObjects。渲染器将​​可渲染对象排序到这两个列表中,以便它可以先渲染不透明对象,然后再渲染透明对象。您需要做的是将所有新对象存储到occlusionObjects列表中而不是那两个。您将看到不透明和透明对象根据其材质属性进行排序。我想在这里,您可能想要将一个属性添加到您想要成为封堵器的对象(可能是“myObject.occluder = true”),然后将这些对象拉出来。

Once you have the three lists, look what the render() function does with these object lists. You’ll see a couple of places with rendering calls like this:

获得三个列表后,查看render()函数对这些对象列表的作用。你会看到几个像这样的渲染调用的地方:

renderObjects( opaqueObjects, camera, lights, fog, true, material );

Add something like this before that line, to turn off writing into the color buffers, render the occlusion objects into the depth buffer only, and then turn color buffer writes back on before you render the remaining objects.

在该行之前添加类似的内容,关闭写入颜色缓冲区,仅将遮挡对象渲染到深度缓冲区中,然后在渲染剩余对象之前重新打开颜色缓冲区写入。

context.colorMask( false, false, false, false);
renderObjects( occluderObjects, camera, lights, fog, true, material );
context.colorMask(true, true, true, true);

You’ll need to do this in a couple of places, but it should work.

你需要在几个地方这样做,但它应该工作。

Now you can just mark any objects in your scene as “occluder = true” and they will only render into the depth buffer, allowing the video to show through and occluding any opaque or transparent objects rendered behind them.

现在,您可以将场景中的任何对象标记为“occluder = true”,它们只会渲染到深度缓冲区中,允许视频显示并遮挡在其后面渲染的任何不透明或透明对象。

#1


6  

EDIT: it appears that the next version of three.js (R71) will have a simpler way to do this, so if you can use the dev branch (or just wait), you can do this much more easily. See this post: three.js transparent object occlusion

编辑:似乎下一个版本的three.js(R71)将有一个更简单的方法来做到这一点,所以如果你可以使用dev分支(或只是等待),你可以更容易地做到这一点。看到这篇文章:three.js透明对象遮挡


MY ORIGINAL ANSWER (without using the new features in R71):

我的原始答案(不使用R71中的新功能):

I think the best way to do this is (to avoid extra work by creating new rendering passes for example) to modify the WebGL renderer (src/renderers/WebGLRenderer.js) and add support for a new kind of object, perhaps call them “occlusionObjects”.

我认为最好的方法是(通过创建新的渲染过程来避免额外的工作)来修改WebGL渲染器(src / renderers / WebGLRenderer.js)并添加对新类型对象的支持,也许称之为“ occlusionObjects”。

If you look in the renderer, you will see two current object lists, opaqueObjects and transparentObjects. The renderer sorts the renderable objects into these two lists, so that it can render the opaque objects first, and then the transparent objects after them. What you need to do is store all of your new objects into the occlusionObjects list rather than those two. You will see that the opaque and transparent objects are sorted based on their material properties. I think here, you may want to add a property to an object you want to be an occluder (“myObject.occluder = true”, perhaps), and just pull those objects out.

如果查看渲染器,您将看到两个当前对象列表,opaqueObjects和transparentObjects。渲染器将​​可渲染对象排序到这两个列表中,以便它可以先渲染不透明对象,然后再渲染透明对象。您需要做的是将所有新对象存储到occlusionObjects列表中而不是那两个。您将看到不透明和透明对象根据其材质属性进行排序。我想在这里,您可能想要将一个属性添加到您想要成为封堵器的对象(可能是“myObject.occluder = true”),然后将这些对象拉出来。

Once you have the three lists, look what the render() function does with these object lists. You’ll see a couple of places with rendering calls like this:

获得三个列表后,查看render()函数对这些对象列表的作用。你会看到几个像这样的渲染调用的地方:

renderObjects( opaqueObjects, camera, lights, fog, true, material );

Add something like this before that line, to turn off writing into the color buffers, render the occlusion objects into the depth buffer only, and then turn color buffer writes back on before you render the remaining objects.

在该行之前添加类似的内容,关闭写入颜色缓冲区,仅将遮挡对象渲染到深度缓冲区中,然后在渲染剩余对象之前重新打开颜色缓冲区写入。

context.colorMask( false, false, false, false);
renderObjects( occluderObjects, camera, lights, fog, true, material );
context.colorMask(true, true, true, true);

You’ll need to do this in a couple of places, but it should work.

你需要在几个地方这样做,但它应该工作。

Now you can just mark any objects in your scene as “occluder = true” and they will only render into the depth buffer, allowing the video to show through and occluding any opaque or transparent objects rendered behind them.

现在,您可以将场景中的任何对象标记为“occluder = true”,它们只会渲染到深度缓冲区中,允许视频显示并遮挡在其后面渲染的任何不透明或透明对象。