molstar
Version:
A comprehensive macromolecular library.
299 lines • 17.2 kB
JavaScript
"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