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

improved picking pass

parent 2fc28f60
Branches
Tags
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