javascript - 如何在复杂场景中快速发现某个点是否被遮挡?

标签 javascript three.js webgl raytracing

我有一个复杂的 3D 场景,我需要根据 3D 坐标在其上显示 HTML 元素。 (我只是在顶部覆盖一个 div 标签并用 CSS 定位它。)但是,当 3D 坐标被模型遮挡时,我还需要部分隐藏它(例如,使其透明) (或换句话说,当它在相机中不可见时)。这些模型可能有数十万张面孔,我需要一种方法来查明它是否被遮挡,速度足以每秒运行多次。

目前我使用的是Three.js内置的raytracer,代码如下:

// 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)。我一直在寻找更好的方法来做到这一点,但到目前为止,我还没有发现任何适合这种情况的方法。

是否有任何更好、更有效的方法来查明某个点是可见的还是被场景中的模型遮挡了?

最佳答案

我不知道有什么真正快速的方法,但您确实有一些选择。我对 three.js 的了解还不够多,无法告诉您如何使用该库来完成它,但一般来说是谈论 WebGL...

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

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);
}

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

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

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

综上所述,根据您的 DOM 对象的外观,将 DOM 对象渲染成纹理并使用四边形绘制该纹理作为 3d 场景的一部分可能会更加容易和快捷。

关于javascript - 如何在复杂场景中快速发现某个点是否被遮挡?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36745711/

相关文章:

json - 在 node.js 的帮助下在服务器上运行 three.js,将模型导出到 json 并通过 ajax 加载到最终用户

webgl - 在 WebGL 中绘制许多形状

javascript - 当来自 javascript 的引用时,将图像放置在 assetic 中的位置

javascript - AWS Cognito 用户池、自定义消息 lambda

javascript - Three.js - 如何反复从左向右移动球

webgl - three.js 中相机的平滑移动

javascript - WebGL 基准 - 我应该创建什么样的测试?

javascript - 如何将运行时创建的 Canvas 上下文资源视为 require.js 插件中的依赖项?

javascript - 影响布局的CSS子菜单

javascript - 在一行中绘制多个图像