UNPKG

molstar

Version:

A comprehensive macromolecular library.

168 lines (167 loc) 8.88 kB
"use strict"; /** * Copyright (c) 2021-2023 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.MarkingPass = exports.MarkingParams = void 0; const util_1 = require("../../mol-gl/compute/util"); const renderable_1 = require("../../mol-gl/renderable"); const schema_1 = require("../../mol-gl/renderable/schema"); const shader_code_1 = require("../../mol-gl/shader-code"); const render_item_1 = require("../../mol-gl/webgl/render-item"); const linear_algebra_1 = require("../../mol-math/linear-algebra"); const mol_util_1 = require("../../mol-util"); const param_definition_1 = require("../../mol-util/param-definition"); const quad_vert_1 = require("../../mol-gl/shader/quad.vert"); const overlay_frag_1 = require("../../mol-gl/shader/marking/overlay.frag"); const color_1 = require("../../mol-util/color"); const edge_frag_1 = require("../../mol-gl/shader/marking/edge.frag"); const debug_1 = require("../../mol-util/debug"); exports.MarkingParams = { enabled: param_definition_1.ParamDefinition.Boolean(true), highlightEdgeColor: param_definition_1.ParamDefinition.Color(color_1.Color.darken(color_1.Color.fromNormalizedRgb(1.0, 0.4, 0.6), 1.0)), selectEdgeColor: param_definition_1.ParamDefinition.Color(color_1.Color.darken(color_1.Color.fromNormalizedRgb(0.2, 1.0, 0.1), 1.0)), edgeScale: param_definition_1.ParamDefinition.Numeric(1, { min: 1, max: 3, step: 1 }, { description: 'Thickness of the edge.' }), highlightEdgeStrength: param_definition_1.ParamDefinition.Numeric(1.0, { min: 0, max: 1, step: 0.1 }), selectEdgeStrength: param_definition_1.ParamDefinition.Numeric(1.0, { min: 0, max: 1, step: 0.1 }), ghostEdgeStrength: param_definition_1.ParamDefinition.Numeric(0.3, { min: 0, max: 1, step: 0.1 }, { description: 'Opacity of the hidden edges that are covered by other geometry. When set to 1, one less geometry render pass is done.' }), innerEdgeFactor: param_definition_1.ParamDefinition.Numeric(1.5, { min: 0, max: 3, step: 0.1 }, { description: 'Factor to multiply the inner edge color with - for added contrast.' }), }; class MarkingPass { static isEnabled(props) { return props.enabled; } constructor(webgl, width, height) { this.webgl = webgl; this.depthTarget = webgl.createRenderTarget(width, height); this.maskTarget = webgl.createRenderTarget(width, height); this.edgesTarget = webgl.createRenderTarget(width, height); this.edge = getEdgeRenderable(webgl, this.maskTarget.texture); this.overlay = getOverlayRenderable(webgl, this.edgesTarget.texture); } setEdgeState(viewport) { const { gl, state } = this.webgl; state.enable(gl.SCISSOR_TEST); state.enable(gl.BLEND); state.blendFunc(gl.ONE, gl.ONE); state.blendEquation(gl.FUNC_ADD); state.disable(gl.DEPTH_TEST); state.depthMask(false); const { x, y, width, height } = viewport; state.viewport(x, y, width, height); state.scissor(x, y, width, height); state.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); } setOverlayState(viewport) { const { gl, state } = this.webgl; state.enable(gl.SCISSOR_TEST); state.enable(gl.BLEND); state.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); state.blendEquation(gl.FUNC_ADD); state.disable(gl.DEPTH_TEST); state.depthMask(false); const { x, y, width, height } = viewport; state.viewport(x, y, width, height); state.scissor(x, y, width, height); } setSize(width, height) { const w = this.depthTarget.getWidth(); const h = this.depthTarget.getHeight(); if (width !== w || height !== h) { this.depthTarget.setSize(width, height); this.maskTarget.setSize(width, height); this.edgesTarget.setSize(width, height); mol_util_1.ValueCell.update(this.edge.values.uTexSizeInv, linear_algebra_1.Vec2.set(this.edge.values.uTexSizeInv.ref.value, 1 / width, 1 / height)); mol_util_1.ValueCell.update(this.overlay.values.uTexSizeInv, linear_algebra_1.Vec2.set(this.overlay.values.uTexSizeInv.ref.value, 1 / width, 1 / height)); } } update(props) { const { highlightEdgeColor, selectEdgeColor, edgeScale, innerEdgeFactor, ghostEdgeStrength, highlightEdgeStrength, selectEdgeStrength } = props; const { values: edgeValues } = this.edge; const _edgeScale = Math.max(1, Math.round(edgeScale * this.webgl.pixelRatio)); if (edgeValues.dEdgeScale.ref.value !== _edgeScale) { mol_util_1.ValueCell.update(edgeValues.dEdgeScale, _edgeScale); this.edge.update(); } const { values: overlayValues } = this.overlay; mol_util_1.ValueCell.update(overlayValues.uHighlightEdgeColor, color_1.Color.toVec3Normalized(overlayValues.uHighlightEdgeColor.ref.value, highlightEdgeColor)); mol_util_1.ValueCell.update(overlayValues.uSelectEdgeColor, color_1.Color.toVec3Normalized(overlayValues.uSelectEdgeColor.ref.value, selectEdgeColor)); mol_util_1.ValueCell.updateIfChanged(overlayValues.uInnerEdgeFactor, innerEdgeFactor); mol_util_1.ValueCell.updateIfChanged(overlayValues.uGhostEdgeStrength, ghostEdgeStrength); mol_util_1.ValueCell.updateIfChanged(overlayValues.uHighlightEdgeStrength, highlightEdgeStrength); mol_util_1.ValueCell.updateIfChanged(overlayValues.uSelectEdgeStrength, selectEdgeStrength); } render(viewport, target) { if (debug_1.isTimingMode) this.webgl.timer.mark('MarkingPass.render'); this.edgesTarget.bind(); this.setEdgeState(viewport); this.edge.render(); if (target) { target.bind(); } else { this.webgl.unbindFramebuffer(); } this.setOverlayState(viewport); this.overlay.render(); if (debug_1.isTimingMode) this.webgl.timer.markEnd('MarkingPass.render'); } } exports.MarkingPass = MarkingPass; // const EdgeSchema = { ...util_1.QuadSchema, tMaskTexture: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'linear'), uTexSizeInv: (0, schema_1.UniformSpec)('v2'), dEdgeScale: (0, schema_1.DefineSpec)('number'), }; const EdgeShaderCode = (0, shader_code_1.ShaderCode)('edge', quad_vert_1.quad_vert, edge_frag_1.edge_frag); function getEdgeRenderable(ctx, maskTexture) { const width = maskTexture.getWidth(); const height = maskTexture.getHeight(); const values = { ...util_1.QuadValues, tMaskTexture: mol_util_1.ValueCell.create(maskTexture), uTexSizeInv: mol_util_1.ValueCell.create(linear_algebra_1.Vec2.create(1 / width, 1 / height)), dEdgeScale: mol_util_1.ValueCell.create(1), }; const schema = { ...EdgeSchema }; const renderItem = (0, render_item_1.createComputeRenderItem)(ctx, 'triangles', EdgeShaderCode, schema, values); return (0, renderable_1.createComputeRenderable)(renderItem, values); } // const OverlaySchema = { ...util_1.QuadSchema, tEdgeTexture: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'linear'), uTexSizeInv: (0, schema_1.UniformSpec)('v2'), uHighlightEdgeColor: (0, schema_1.UniformSpec)('v3'), uSelectEdgeColor: (0, schema_1.UniformSpec)('v3'), uHighlightEdgeStrength: (0, schema_1.UniformSpec)('f'), uSelectEdgeStrength: (0, schema_1.UniformSpec)('f'), uGhostEdgeStrength: (0, schema_1.UniformSpec)('f'), uInnerEdgeFactor: (0, schema_1.UniformSpec)('f'), }; const OverlayShaderCode = (0, shader_code_1.ShaderCode)('overlay', quad_vert_1.quad_vert, overlay_frag_1.overlay_frag); function getOverlayRenderable(ctx, edgeTexture) { const width = edgeTexture.getWidth(); const height = edgeTexture.getHeight(); const values = { ...util_1.QuadValues, tEdgeTexture: mol_util_1.ValueCell.create(edgeTexture), uTexSizeInv: mol_util_1.ValueCell.create(linear_algebra_1.Vec2.create(1 / width, 1 / height)), uHighlightEdgeColor: mol_util_1.ValueCell.create((0, linear_algebra_1.Vec3)()), uSelectEdgeColor: mol_util_1.ValueCell.create((0, linear_algebra_1.Vec3)()), uHighlightEdgeStrength: mol_util_1.ValueCell.create(1), uSelectEdgeStrength: mol_util_1.ValueCell.create(1), uGhostEdgeStrength: mol_util_1.ValueCell.create(0), uInnerEdgeFactor: mol_util_1.ValueCell.create(0), }; const schema = { ...OverlaySchema }; const renderItem = (0, render_item_1.createComputeRenderItem)(ctx, 'triangles', OverlayShaderCode, schema, values); return (0, renderable_1.createComputeRenderable)(renderItem, values); }