我在Three.js场景中有一个点网格(object3D使用THREE.Points),模型位于网格顶部,如下所示 . 在代码中,模型被称为 default mesh
,并出于性能原因使用合并的几何:
我正在尝试找出我的透视相机在任何给定点可以看到的网格中的哪个点,即每次使用我的轨道控件更新相机位置时 .
我的第一个想法是使用光线投射在相机和网格中的每个点之间创建光线 . 然后我可以找到哪些光线与模型相交,并从所有点的列表中删除与这些光线相对应的点,从而为我留下相机可以看到的点列表 .
到目前为止,光线创建和交叉代码放置在渲染循环中(因为每当移动摄像机时都必须更新),因此它显然很慢(显然) .
gridPointsVisible = gridPoints.geometry.vertices.slice(0);
startPoint = camera.position.clone();
//create the rays from each point in the grid to the camera position
for ( var point in gridPoints.geometry.vertices) {
direction = gridPoints.geometry.vertices[point].clone();
vector.subVectors(direction, startPoint);
ray = new THREE.Raycaster(startPoint, vector.clone().normalize());
if(ray.intersectObject( defaultMesh ).length > 0){
gridPointsVisible.pop(gridPoints.geometry.vertices[point]);
}
}
在所示的示例模型中,创建了大约2300条光线,并且网格具有1500个面,因此渲染需要永久 .
所以我有2个问题:
-
有更好的方法可以找到相机可以看到的物体吗?
-
如果没有,我可以加快我的光线投射/交叉检查吗?
提前致谢!
1 回答
看看this example of GPU picking .
你可以做类似的事情,特别容易,因为你有一套有限且有序的球体 . 这个想法是你使用着色器计算(可能基于位置)每个球体的平面颜色,并渲染到离屏渲染目标 . 然后,您将解析渲染目标数据的颜色,并能够映射回您的球体 . 任何可见的颜色也是可见的球体 . 任何剩余的球体都是隐藏的 . 此方法应该比光线投射更快地生成结果 .
WebGLRenderTarget允许您绘制到缓冲区而不绘制到画布 . 然后,您可以逐个像素地访问渲染目标的图像缓冲区(RGBA中真的是逐个颜色) .
对于映射,您将解析该缓冲区并创建您看到的所有唯一颜色的列表(所有非球形对象应该是其他一些平面颜色) . 然后你可以遍历你的点 - 你应该知道每个球体的颜色应该与着色器使用的颜色计算相同 . 如果点的颜色位于找到的颜色列表中,则该点可见 .
要优化此想法,可以降低渲染目标的分辨率 . 您可能会丢失仅可通过条子看到的分数,但您可以调整分辨率以满足您的需求 . 此外,如果您的点数少于256,则只能使用红色值,这会将每4个选中的值减少为1(仅检查RGBA像素的R) . 如果超过256,请包括检查绿色值,等等 .