物件選擇 GPU
根據你的設定(例如,如果你沒有像設定這樣的八叉樹)和場景中的物件數量,使用 Raycasting 進行物件拾取對你的 CPU 來說可能是一項繁重的任務。
如果你不需要滑鼠游標下的世界座標,但僅用於識別其下的物件,則可以使用 GPU 拾取。
簡短的解釋,GPU 可以是一個強大的計算工具,但你需要知道如何獲得結果。我們的想法是,如果使用表示其 id 的顏色渲染物件,則可以讀取游標下畫素的顏色並找出所拾取物件的 id。記住 RGB 只是十六進位制值,因此 id(整數)和顏色(hex)之間存在轉換。
- 為物件建立新場景和新渲染目標
var pickingScene = new THREE.Scene();
var pickingTexture = new THREE.WebGLRenderTarget(renderer.domElement.clientWidth, renderer.domElement.clientHeight);
pickingTexture.texture.minFilter = THREE.LinearFilter;
- 為物件拾取建立新的著色器材質;
var vs3D = `
attribute vec3 idcolor;
varying vec3 vidcolor;
void main(){
vidcolor = idcolor;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0);
}`;
var fs3D = `
varying vec3 vidcolor;
void main(void) {
gl_FragColor = vec4(vidcolor,1.0);
}`;
var pickingMaterial = new THREE.ShaderMaterial(
{
vertexShader: vs3D,
fragmentShader: fs3D,
transparent: false,
side: THREE.DoubleSide
});
- 新增網格/線幾何圖形,在 RGB 中表示其 id 的新屬性,使用相同的幾何圖形建立 pickingObject 並將其新增到拾取場景,並將實際網格新增到 id-> object 字典
var selectionObjects = [];
for(var i=0; i<myMeshes.length; i++){
var mesh = myMeshes[i];
var positions = mesh.geometry.attributes["position"].array;
var idColor = new Float32Array(positions.length);
var color = new THREE.Color();
color.setHex(mesh.id);
for (var j=0; j< positions.length; j+=3){
idColor[j] = color.r;
idColor[j+1] = color.g;
idColor[j+2] = color.b;
}
mesh.geometry.addAttribute('idcolor', new THREE.BufferAttribute(idColor, 3));
var pickingObject = new THREE.Mesh(mesh.geometry, pickingMaterial);
pickingScene.add(pickingObject);
selectionObjects[mesh.id] = mesh;
}
- 最後,在滑鼠單擊處理程式上
renderer.render(pickingScene, camera, pickingTexture);
var pixelBuffer = new Uint8Array(4);
renderer.readRenderTargetPixels(pickingTexture, event.pageX, pickingTexture.height - event.pageY, 1, 1, pixelBuffer);
var id = (pixelBuffer[0] << 16) | (pixelBuffer[1] << 8) | (pixelBuffer[2]);
if (id>0){
//this is the id of the picked object
}else{
//it's 0. clicked on an empty space
}