我有一个复杂的 3D 场景,需要根据 3D 坐标在其上显示 HTML 元素。 (我只是简单地覆盖了一个div
标签放在顶部并使用 CSS 定位。)但是,当 3D 坐标被模型遮挡时(或者以另一种方式表述,当它在相机中不可见时)时,我还需要部分隐藏它(例如,使其透明) 。这些模型可能有数十万张面孔,我需要一种方法来查明它是否被遮挡,并且速度足够快,可以每秒运行多次。
目前,我使用的是Three.js的内置光线追踪器,代码如下:
// 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
然而,这是very在这些复杂模型上速度很慢(帧速率从 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 缓冲区。有一个扩展可以使用适当的深度纹理(更多详细信息请点击这里 http://blog.tojicode.com/2012/07/using-webgldepthtexture.html),但如果这是不可能的,您总是可以使用输出每个像素深度的片段着色器来绘制场景。
然后,您可以在深度纹理上使用 gl.ReadPixels() 。再次强调,请注意 GPU->CPU 传输的延迟,这总是很重要。
话虽如此,根据您的 DOM 对象的外观,将 DOM 对象渲染为纹理并使用四边形作为 3d 场景的一部分绘制该纹理可能会更容易、更快捷。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)