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'; ...@@ -11,14 +11,17 @@ import Scene from '../../mol-gl/scene';
import { PickingId } from '../../mol-geo/geometry/picking'; import { PickingId } from '../../mol-geo/geometry/picking';
import { decodeFloatRGB } from '../../mol-util/float-packing'; import { decodeFloatRGB } from '../../mol-util/float-packing';
const readBuffer = new Uint8Array(4)
export class PickPass { export class PickPass {
pickDirty = true pickDirty = true
objectPickTarget: RenderTarget objectPickTarget: RenderTarget
instancePickTarget: RenderTarget instancePickTarget: RenderTarget
groupPickTarget: RenderTarget groupPickTarget: RenderTarget
private objectBuffer: Uint8Array
private instanceBuffer: Uint8Array
private groupBuffer: Uint8Array
private pickScale: number private pickScale: number
private pickWidth: number private pickWidth: number
private pickHeight: number private pickHeight: number
...@@ -31,18 +34,33 @@ export class PickPass { ...@@ -31,18 +34,33 @@ export class PickPass {
this.pickScale = pickBaseScale / webgl.pixelRatio this.pickScale = pickBaseScale / webgl.pixelRatio
this.pickWidth = Math.round(width * this.pickScale) this.pickWidth = Math.round(width * this.pickScale)
this.pickHeight = Math.round(height * this.pickScale) this.pickHeight = Math.round(height * this.pickScale)
this.objectPickTarget = createRenderTarget(webgl, this.pickWidth, this.pickHeight) this.objectPickTarget = createRenderTarget(webgl, this.pickWidth, this.pickHeight)
this.instancePickTarget = createRenderTarget(webgl, this.pickWidth, this.pickHeight) this.instancePickTarget = createRenderTarget(webgl, this.pickWidth, this.pickHeight)
this.groupPickTarget = 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) { setSize(width: number, height: number) {
this.pickScale = this.pickBaseScale / this.webgl.pixelRatio this.pickScale = this.pickBaseScale / this.webgl.pixelRatio
this.pickWidth = Math.round(width * this.pickScale) this.pickWidth = Math.round(width * this.pickScale)
this.pickHeight = Math.round(height * this.pickScale) this.pickHeight = Math.round(height * this.pickScale)
this.objectPickTarget.setSize(this.pickWidth, this.pickHeight) this.objectPickTarget.setSize(this.pickWidth, this.pickHeight)
this.instancePickTarget.setSize(this.pickWidth, this.pickHeight) this.instancePickTarget.setSize(this.pickWidth, this.pickHeight)
this.groupPickTarget.setSize(this.pickWidth, this.pickHeight) this.groupPickTarget.setSize(this.pickWidth, this.pickHeight)
this.setupBuffers()
} }
render() { render() {
...@@ -54,12 +72,35 @@ export class PickPass { ...@@ -54,12 +72,35 @@ export class PickPass {
renderer.render(scene, 'pickInstance', true); renderer.render(scene, 'pickInstance', true);
this.groupPickTarget.bind(); this.groupPickTarget.bind();
renderer.render(scene, 'pickGroup', true); 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 { identify(x: number, y: number): PickingId | undefined {
const { webgl, pickScale } = this const { webgl, pickScale } = this
const { gl } = webgl const { gl } = webgl
if (this.pickDirty) this.render() if (this.pickDirty) {
this.render()
this.syncBuffers()
}
x *= webgl.pixelRatio x *= webgl.pixelRatio
y *= webgl.pixelRatio y *= webgl.pixelRatio
...@@ -68,19 +109,13 @@ export class PickPass { ...@@ -68,19 +109,13 @@ export class PickPass {
const xp = Math.round(x * pickScale) const xp = Math.round(x * pickScale)
const yp = Math.round(y * pickScale) const yp = Math.round(y * pickScale)
this.objectPickTarget.bind() const objectId = this.getId(xp, yp, this.objectBuffer)
webgl.readPixels(xp, yp, 1, 1, readBuffer)
const objectId = decodeFloatRGB(readBuffer[0], readBuffer[1], readBuffer[2])
if (objectId === -1) return if (objectId === -1) return
this.instancePickTarget.bind() const instanceId = this.getId(xp, yp, this.instanceBuffer)
webgl.readPixels(xp, yp, 1, 1, readBuffer)
const instanceId = decodeFloatRGB(readBuffer[0], readBuffer[1], readBuffer[2])
if (instanceId === -1) return if (instanceId === -1) return
this.groupPickTarget.bind() const groupId = this.getId(xp, yp, this.groupBuffer)
webgl.readPixels(xp, yp, 1, 1, readBuffer)
const groupId = decodeFloatRGB(readBuffer[0], readBuffer[1], readBuffer[2])
if (groupId === -1) return if (groupId === -1) return
return { objectId, instanceId, groupId } 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