前言
坐标拾取有几种方式,这里只讲scene.pickPosition。大体思路是:先获取点击的屏幕坐标,然后读取fbo中的深度缓存信息,有了屏幕坐标和深度信息,即可根据矩阵变换,重新计算得到顶点的世界坐标。
流程图大体图下:
1.深度信息的存储
获取屏幕坐标这个就不讲了,直接讲如何获取深度信息,在此之前,需要先知道深度信息保存在哪里。
在初始化view的时候,会创建GlobeDepth,GlobeDepth会创建两个fbo:_pickColorFramebuffer和_outputFramebuffer,这两个fbo都有深度缓存纹理
function GlobeDepth() {
...
this._pickColorFramebuffer = new FramebufferManager({
depthStencil: true,
supportsDepthTexture: true,
});
this._outputFramebuffer = new FramebufferManager({
depthStencil: true,
supportsDepthTexture: true,
});
}
为什么要创建GlobeDepth呢,因为cesium并不是直接把场景渲染到屏幕,而是先渲染到fbo,再从fbo到屏幕。如果我们看Scene里面的流程,会发现通常情况下使用的fbo正是GlobeDepth创建的fbo。
if (environmentState.isSunVisible && scene.sunBloom && !useWebVR) {
passState.framebuffer = scene._sunPostProcess.update(passState);
scene._sunPostProcess.clear(context, passState, clearColor);
} else if (useGlobeDepthFramebuffer) {
passState.framebuffer = view.globeDepth.framebuffer;//通常是使用这个
} else if (usePostProcess) {
passState.framebuffer = view.sceneFramebuffer.framebuffer;
}
知道深度信息保存在哪里后,我们后面就能通过context.readPixels读取深度信息了。
2.获取坐标
获取坐标的核心方法是pickPositionWorldCoordinates,下面具体说明每一句的作用(仅展示核心代码),大体分两步,先通过pickDepth.getDepth获取深度值,再通过 SceneTransforms.drawingBufferToWgs84Coordinates计算世界坐标
Picking.prototype.pickPositionWorldCoordinates = function(
scene,
windowPosition,
result
) {
...
scene.view = defaultView;
const drawingBufferPosition