在询问之前,我已经尝试了很多方法来解决这个话题,现在我真的不知道如何在 gltf 加载的文件上使用 gpu 完成对象拾取,所以我希望能得到任何帮助:(
我已经加载了一个巨大的 GLTF 文件,其中有很多小对象,由于文件数量,如果我只是将它们添加到场景中,它不可能实现良好的 fps,所以我设法实现了 60fps 合并gltfs 孩子成块,但是当我尝试实现 webgl_interactive_cubes_gpu 示例时,但它似乎对我不起作用,我点击时总是得到相同的对象。
为了调试,我尝试渲染 PickingScene 并且一切似乎都到位,从图形上讲,但是当涉及到挑选时,它似乎并没有像我预期的那样工作,除非我做错了什么。
Raycast 拾取对我来说不是一个合适的选择,因为有很多对象并且在其中添加渲染会杀死 fps。(55k 个对象);
以下是加载gltf后的代码:
var child = gltf.scene.children[i];
var childGeomCopy = child.geometry.clone();
childGeomCopy.translate(geomPosition.x, geomPosition.y, geomPosition.z);
childGeomCopy.scale(child.scale.x * Scalar, child.scale.y * Scalar, child.scale.z * Scalar);
childGeomCopy.computeBoundingBox();
childGeomCopy.computeBoundingSphere();
childGeomCopy.applyMatrix(new THREE.Matrix4());
geometriesPicking.push(childGeomCopy);
var individualObj = new THREE.Mesh(childGeomCopy, IndividualObjMat);
individualObj.name = "individual_" + child.name;
pickingData[childCounter] = {
object: individualObj,
position: individualObj.position.clone(),
rotation: individualObj.rotation.clone(),
scale: individualObj.scale.clone()
};
childCounter++;
编辑:
gltf.scene.traverse(function (child) {
//console.log(child.type);
if (child.isMesh) {
let geometry = child.geometry.clone();
let position = new THREE.Vector3();
position.x = child.position.x;
position.y = child.position.y;
position.z = child.position.z;
let rotation = new THREE.Euler();
rotation.x = child.rotation.x;
rotation.y = child.rotation.y;
rotation.z = child.rotation.z;
let scale = new THREE.Vector3();
scale.x = child.scale.x;
scale.y = child.scale.y;
scale.z = child.scale.z;
quaternion.setFromEuler(rotation);
matrix.compose(position.multiplyScalar(Scalar), quaternion, scale.multiplyScalar(Scalar));
geometry.applyMatrix(matrix);
applyVertexColors(geometry, color.setHex(Math.random() * 0xffffff));
geometriesDrawn.push(geometry);
geometry = geometry.clone();
applyVertexColors(geometry, color.setHex(childCounter));
geometriesPicking.push(geometry);
pickingData[childCounter] = {
object: new THREE.Mesh(geometry.clone(), new THREE.MeshBasicMaterial({ color: 0xffff00, blending: THREE.AdditiveBlending, transparent: true, opacity: 0.8 })),
id: childCounter,
position: position,
rotation: rotation,
scale: scale
};
childCounter++;
//console.log("%c [childCounter] :", "", childCounter);
}
});
... var PickGeom = THREE.BufferGeometryUtils.mergeBufferGeometries(geometriesPicking); PickGeom.rotateX(THREE.Math.degToRad(90)); PickingScene.add(new THREE.Mesh(pickingGeom, PickingMaterial));
然后在我的 MouseUp 函数中调用 pick(mouse*) 并传入 mouse* 信息:
function pick(mouse) {
camera.setViewOffset(renderer.domElement.width, renderer.domElement.height, mouse.x * window.devicePixelRatio | 0, mouse.y * window.devicePixelRatio | 0, 1, 1);
renderer.setRenderTarget(pickingTexture);
renderer.render(pickingScene, camera);
camera.clearViewOffset();
var pixelBuffer = new Uint8Array(4);
renderer.readRenderTargetPixels(pickingTexture, 0, 0, 1, 1, pixelBuffer);
var id = (pixelBuffer[0] << 16) | (pixelBuffer[1] << 8) | (pixelBuffer[2]);
var data = pickingData[id];
if (data) {
console.log(data.object.name, ":", data.position); // Always return the same object
}}