diff --git a/src/mol-app/ui/visualization/viewport.tsx b/src/mol-app/ui/visualization/viewport.tsx index aeb157e3b81385e26d857bf870aa59da77c956fe..345fad88a6e7a90b4735bd7773ff0ef6cd7f3e94 100644 --- a/src/mol-app/ui/visualization/viewport.tsx +++ b/src/mol-app/ui/visualization/viewport.tsx @@ -128,7 +128,6 @@ export class Viewport extends View<ViewportController, ViewportState, { noWebGl? viewer.didDraw.subscribe(() => { // this.setState({ imageData: viewer.getImageData() }) - viewer.pick() this.setState({ images: { 'object': viewer.getImageData('pickObject'), diff --git a/src/mol-geo/representation/structure/index.ts b/src/mol-geo/representation/structure/index.ts index 508e4a45436aecb59dd0dfddb072bad9940a37b3..b9716cef44a687d8ab542453959c3f6c2682a2e2 100644 --- a/src/mol-geo/representation/structure/index.ts +++ b/src/mol-geo/representation/structure/index.ts @@ -67,7 +67,8 @@ export const DefaultStructureProps = { alpha: 1, visible: true, doubleSided: false, - depthMask: true + depthMask: true, + hoverSelection: { objectId: -1, instanceId: -1, elementId: -1 } as PickingId } export type StructureProps = Partial<typeof DefaultStructureProps> diff --git a/src/mol-geo/representation/structure/point.ts b/src/mol-geo/representation/structure/point.ts index a6498587ceb75378f16d7bcdcbab5d36dfe72515..cf090acac8cafb697f1d0c96d60fe4794a843f5e 100644 --- a/src/mol-geo/representation/structure/point.ts +++ b/src/mol-geo/representation/structure/point.ts @@ -11,21 +11,18 @@ import { Unit, Element } from 'mol-model/structure'; import { Task } from 'mol-task' import { fillSerial } from 'mol-gl/renderable/util'; -import { UnitsRepresentation } from './index'; +import { UnitsRepresentation, DefaultStructureProps } from './index'; import VertexMap from '../../shape/vertex-map'; -import { ColorTheme, SizeTheme } from '../../theme'; -import { createTransforms, createColors, createSizes } from './utils'; +import { SizeTheme } from '../../theme'; +import { createTransforms, createColors, createSizes, createFlags } from './utils'; import { deepEqual, defaults } from 'mol-util'; import { SortedArray } from 'mol-data/int'; import { RenderableState, PointValues } from 'mol-gl/renderable'; import { PickingId } from '../../util/picking'; export const DefaultPointProps = { - colorTheme: { name: 'instance-index' } as ColorTheme, - sizeTheme: { name: 'vdw' } as SizeTheme, - alpha: 1, - visible: true, - depthMask: true + ...DefaultStructureProps, + sizeTheme: { name: 'vdw' } as SizeTheme } export type PointProps = Partial<typeof DefaultPointProps> @@ -69,7 +66,7 @@ export default function Point(): UnitsRepresentation<PointProps> { _units = group.units _elements = group.elements; - const { colorTheme, sizeTheme } = currentProps + const { colorTheme, sizeTheme, hoverSelection } = currentProps const elementCount = _elements.length const vertexMap = VertexMap.create( @@ -91,6 +88,9 @@ export default function Point(): UnitsRepresentation<PointProps> { await ctx.update('Computing point sizes'); const size = createSizes(group, vertexMap, sizeTheme) + await ctx.update('Computing spacefill flags'); + const flag = createFlags(group, hoverSelection.instanceId, hoverSelection.elementId) + const instanceCount = group.units.length const values: PointValues = { @@ -99,6 +99,7 @@ export default function Point(): UnitsRepresentation<PointProps> { aTransform: transforms, aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))), ...color, + ...flag, ...size, uAlpha: ValueCell.create(defaults(props.alpha, 1.0)), diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts index fe2e6141cdad467942a0201c89c5bbf64245028a..49e15e20733c3827431b1b54d40bf76c6802581f 100644 --- a/src/mol-geo/representation/structure/spacefill.ts +++ b/src/mol-geo/representation/structure/spacefill.ts @@ -14,7 +14,7 @@ import { Unit, Element, Queries } from 'mol-model/structure'; import { UnitsRepresentation, DefaultStructureProps } from './index'; import { Task } from 'mol-task' import { MeshBuilder } from '../../shape/mesh-builder'; -import { createTransforms, createColors } from './utils'; +import { createTransforms, createColors, createFlags } from './utils'; import VertexMap from '../../shape/vertex-map'; import { icosahedronVertexCount } from '../../primitive/icosahedron'; import { deepEqual, defaults } from 'mol-util'; @@ -92,7 +92,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { renderObjects.length = 0 // clear currentGroup = group - const { detail, colorTheme } = { ...DefaultSpacefillProps, ...props } + const { detail, colorTheme, hoverSelection } = { ...DefaultSpacefillProps, ...props } mesh = await createSpacefillMesh(group.units[0], detail).runAsChild(ctx, 'Computing spacefill mesh') // console.log(mesh) @@ -104,6 +104,9 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { await ctx.update('Computing spacefill colors'); const color = createColors(group, vertexMap, colorTheme) + await ctx.update('Computing spacefill flags'); + const flag = createFlags(group, hoverSelection.instanceId, hoverSelection.elementId) + const instanceCount = group.units.length const values: MeshValues = { @@ -111,6 +114,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { aTransform: transforms, aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))), ...color, + ...flag, uAlpha: ValueCell.create(defaults(props.alpha, 1.0)), uInstanceCount: ValueCell.create(instanceCount), @@ -159,6 +163,11 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { createColors(currentGroup, vertexMap, newProps.colorTheme, spheres.values) } + if (newProps.hoverSelection !== currentProps.hoverSelection) { + await ctx.update('Computing spacefill flags'); + createFlags(currentGroup, newProps.hoverSelection.instanceId, newProps.hoverSelection.elementId, spheres.values) + } + ValueCell.updateIfChanged(spheres.values.uAlpha, newProps.alpha) ValueCell.updateIfChanged(spheres.values.dDoubleSided, newProps.doubleSided) ValueCell.updateIfChanged(spheres.values.dFlipSided, newProps.flipSided) diff --git a/src/mol-geo/representation/structure/utils.ts b/src/mol-geo/representation/structure/utils.ts index a242839edcee47cdf8b2ec8b3eaaea48d444fd2c..594588a2f54772c4eb649f01762712d138a81dfe 100644 --- a/src/mol-geo/representation/structure/utils.ts +++ b/src/mol-geo/representation/structure/utils.ts @@ -6,7 +6,7 @@ */ import { Unit } from 'mol-model/structure'; -import { Mat4 } from 'mol-math/linear-algebra' +import { Mat4, Vec2 } from 'mol-math/linear-algebra' import { createUniformColor, ColorData } from '../../util/color-data'; import { createUniformSize } from '../../util/size-data'; @@ -15,6 +15,7 @@ import VertexMap from '../../shape/vertex-map'; import { ColorTheme, SizeTheme } from '../../theme'; import { elementIndexColorData, elementSymbolColorData, instanceIndexColorData, chainIdColorData } from '../../theme/structure/color'; import { ValueCell } from 'mol-util'; +import { TextureImage, createTextureImage } from 'mol-gl/renderable/util'; export function createTransforms({ units }: Unit.SymmetryGroup, transforms?: ValueCell<Float32Array>) { const unitCount = units.length @@ -48,4 +49,42 @@ export function createSizes(group: Unit.SymmetryGroup, vertexMap: VertexMap, pro case 'vdw': return elementSizeData({ group, vertexMap }) } +} + +export type FlagData = { + tFlag: ValueCell<TextureImage> + uFlagTexSize: ValueCell<Vec2> +} + +export function createFlags(group: Unit.SymmetryGroup, instanceId: number, elementId: number, flagData?: FlagData): FlagData { + const instanceCount = group.units.length + const elementCount = group.elements.length + const count = instanceCount * elementCount + const flags = flagData && flagData.tFlag.ref.value.array.length >= count ? flagData.tFlag.ref.value : createTextureImage(count, 1) + let flagOffset = 0 + for (let i = 0; i < instanceCount; i++) { + for (let j = 0, jl = elementCount; j < jl; ++j) { + flags.array[flagOffset] = (i === instanceId && j === elementId) ? 255 : 0 + flagOffset += 1 + } + } + // console.log(flags, instanceCount, elementCount) + if (flagData) { + ValueCell.update(flagData.tFlag, flags) + ValueCell.update(flagData.uFlagTexSize, Vec2.create(flags.width, flags.height)) + return flagData + } else { + return { + tFlag: ValueCell.create(flags), + uFlagTexSize: ValueCell.create(Vec2.create(flags.width, flags.height)), + } + } +} + +const emptyFlagTexture = { array: new Uint8Array(1), width: 1, height: 1 } +export function createEmptyFlags() { + return { + tFlag: ValueCell.create(emptyFlagTexture), + uFlagTexSize: ValueCell.create(Vec2.create(1, 1)), + } } \ No newline at end of file diff --git a/src/mol-geo/representation/volume/surface.ts b/src/mol-geo/representation/volume/surface.ts index 16071c84a0f802cd7d7a25bae157c5ce95b78631..fab4c945407a158c3383537f9c1c8af0acf283d6 100644 --- a/src/mol-geo/representation/volume/surface.ts +++ b/src/mol-geo/representation/volume/surface.ts @@ -18,6 +18,7 @@ import { createUniformColor } from '../../util/color-data'; import { getMeshData } from '../../util/mesh-data'; import { RenderableState, MeshValues } from 'mol-gl/renderable'; import { PickingId } from '../../util/picking'; +import { createEmptyFlags } from '../structure/utils'; export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValue) { return Task.create<Mesh>('Volume Surface', async ctx => { @@ -66,12 +67,14 @@ export default function Surface(): VolumeElementRepresentation<SurfaceProps> { const instanceCount = 1 const color = createUniformColor({ value: 0x7ec0ee }) + const flag = createEmptyFlags() const values: MeshValues = { ...getMeshData(mesh), aTransform: ValueCell.create(new Float32Array(Mat4.identity())), aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))), ...color, + ...flag, uAlpha: ValueCell.create(defaults(props.alpha, 1.0)), uInstanceCount: ValueCell.create(instanceCount), diff --git a/src/mol-geo/util/color-data.ts b/src/mol-geo/util/color-data.ts index 0da692da97f6c69e077ea7409b4890be547bfc74..aadc34027e952ff37196c00bcc1fd7dfe78279c1 100644 --- a/src/mol-geo/util/color-data.ts +++ b/src/mol-geo/util/color-data.ts @@ -5,7 +5,7 @@ */ import { ValueCell } from 'mol-util'; -import { TextureImage, createColorTexture, emptyTexture } from 'mol-gl/renderable/util'; +import { TextureImage, createTextureImage } from 'mol-gl/renderable/util'; import { Color } from 'mol-util/color'; import VertexMap from '../shape/vertex-map'; import { Vec2, Vec3 } from 'mol-math/linear-algebra'; @@ -20,6 +20,14 @@ export type ColorData = { dColorType: ValueCell<string>, } +const emptyColorTexture = { array: new Uint8Array(3), width: 1, height: 1 } +function createEmptyColorTexture() { + return { + tColor: ValueCell.create(emptyColorTexture), + uColorTexSize: ValueCell.create(Vec2.create(1, 1)) + } +} + export interface UniformColorProps { value: Color } @@ -36,8 +44,7 @@ export function createUniformColor(props: UniformColorProps, colorData?: ColorDa return { uColor: ValueCell.create(Color.toRgbNormalized(props.value) as Vec3), aColor: ValueCell.create(new Float32Array(0)), - tColor: ValueCell.create(emptyTexture), - uColorTexSize: ValueCell.create(Vec2.zero()), + ...createEmptyColorTexture(), dColorType: ValueCell.create('uniform'), } } @@ -71,8 +78,7 @@ export function createAttributeColor(props: AttributeColorProps, colorData?: Col return { uColor: ValueCell.create(Vec3.zero()), aColor: ValueCell.create(colors), - tColor: ValueCell.create(emptyTexture), - uColorTexSize: ValueCell.create(Vec2.zero()), + ...createEmptyColorTexture(), dColorType: ValueCell.create('attribute'), } } @@ -105,7 +111,7 @@ export interface InstanceColorProps { /** Creates color texture with color for each instance/unit */ export function createInstanceColor(props: InstanceColorProps, colorData?: ColorData): ColorData { const { colorFn, instanceCount} = props - const colors = colorData && colorData.tColor.ref.value.array.length >= instanceCount * 3 ? colorData.tColor.ref.value : createColorTexture(instanceCount) + const colors = colorData && colorData.tColor.ref.value.array.length >= instanceCount * 3 ? colorData.tColor.ref.value : createTextureImage(instanceCount, 3) for (let i = 0; i < instanceCount; i++) { Color.toArray(colorFn(i), colors.array, i * 3) } @@ -121,7 +127,7 @@ export interface ElementColorProps { export function createElementColor(props: ElementColorProps, colorData?: ColorData): ColorData { const { colorFn, vertexMap } = props const elementCount = vertexMap.offsetCount - 1 - const colors = colorData && colorData.tColor.ref.value.array.length >= elementCount * 3 ? colorData.tColor.ref.value : createColorTexture(elementCount) + const colors = colorData && colorData.tColor.ref.value.array.length >= elementCount * 3 ? colorData.tColor.ref.value : createTextureImage(elementCount, 3) for (let i = 0, il = elementCount; i < il; ++i) { Color.toArray(colorFn(i), colors.array, i * 3) } @@ -139,7 +145,7 @@ export function createElementInstanceColor(props: ElementInstanceColorProps, col const { colorFn, instanceCount, vertexMap } = props const elementCount = vertexMap.offsetCount - 1 const count = instanceCount * elementCount - const colors = colorData && colorData.tColor.ref.value.array.length >= count * 3 ? colorData.tColor.ref.value : createColorTexture(count) + const colors = colorData && colorData.tColor.ref.value.array.length >= count * 3 ? colorData.tColor.ref.value : createTextureImage(count, 3) let colorOffset = 0 for (let i = 0; i < instanceCount; i++) { for (let j = 0, jl = elementCount; j < jl; ++j) { diff --git a/src/mol-gl/_spec/renderer.spec.ts b/src/mol-gl/_spec/renderer.spec.ts index 86849b10c81ada35e6e4fa0031a8e7224dc20d13..2b57d415255f4c8220d6520c4a4810430a89c8fb 100644 --- a/src/mol-gl/_spec/renderer.spec.ts +++ b/src/mol-gl/_spec/renderer.spec.ts @@ -19,6 +19,7 @@ import { RenderableState } from '../renderable'; import { createPointRenderObject } from '../render-object'; import { PointValues } from '../renderable/point'; import Scene from '../scene'; +import { createEmptyFlags } from 'mol-geo/representation/structure/utils'; // function writeImage(gl: WebGLRenderingContext, width: number, height: number) { // const pixels = new Uint8Array(width * height * 4) @@ -48,6 +49,7 @@ function createPoints() { const aInstanceId = ValueCell.create(fillSerial(new Float32Array(1))) const color = createUniformColor({ value: 0xFF0000 }) const size = createUniformSize({ value: 1 }) + const flag = createEmptyFlags() const aTransform = ValueCell.create(new Float32Array(16)) const m4 = Mat4.identity() @@ -59,6 +61,7 @@ function createPoints() { aTransform, aInstanceId, ...color, + ...flag, ...size, uAlpha: ValueCell.create(1.0), @@ -108,7 +111,7 @@ describe('renderer', () => { scene.add(points) expect(ctx.bufferCount).toBe(6); - expect(ctx.textureCount).toBe(1); + expect(ctx.textureCount).toBe(2); expect(ctx.vaoCount).toBe(4); expect(ctx.programCache.count).toBe(4); expect(ctx.shaderCache.count).toBe(8); diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts index d4b60bbb563614b848b6c3b7af76f86f57bfbbe3..de475c520699e703f1b8c8a729030fd7426639a5 100644 --- a/src/mol-gl/renderable/schema.ts +++ b/src/mol-gl/renderable/schema.ts @@ -144,10 +144,12 @@ export const BaseSchema = { uAlpha: UniformSpec('f'), uInstanceCount: UniformSpec('i'), uElementCount: UniformSpec('i'), - uColorTexSize: UniformSpec('v2'), uColor: UniformSpec('v3'), + uColorTexSize: UniformSpec('v2'), + uFlagTexSize: UniformSpec('v2'), tColor: TextureSpec('rgb', 'ubyte'), + tFlag: TextureSpec('alpha', 'ubyte'), drawCount: ValueSpec('number'), instanceCount: ValueSpec('number'), diff --git a/src/mol-gl/renderable/util.ts b/src/mol-gl/renderable/util.ts index ea78f87d7cdbae63160291e0a093f07dce1d8b51..3c6048dd84a8a12f00fb05659bd7362dc061aa03 100644 --- a/src/mol-gl/renderable/util.ts +++ b/src/mol-gl/renderable/util.ts @@ -18,13 +18,11 @@ export interface TextureImage { height: number } -export function createColorTexture (n: number): TextureImage { - const { length, width, height } = calculateTextureInfo(n, 3) +export function createTextureImage (n: number, itemSize: number): TextureImage { + const { length, width, height } = calculateTextureInfo(n, itemSize) return { array: new Uint8Array(length), width, height } } -export const emptyTexture = { array: new Uint8Array(0), width: 0, height: 0 } - export function fillSerial<T extends Helpers.NumberArray> (array: T) { const n = array.length for (let i = 0; i < n; ++i) array[ i ] = i diff --git a/src/mol-gl/shader/chunks/color-assign-varying.glsl b/src/mol-gl/shader/chunks/color-assign-varying.glsl index 09c52bd20739d09e5fb430ef0a4efa302b015dd8..b5848197a89b908cb5664869d1206f90eb222042 100644 --- a/src/mol-gl/shader/chunks/color-assign-varying.glsl +++ b/src/mol-gl/shader/chunks/color-assign-varying.glsl @@ -1,11 +1,11 @@ #if defined(dColorType_attribute) - vColor.xyz = aColor; + vColor.rgb = aColor; #elif defined(dColorType_instance) - vColor.xyz = read_vec3(tColor, aInstanceId, uColorTexSize); + vColor.rgb = readFromTexture(tColor, aInstanceId, uColorTexSize).rgb; #elif defined(dColorType_element) - vColor.xyz = read_vec3(tColor, aElementId, uColorTexSize); + vColor.rgb = readFromTexture(tColor, aElementId, uColorTexSize).rgb; #elif defined(dColorType_elementInstance) - vColor.xyz = read_vec3(tColor, aInstanceId * float(uElementCount) + aElementId, uColorTexSize); + vColor.rgb = readFromTexture(tColor, aInstanceId * float(uElementCount) + aElementId, uColorTexSize).rgb; #elif defined(dColorType_objectPicking) vColor = encodeIdRGBA(float(uObjectId)); #elif defined(dColorType_instancePicking) diff --git a/src/mol-gl/shader/chunks/color-vert-params.glsl b/src/mol-gl/shader/chunks/color-vert-params.glsl index 19a12ea30eb1cce2de83130c8cd88e9bf8d74262..8f49becee4630b39320a3660dcae7adc8a6aafcd 100644 --- a/src/mol-gl/shader/chunks/color-vert-params.glsl +++ b/src/mol-gl/shader/chunks/color-vert-params.glsl @@ -10,6 +10,4 @@ #elif defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_elementPicking) varying vec4 vColor; #pragma glslify: encodeIdRGBA = require(../utils/encode-id-rgba.glsl) -#endif - -#pragma glslify: read_vec3 = require(../utils/read-from-texture.glsl) \ No newline at end of file +#endif \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/common-frag-params.glsl b/src/mol-gl/shader/chunks/common-frag-params.glsl index d217f2530aff5e0e103694382960ddb33ae35a6a..744b3a1a247019dc92cc745374f38c138ba387d2 100644 --- a/src/mol-gl/shader/chunks/common-frag-params.glsl +++ b/src/mol-gl/shader/chunks/common-frag-params.glsl @@ -1,3 +1,5 @@ uniform int uObjectId; uniform int uInstanceCount; -uniform int uElementCount; \ No newline at end of file +uniform int uElementCount; + +varying float vFlag; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/common-vert-params.glsl b/src/mol-gl/shader/chunks/common-vert-params.glsl index 1733a09bd98312a7f11904b793dbcd4e62e43ded..005d347d55fe9d79fa16f53c46681b4f44d50ef9 100644 --- a/src/mol-gl/shader/chunks/common-vert-params.glsl +++ b/src/mol-gl/shader/chunks/common-vert-params.glsl @@ -2,4 +2,9 @@ uniform mat4 uProjection, uModel, uView; uniform int uObjectId; uniform int uInstanceCount; -uniform int uElementCount; \ No newline at end of file +uniform int uElementCount; + +uniform vec2 uFlagTexSize; +uniform sampler2D tFlag; +varying float vFlag; +#pragma glslify: readFromTexture = require(../utils/read-from-texture.glsl) \ No newline at end of file diff --git a/src/mol-gl/shader/mesh.frag b/src/mol-gl/shader/mesh.frag index a5beff4ac5a7d8e135a5302fb7a0ea2fa261164d..401a0e46bc5aa9f1d6db723aeebe117e5846b38a 100644 --- a/src/mol-gl/shader/mesh.frag +++ b/src/mol-gl/shader/mesh.frag @@ -75,5 +75,9 @@ void main() { // gl_FragColor.rgb = vec3(1.0, 0.0, 0.0); gl_FragColor.rgb = finalColor; gl_FragColor.a = uAlpha; + + if (vFlag == 1.0) { + gl_FragColor.rgb = mix(vec3(1.0, 0.4, 0.6), gl_FragColor.rgb, 0.3); + } #endif } \ No newline at end of file diff --git a/src/mol-gl/shader/mesh.vert b/src/mol-gl/shader/mesh.vert index 48f9eaea8ebf5ab1d24be9ea5478e737beae9a40..9b9ec9ea3ed9efe91980b50ef2fe8d3db6feb13d 100644 --- a/src/mol-gl/shader/mesh.vert +++ b/src/mol-gl/shader/mesh.vert @@ -27,6 +27,7 @@ varying vec3 vViewPosition; void main(){ #pragma glslify: import('./chunks/color-assign-varying.glsl') + vFlag = readFromTexture(tFlag, aInstanceId * float(uElementCount) + aElementId, uFlagTexSize).a; mat4 modelView = uView * uModel * aTransform; vec4 mvPosition = modelView * vec4(aPosition, 1.0); diff --git a/src/mol-gl/shader/utils/read-from-texture.glsl b/src/mol-gl/shader/utils/read-from-texture.glsl index b342a3f78e7dee39e79481a94ee002481532adb6..10b4e9d60c09519c17cd0b5a3fe60e27a8bb7fe6 100644 --- a/src/mol-gl/shader/utils/read-from-texture.glsl +++ b/src/mol-gl/shader/utils/read-from-texture.glsl @@ -4,10 +4,10 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -vec3 read_vec3 (const in sampler2D tex, const in float i, const in vec2 size) { +vec4 readFromTexture (const in sampler2D tex, const in float i, const in vec2 size) { float x = mod(i, size.x); float y = floor(i / size.x); vec2 uv = (vec2(x, y) + 0.5) / size; - return texture2D(tex, uv).rgb; + return texture2D(tex, uv); } -#pragma glslify: export(read_vec3) \ No newline at end of file +#pragma glslify: export(readFromTexture) \ No newline at end of file diff --git a/src/mol-gl/webgl/context.ts b/src/mol-gl/webgl/context.ts index 5128e79b5f8c356fd7a9ff67f57114bcfdc3aab8..62d234c85b503c958e412ec6f92926b41dacaf52 100644 --- a/src/mol-gl/webgl/context.ts +++ b/src/mol-gl/webgl/context.ts @@ -112,11 +112,13 @@ export function createContext(gl: WebGLRenderingContext): Context { unbindFramebuffer: () => unbindFramebuffer(gl), readPixels: (x: number, y: number, width: number, height: number, buffer: Uint8Array) => { - if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) { - gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer) - } else { - console.error('Reading pixels failed. Framebuffer not complete.') - } + gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer) + // TODO check is very expensive + // if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) { + // gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer) + // } else { + // console.error('Reading pixels failed. Framebuffer not complete.') + // } }, destroy: () => { diff --git a/src/mol-gl/webgl/texture.ts b/src/mol-gl/webgl/texture.ts index dc4fe9e53ad477e97bed77b9f9dd43481e2d3428..a156f2ebd969270b170b23116423fcee39987c89 100644 --- a/src/mol-gl/webgl/texture.ts +++ b/src/mol-gl/webgl/texture.ts @@ -13,13 +13,14 @@ import { Framebuffer } from './framebuffer'; const getNextTextureId = idFactory() -export type TextureFormat = 'rgb' | 'rgba' +export type TextureFormat = 'alpha' | 'rgb' | 'rgba' export type TextureType = 'ubyte' | 'uint' export type TextureAttachment = 'depth' | 'stencil' | 'color0' export function getFormat(ctx: Context, format: TextureFormat) { const { gl } = ctx switch (format) { + case 'alpha': return gl.ALPHA case 'rgb': return gl.RGB case 'rgba': return gl.RGBA } diff --git a/src/mol-view/viewer.ts b/src/mol-view/viewer.ts index 0f090610cf8ebeb354a313f121aa99f7e091b576..8789dafe54904aa94522302a891e0cc9b4c79704 100644 --- a/src/mol-view/viewer.ts +++ b/src/mol-view/viewer.ts @@ -81,7 +81,14 @@ namespace Viewer { let label = '' reprMap.forEach((roSet, repr) => { const info = repr.getLabel(p) - if (info) label = info.label + if (info) { + label = info.label + // TODO do better, take objectId fully into account + repr.update({ hoverSelection: p }).run().then(() => { + scene.update() + requestDraw() + }) + } }) identified.next(`Object: ${p.objectId}, Instance: ${p.instanceId}, Element: ${p.elementId}, Label: ${label}`) }) @@ -117,6 +124,7 @@ namespace Viewer { const instancePickTarget = createRenderTarget(ctx, pickWidth, pickHeight) const elementPickTarget = createRenderTarget(ctx, pickWidth, pickHeight) + let pickDirty = true let drawPending = false const prevProjectionView = Mat4.zero() @@ -127,6 +135,10 @@ namespace Viewer { if (force || !Mat4.areEqual(camera.projectionView, prevProjectionView, EPSILON.Value)) { Mat4.copy(prevProjectionView, camera.projectionView) renderer.render(scene, variant) + if (variant === 'draw') { + pickDirty = true + pick() + } didRender = true } return didRender @@ -153,6 +165,19 @@ namespace Viewer { window.requestAnimationFrame(() => animate()) } + function pick() { + objectPickTarget.bind() + render('pickObject', pickDirty) + + instancePickTarget.bind() + render('pickInstance', pickDirty) + + elementPickTarget.bind() + render('pickElement', pickDirty) + + pickDirty = false + } + function identify (x: number, y: number): PickingId { const buffer = new Uint8Array(4) y = canvas.height - y // flip y @@ -222,16 +247,7 @@ namespace Viewer { draw, requestDraw, animate, - pick: () => { - objectPickTarget.bind() - render('pickObject', true) - - instancePickTarget.bind() - render('pickInstance', true) - - elementPickTarget.bind() - render('pickElement', true) - }, + pick, identify, handleResize,