Skip to content
Snippets Groups Projects
Commit 9bea1343 authored by Alexander Rose's avatar Alexander Rose
Browse files

improved picking pass

parent 2fc28f60
No related branches found
No related tags found
No related merge requests found
......@@ -11,14 +11,17 @@ import Scene from '../../mol-gl/scene';
import { PickingId } from '../../mol-geo/geometry/picking';
import { decodeFloatRGB } from '../../mol-util/float-packing';
const readBuffer = new Uint8Array(4)
export class PickPass {
pickDirty = true
objectPickTarget: RenderTarget
instancePickTarget: RenderTarget
groupPickTarget: RenderTarget
private objectBuffer: Uint8Array
private instanceBuffer: Uint8Array
private groupBuffer: Uint8Array
private pickScale: number
private pickWidth: number
private pickHeight: number
......@@ -31,18 +34,33 @@ export class PickPass {
this.pickScale = pickBaseScale / webgl.pixelRatio
this.pickWidth = Math.round(width * this.pickScale)
this.pickHeight = Math.round(height * this.pickScale)
this.objectPickTarget = createRenderTarget(webgl, this.pickWidth, this.pickHeight)
this.instancePickTarget = createRenderTarget(webgl, this.pickWidth, this.pickHeight)
this.groupPickTarget = createRenderTarget(webgl, this.pickWidth, this.pickHeight)
this.setupBuffers()
}
private setupBuffers() {
const bufferSize = this.pickWidth * this.pickHeight * 4
if (!this.objectBuffer || this.objectBuffer.length !== bufferSize) {
this.objectBuffer = new Uint8Array(bufferSize)
this.instanceBuffer = new Uint8Array(bufferSize)
this.groupBuffer = new Uint8Array(bufferSize)
}
}
setSize(width: number, height: number) {
this.pickScale = this.pickBaseScale / this.webgl.pixelRatio
this.pickWidth = Math.round(width * this.pickScale)
this.pickHeight = Math.round(height * this.pickScale)
this.objectPickTarget.setSize(this.pickWidth, this.pickHeight)
this.instancePickTarget.setSize(this.pickWidth, this.pickHeight)
this.groupPickTarget.setSize(this.pickWidth, this.pickHeight)
this.setupBuffers()
}
render() {
......@@ -54,12 +72,35 @@ export class PickPass {
renderer.render(scene, 'pickInstance', true);
this.groupPickTarget.bind();
renderer.render(scene, 'pickGroup', true);
this.pickDirty = false
}
private syncBuffers() {
const { webgl } = this
this.objectPickTarget.bind()
webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.objectBuffer)
this.instancePickTarget.bind()
webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.instanceBuffer)
this.groupPickTarget.bind()
webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.groupBuffer)
}
private getId(x: number, y: number, buffer: Uint8Array) {
const idx = (y * this.pickWidth + x) * 4
return decodeFloatRGB(buffer[idx], buffer[idx + 1], buffer[idx + 2])
}
identify(x: number, y: number): PickingId | undefined {
const { webgl, pickScale } = this
const { gl } = webgl
if (this.pickDirty) this.render()
if (this.pickDirty) {
this.render()
this.syncBuffers()
}
x *= webgl.pixelRatio
y *= webgl.pixelRatio
......@@ -68,19 +109,13 @@ export class PickPass {
const xp = Math.round(x * pickScale)
const yp = Math.round(y * pickScale)
this.objectPickTarget.bind()
webgl.readPixels(xp, yp, 1, 1, readBuffer)
const objectId = decodeFloatRGB(readBuffer[0], readBuffer[1], readBuffer[2])
const objectId = this.getId(xp, yp, this.objectBuffer)
if (objectId === -1) return
this.instancePickTarget.bind()
webgl.readPixels(xp, yp, 1, 1, readBuffer)
const instanceId = decodeFloatRGB(readBuffer[0], readBuffer[1], readBuffer[2])
const instanceId = this.getId(xp, yp, this.instanceBuffer)
if (instanceId === -1) return
this.groupPickTarget.bind()
webgl.readPixels(xp, yp, 1, 1, readBuffer)
const groupId = decodeFloatRGB(readBuffer[0], readBuffer[1], readBuffer[2])
const groupId = this.getId(xp, yp, this.groupBuffer)
if (groupId === -1) return
return { objectId, instanceId, groupId }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment