如何在复杂场景中快速查找某个点是否被遮挡? [英] How to quickly find if a point is obscured in a complex scene?

查看:51
本文介绍了如何在复杂场景中快速查找某个点是否被遮挡?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个复杂的 3D 场景,我需要根据 3D 坐标在其上显示 HTML 元素.(我只是在顶部覆盖一个 div 标签并用 CSS 定位它.)但是,当 3D 坐标被模型遮挡时,我还需要部分隐藏它(例如,使其透明)(或以另一种方式表达,当它在相机中不可见时).这些模型可能有成百上千的人脸,我需要一种方法来确定它是否被遮挡,其速度足以每秒运行多次.

I have a complex 3D scene that I need to display HTML elements on top of, based on a 3D coordinate. (I'm simply overlaying a div tag on top and positioning it with CSS.) However, I also need to partially hide it (e.g., making it transparent) when the 3D coordinate is obscured by a model (or phrased in another way, when it's not visible in the camera). These models may be have many hundreds of thousands of faces, and I need a way to find out if it's obscured that's fast enough to be run many times per second.

目前,我使用 Three.js 的内置光线追踪器,代码如下:

Currently, I am using Three.js's built-in raytracer, with the following code:

// pos   = vector with (normalized) x, y coordinates on canvas
// dir   = vector from camera to target point

const raycaster = new THREE.Raycaster();
const d = dir.length(); // distance to point
let intersects = false;
raycaster.setFromCamera(pos, camera);
const intersections = raycaster.intersectObject(modelObject, true);
if (intersections.length > 0 && intersections[0].distance < d)
    intersects = true;

// if ray intersects at a point closer than d, then the target point is obscured
// otherwise it is visible

然而,在这些复杂模型上,这非常很慢(帧速率从 50 fps 下降到 8 fps).我一直在寻找更好的方法来做到这一点,但到目前为止,我还没有找到任何适合这种情况的方法.

However, this is very slow (frame rate drops from 50 fps to 8 fps) on these complex models. I've been looking for better ways to do this, but so far I haven't found any that work well in this case.

是否有更好、更有效的方法来确定某个点是否被场景中的模型可见或遮挡?

Are there any better, more effective ways of finding out if a point is visible or obscured by models in the scene?

推荐答案

我不知道有什么真正快捷的方法,但您确实有一些选择.我对 Three.js 的了解还不够多,无法告诉您如何使用该库进行操作,但一般来说说的是 WebGL...

I am not aware of any really quick way, but you do have a few options. I don't know enough about three.js to tell you how to do it with that library, but speaking about WebGL in general...

如果可以使用 WebGL 2.0,则可以使用遮挡查询.这归结为

If you can use WebGL 2.0, you can use occlusion queries. This boils down to

var query = gl.createQuery();
gl.beginQuery(gl.ANY_SAMPLES_PASSED, query);
// ... draw a small quad at the specified 3d position ...
gl.endQuery(gl.ANY_SAMPLES_PASSED);
// some time later, typically a few frames later (after a fraction of a second)
if (gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE))
{
     gl.getQueryParameter(query, gl.QUERY_RESULT);
}

但请注意,查询结果仅在几帧后可用.

Note though, that the result of the query is only available a few frames later.

如果 WebGl 2.0 不是一个选项,那么您可能应该将场景绘制到帧缓冲区,在那里附加您自己的纹理来代替普通的 z 缓冲区.有一个使用适当深度纹理的扩展(更多细节在这里),但如果这是不可能的,您总是可以退回到使用输出每个像素深度的片段着色器来绘制场景.

If WebGl 2.0 is not an option, then you should probably draw the scene to a framebuffer, where you attach your own texture to use in place of the normal z-buffer. There is an extension to use proper depth textures (more details here), but where that is not possible you could always fall back to drawing your scene with a fragment shader that outputs the depth of each pixel.

然后您可以在深度纹理上使用 gl.ReadPixels().同样,请注意 GPU->CPU 传输的延迟,这总是很重要.

You can then use gl.ReadPixels() on the depth texture. Again, be aware of the latency for the GPU->CPU transfer, that's always going to be significant.

话虽如此,根据 DOM 对象的外观,将 DOM 对象渲染为纹理并使用四边形作为 3d 场景的一部分绘制该纹理可能会更容易、更快.

Having said all that, depending on what your DOM objects look like, it could be far easier and quicker to render your DOM objects into a texture and draw that texture using a quad as part of your 3d scene.

这篇关于如何在复杂场景中快速查找某个点是否被遮挡?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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