UNPKG

molstar

Version:

A comprehensive macromolecular library.

299 lines 17.2 kB
"use strict"; /** * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.DrawPass = void 0; var tslib_1 = require("tslib"); var render_target_1 = require("../../mol-gl/webgl/render-target"); var util_1 = require("../../mol-gl/compute/util"); var schema_1 = require("../../mol-gl/renderable/schema"); var renderable_1 = require("../../mol-gl/renderable"); var shader_code_1 = require("../../mol-gl/shader-code"); var render_item_1 = require("../../mol-gl/webgl/render-item"); var mol_util_1 = require("../../mol-util"); var linear_algebra_1 = require("../../mol-math/linear-algebra"); var quad_vert_1 = require("../../mol-gl/shader/quad.vert"); var depth_merge_frag_1 = require("../../mol-gl/shader/depth-merge.frag"); var copy_frag_1 = require("../../mol-gl/shader/copy.frag"); var stereo_1 = require("../camera/stereo"); var wboit_1 = require("./wboit"); var postprocessing_1 = require("./postprocessing"); var marking_1 = require("./marking"); var DepthMergeSchema = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, util_1.QuadSchema), { tDepthPrimitives: (0, schema_1.TextureSpec)('texture', 'depth', 'ushort', 'nearest'), tDepthVolumes: (0, schema_1.TextureSpec)('texture', 'depth', 'ushort', 'nearest'), uTexSize: (0, schema_1.UniformSpec)('v2'), dPackedDepth: (0, schema_1.DefineSpec)('boolean') }); var DepthMergeShaderCode = (0, shader_code_1.ShaderCode)('depth-merge', quad_vert_1.quad_vert, depth_merge_frag_1.depthMerge_frag); function getDepthMergeRenderable(ctx, depthTexturePrimitives, depthTextureVolumes, packedDepth) { var values = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, util_1.QuadValues), { tDepthPrimitives: mol_util_1.ValueCell.create(depthTexturePrimitives), tDepthVolumes: mol_util_1.ValueCell.create(depthTextureVolumes), uTexSize: mol_util_1.ValueCell.create(linear_algebra_1.Vec2.create(depthTexturePrimitives.getWidth(), depthTexturePrimitives.getHeight())), dPackedDepth: mol_util_1.ValueCell.create(packedDepth) }); var schema = (0, tslib_1.__assign)({}, DepthMergeSchema); var renderItem = (0, render_item_1.createComputeRenderItem)(ctx, 'triangles', DepthMergeShaderCode, schema, values); return (0, renderable_1.createComputeRenderable)(renderItem, values); } var CopySchema = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, util_1.QuadSchema), { tColor: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'nearest'), uTexSize: (0, schema_1.UniformSpec)('v2') }); var CopyShaderCode = (0, shader_code_1.ShaderCode)('copy', quad_vert_1.quad_vert, copy_frag_1.copy_frag); function getCopyRenderable(ctx, colorTexture) { var values = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, util_1.QuadValues), { tColor: mol_util_1.ValueCell.create(colorTexture), uTexSize: mol_util_1.ValueCell.create(linear_algebra_1.Vec2.create(colorTexture.getWidth(), colorTexture.getHeight())) }); var schema = (0, tslib_1.__assign)({}, CopySchema); var renderItem = (0, render_item_1.createComputeRenderItem)(ctx, 'triangles', CopyShaderCode, schema, values); return (0, renderable_1.createComputeRenderable)(renderItem, values); } var DrawPass = /** @class */ (function () { function DrawPass(webgl, width, height, enableWboit) { this.webgl = webgl; var extensions = webgl.extensions, resources = webgl.resources, isWebGL2 = webgl.isWebGL2; this.drawTarget = (0, render_target_1.createNullRenderTarget)(webgl.gl); this.colorTarget = webgl.createRenderTarget(width, height, true, 'uint8', 'linear'); this.packedDepth = !extensions.depthTexture; this.depthTarget = webgl.createRenderTarget(width, height); this.depthTexture = this.depthTarget.texture; this.depthTargetPrimitives = this.packedDepth ? webgl.createRenderTarget(width, height) : null; this.depthTargetVolumes = this.packedDepth ? webgl.createRenderTarget(width, height) : null; this.depthTexturePrimitives = this.depthTargetPrimitives ? this.depthTargetPrimitives.texture : resources.texture('image-depth', 'depth', isWebGL2 ? 'float' : 'ushort', 'nearest'); this.depthTextureVolumes = this.depthTargetVolumes ? this.depthTargetVolumes.texture : resources.texture('image-depth', 'depth', isWebGL2 ? 'float' : 'ushort', 'nearest'); if (!this.packedDepth) { this.depthTexturePrimitives.define(width, height); this.depthTextureVolumes.define(width, height); } this.depthMerge = getDepthMergeRenderable(webgl, this.depthTexturePrimitives, this.depthTextureVolumes, this.packedDepth); this.wboit = enableWboit ? new wboit_1.WboitPass(webgl, width, height) : undefined; this.marking = new marking_1.MarkingPass(webgl, width, height); this.postprocessing = new postprocessing_1.PostprocessingPass(webgl, this); this.antialiasing = new postprocessing_1.AntialiasingPass(webgl, this); this.copyFboTarget = getCopyRenderable(webgl, this.colorTarget.texture); this.copyFboPostprocessing = getCopyRenderable(webgl, this.postprocessing.target.texture); } Object.defineProperty(DrawPass.prototype, "wboitEnabled", { get: function () { var _a; return !!((_a = this.wboit) === null || _a === void 0 ? void 0 : _a.supported); }, enumerable: false, configurable: true }); DrawPass.prototype.reset = function () { var _a; (_a = this.wboit) === null || _a === void 0 ? void 0 : _a.reset(); }; DrawPass.prototype.setSize = function (width, height) { var _a; var w = this.colorTarget.getWidth(); var h = this.colorTarget.getHeight(); if (width !== w || height !== h) { this.colorTarget.setSize(width, height); this.depthTarget.setSize(width, height); if (this.depthTargetPrimitives) { this.depthTargetPrimitives.setSize(width, height); } else { this.depthTexturePrimitives.define(width, height); } if (this.depthTargetVolumes) { this.depthTargetVolumes.setSize(width, height); } else { this.depthTextureVolumes.define(width, height); } mol_util_1.ValueCell.update(this.depthMerge.values.uTexSize, linear_algebra_1.Vec2.set(this.depthMerge.values.uTexSize.ref.value, width, height)); mol_util_1.ValueCell.update(this.copyFboTarget.values.uTexSize, linear_algebra_1.Vec2.set(this.copyFboTarget.values.uTexSize.ref.value, width, height)); mol_util_1.ValueCell.update(this.copyFboPostprocessing.values.uTexSize, linear_algebra_1.Vec2.set(this.copyFboPostprocessing.values.uTexSize.ref.value, width, height)); if ((_a = this.wboit) === null || _a === void 0 ? void 0 : _a.supported) { this.wboit.setSize(width, height); } this.marking.setSize(width, height); this.postprocessing.setSize(width, height); this.antialiasing.setSize(width, height); } }; DrawPass.prototype._depthMerge = function () { var _a = this.webgl, state = _a.state, gl = _a.gl; this.depthMerge.update(); this.depthTarget.bind(); state.disable(gl.BLEND); state.disable(gl.DEPTH_TEST); state.disable(gl.CULL_FACE); state.depthMask(false); state.clearColor(1, 1, 1, 1); gl.clear(gl.COLOR_BUFFER_BIT); this.depthMerge.render(); }; DrawPass.prototype._renderWboit = function (renderer, camera, scene, transparentBackground, postprocessingProps) { var _a; if (!((_a = this.wboit) === null || _a === void 0 ? void 0 : _a.supported)) throw new Error('expected wboit to be supported'); this.colorTarget.bind(); renderer.clear(true); // render opaque primitives this.depthTexturePrimitives.attachFramebuffer(this.colorTarget.framebuffer, 'depth'); this.colorTarget.bind(); renderer.clearDepth(); renderer.renderWboitOpaque(scene.primitives, camera, null); // render opaque volumes this.depthTextureVolumes.attachFramebuffer(this.colorTarget.framebuffer, 'depth'); this.colorTarget.bind(); renderer.clearDepth(); renderer.renderWboitOpaque(scene.volumes, camera, this.depthTexturePrimitives); // merge depth of opaque primitives and volumes this._depthMerge(); if (postprocessing_1.PostprocessingPass.isEnabled(postprocessingProps)) { this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps); } // render transparent primitives and volumes this.wboit.bind(); renderer.renderWboitTransparent(scene.primitives, camera, this.depthTexture); renderer.renderWboitTransparent(scene.volumes, camera, this.depthTexture); // evaluate wboit if (postprocessing_1.PostprocessingPass.isEnabled(postprocessingProps)) { this.depthTexturePrimitives.attachFramebuffer(this.postprocessing.target.framebuffer, 'depth'); this.postprocessing.target.bind(); } else { this.depthTexturePrimitives.attachFramebuffer(this.colorTarget.framebuffer, 'depth'); this.colorTarget.bind(); } this.wboit.render(); }; DrawPass.prototype._renderBlended = function (renderer, camera, scene, toDrawingBuffer, transparentBackground, postprocessingProps) { if (toDrawingBuffer) { this.drawTarget.bind(); } else { this.colorTarget.bind(); if (!this.packedDepth) { this.depthTexturePrimitives.attachFramebuffer(this.colorTarget.framebuffer, 'depth'); } } renderer.clear(true); renderer.renderBlendedOpaque(scene.primitives, camera, null); if (!toDrawingBuffer) { // do a depth pass if not rendering to drawing buffer and // extensions.depthTexture is unsupported (i.e. depthTarget is set) if (this.depthTargetPrimitives) { this.depthTargetPrimitives.bind(); renderer.clear(false); // TODO: this should only render opaque renderer.renderDepth(scene.primitives, camera, null); this.colorTarget.bind(); } // do direct-volume rendering if (!this.packedDepth) { this.depthTextureVolumes.attachFramebuffer(this.colorTarget.framebuffer, 'depth'); renderer.clearDepth(); // from previous frame } renderer.renderBlendedVolumeOpaque(scene.volumes, camera, this.depthTexturePrimitives); // do volume depth pass if extensions.depthTexture is unsupported (i.e. depthTarget is set) if (this.depthTargetVolumes) { this.depthTargetVolumes.bind(); renderer.clear(false); renderer.renderDepth(scene.volumes, camera, this.depthTexturePrimitives); this.colorTarget.bind(); } // merge depths from primitive and volume rendering this._depthMerge(); this.colorTarget.bind(); if (postprocessing_1.PostprocessingPass.isEnabled(postprocessingProps)) { this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps); } renderer.renderBlendedVolumeTransparent(scene.volumes, camera, this.depthTexturePrimitives); var target = postprocessing_1.PostprocessingPass.isEnabled(postprocessingProps) ? this.postprocessing.target : this.colorTarget; if (!this.packedDepth) { this.depthTexturePrimitives.attachFramebuffer(target.framebuffer, 'depth'); } target.bind(); } renderer.renderBlendedTransparent(scene.primitives, camera, null); }; DrawPass.prototype._render = function (renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, postprocessingProps, markingProps) { var volumeRendering = scene.volumes.renderables.length > 0; var postprocessingEnabled = postprocessing_1.PostprocessingPass.isEnabled(postprocessingProps); var antialiasingEnabled = postprocessing_1.AntialiasingPass.isEnabled(postprocessingProps); var markingEnabled = marking_1.MarkingPass.isEnabled(markingProps); var _a = camera.viewport, x = _a.x, y = _a.y, width = _a.width, height = _a.height; renderer.setViewport(x, y, width, height); renderer.update(camera); if (transparentBackground && !antialiasingEnabled && toDrawingBuffer) { this.drawTarget.bind(); renderer.clear(false); } if (this.wboitEnabled) { this._renderWboit(renderer, camera, scene, transparentBackground, postprocessingProps); } else { this._renderBlended(renderer, camera, scene, !volumeRendering && !postprocessingEnabled && !antialiasingEnabled && toDrawingBuffer, transparentBackground, postprocessingProps); } if (postprocessingEnabled) { this.postprocessing.target.bind(); } else if (!toDrawingBuffer || volumeRendering || this.wboitEnabled) { this.colorTarget.bind(); } else { this.drawTarget.bind(); } if (markingEnabled) { var markingDepthTest = markingProps.ghostEdgeStrength < 1; if (markingDepthTest) { this.marking.depthTarget.bind(); renderer.clear(false); renderer.renderMarkingDepth(scene.primitives, camera, null); } this.marking.maskTarget.bind(); renderer.clear(false); renderer.renderMarkingMask(scene.primitives, camera, markingDepthTest ? this.marking.depthTarget.texture : null); this.marking.update(markingProps); this.marking.render(camera.viewport, postprocessingEnabled ? this.postprocessing.target : this.colorTarget); } if (helper.debug.isEnabled) { helper.debug.syncVisibility(); renderer.renderBlended(helper.debug.scene, camera, null); } if (helper.handle.isEnabled) { renderer.renderBlended(helper.handle.scene, camera, null); } if (helper.camera.isEnabled) { helper.camera.update(camera); renderer.update(helper.camera.camera); renderer.renderBlended(helper.camera.scene, helper.camera.camera, null); } if (antialiasingEnabled) { this.antialiasing.render(camera, toDrawingBuffer, postprocessingProps); } else if (toDrawingBuffer) { this.drawTarget.bind(); this.webgl.state.disable(this.webgl.gl.DEPTH_TEST); if (postprocessingEnabled) { this.copyFboPostprocessing.render(); } else if (volumeRendering || this.wboitEnabled) { this.copyFboTarget.render(); } } this.webgl.gl.flush(); }; DrawPass.prototype.render = function (renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, postprocessingProps, markingProps) { renderer.setTransparentBackground(transparentBackground); renderer.setDrawingBufferSize(this.colorTarget.getWidth(), this.colorTarget.getHeight()); renderer.setPixelRatio(this.webgl.pixelRatio); if (stereo_1.StereoCamera.is(camera)) { this._render(renderer, camera.left, scene, helper, toDrawingBuffer, transparentBackground, postprocessingProps, markingProps); this._render(renderer, camera.right, scene, helper, toDrawingBuffer, transparentBackground, postprocessingProps, markingProps); } else { this._render(renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, postprocessingProps, markingProps); } }; DrawPass.prototype.getColorTarget = function (postprocessingProps) { if (postprocessing_1.AntialiasingPass.isEnabled(postprocessingProps)) { return this.antialiasing.target; } else if (postprocessing_1.PostprocessingPass.isEnabled(postprocessingProps)) { return this.postprocessing.target; } return this.colorTarget; }; return DrawPass; }()); exports.DrawPass = DrawPass; //# sourceMappingURL=draw.js.map