我的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个面,因此渲染需要永久。
所以我有两个问题:
提前致谢!
答案 0 :(得分:1)
看看this example of GPU picking。
你可以做类似的事情,特别容易,因为你有一套有限且有序的球体。这个想法是你使用着色器计算(可能基于位置)每个球体的平面颜色,并渲染到离屏渲染目标。然后,您将解析渲染目标数据的颜色,并能够映射回您的球体。任何可见的颜色也是可见的球体。任何剩余的球体都是隐藏的。这种方法应该比光线投射更快地产生结果。
WebGLRenderTarget
可让您在不绘制画布的情况下绘制到缓冲区。然后,您可以逐个像素地访问渲染目标的图像缓冲区(RGBA中真的是逐个颜色)。
对于映射,您将解析该缓冲区并创建您看到的所有唯一颜色的列表(所有非球形对象应该是其他一些平面颜色)。然后你可以遍历你的点 - 你应该知道每个球体的颜色应该与着色器使用的颜色计算相同。如果点的颜色在找到的颜色列表中,则该点可见。
要优化此想法,您可以降低渲染目标的分辨率。您可能会丢失仅可通过条子看到的分数,但您可以调整分辨率以满足您的需求。此外,如果您的点数少于256,则只能使用红色值,这会将每4个选中的值减少为1(仅检查RGBA像素的R)。如果你超过256,包括检查绿色值,等等。