Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Occlusion of real-world objects using three.js

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.

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).

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

like image 773
jdb51 Avatar asked Mar 06 '15 20:03

jdb51


People also ask

What can three js be used for?

Three. js is a powerful library for creating three-dimensional models and games. With just a few lines of JavaScript, you can create anything from simple 3D patterns to photorealistic, real-time scenes. You can build simple and complex 3D geometrics, animate and move objects through a lifelike scene, and more.

What's the relationship between WebGL and three js?

If you use Three. js, you don't need to know how to program in WebGL, you just need to understand the WebGL concepts. That means, that you just need to be able to read someone else's WebGL code and understand what you read. That is a lot easier than being expected to write a WebGL program yourself from scratch.

Is Three js a framework?

js is the world's most popular JavaScript framework for displaying 3D content on the web.


1 Answers

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


MY ORIGINAL ANSWER (without using the new features in 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”.

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.

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:

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.

like image 120
Blair MacIntyre Avatar answered Sep 30 '22 19:09

Blair MacIntyre