molstar
Version:
A comprehensive macromolecular library.
153 lines (152 loc) • 7.49 kB
JavaScript
"use strict";
/**
* Copyright (c) 2019-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImagePass = exports.ImageParams = void 0;
const renderer_1 = require("../../mol-gl/renderer.js");
const param_definition_1 = require("../../mol-util/param-definition.js");
const draw_1 = require("./draw.js");
const postprocessing_1 = require("./postprocessing.js");
const multi_sample_1 = require("./multi-sample.js");
const camera_1 = require("../camera.js");
const util_1 = require("../camera/util.js");
const image_1 = require("../../mol-util/image.js");
const camera_helper_1 = require("../helper/camera-helper.js");
const marking_1 = require("./marking.js");
const illumination_1 = require("./illumination.js");
const debug_1 = require("../../mol-util/debug.js");
const timer_1 = require("../../mol-gl/webgl/timer.js");
const shader_manager_1 = require("../helper/shader-manager.js");
exports.ImageParams = {
transparentBackground: param_definition_1.ParamDefinition.Boolean(false),
dpoitIterations: param_definition_1.ParamDefinition.Numeric(2, { min: 1, max: 10, step: 1 }),
multiSample: param_definition_1.ParamDefinition.Group(multi_sample_1.MultiSampleParams),
postprocessing: param_definition_1.ParamDefinition.Group(postprocessing_1.PostprocessingParams),
marking: param_definition_1.ParamDefinition.Group(marking_1.MarkingParams),
illumination: param_definition_1.ParamDefinition.Group(illumination_1.IlluminationParams),
cameraHelper: param_definition_1.ParamDefinition.Group(camera_helper_1.CameraHelperParams),
renderer: param_definition_1.ParamDefinition.Group(renderer_1.RendererParams),
};
class ImagePass {
get colorTarget() { return this._colorTarget; }
get width() { return this._width; }
get height() { return this._height; }
constructor(webgl, assetManager, renderer, scene, camera, helper, props) {
this.webgl = webgl;
this.renderer = renderer;
this.scene = scene;
this.camera = camera;
this._width = 0;
this._height = 0;
this._camera = new camera_1.Camera();
this.props = { ...param_definition_1.ParamDefinition.getDefaultValues(exports.ImageParams), ...props };
this.drawPass = new draw_1.DrawPass(webgl, assetManager, 128, 128, scene.transparency);
this.illuminationPass = new illumination_1.IlluminationPass(webgl, this.drawPass);
this.multiSamplePass = new multi_sample_1.MultiSamplePass(webgl, this.drawPass);
this.multiSampleHelper = new multi_sample_1.MultiSampleHelper(this.multiSamplePass);
this.helper = {
camera: new camera_helper_1.CameraHelper(webgl, this.props.cameraHelper),
debug: helper.debug,
handle: helper.handle,
pointer: helper.pointer,
};
this.setSize(1024, 768);
}
getByteCount() {
return this.drawPass.getByteCount() + this.illuminationPass.getByteCount() + this.multiSamplePass.getByteCount();
}
updateBackground() {
return new Promise(resolve => {
this.drawPass.postprocessing.background.update(this.camera, this.props.postprocessing.background, () => {
resolve();
});
});
}
setSize(width, height) {
if (width === this._width && height === this._height)
return;
this._width = width;
this._height = height;
this.drawPass.setSize(width, height);
this.illuminationPass.setSize(width, height);
this.multiSamplePass.syncSize();
}
setProps(props = {}) {
Object.assign(this.props, props);
if (props.cameraHelper)
this.helper.camera.setProps(props.cameraHelper);
}
async render(runtime) {
this.drawPass.setTransparency(this.scene.transparency);
shader_manager_1.ShaderManager.ensureRequired(this.webgl, this.scene, this.props);
camera_1.Camera.copySnapshot(this._camera.state, this.camera.state);
util_1.Viewport.set(this._camera.viewport, 0, 0, this._width, this._height);
this._camera.update();
this.renderer.setOcclusionTest(null);
const ctx = { renderer: this.renderer, camera: this._camera, scene: this.scene, helper: this.helper };
if (this.illuminationPass.supported && this.props.illumination.enabled) {
await runtime.update({ message: 'Tracing...', current: 1, max: this.illuminationPass.getMaxIterations(this.props.illumination) });
this.illuminationPass.restart(true);
while (this.illuminationPass.shouldRender(this.props.illumination)) {
if (debug_1.isTimingMode)
this.webgl.timer.mark('ImagePass.render', { captureStats: true });
this.illuminationPass.render(ctx, this.props, false);
if (debug_1.isTimingMode)
this.webgl.timer.markEnd('ImagePass.render');
if (runtime.shouldUpdate) {
await runtime.update({ current: this.illuminationPass.iteration });
}
await this.webgl.waitForGpuCommandsComplete();
}
this._colorTarget = this.illuminationPass.colorTarget;
}
else {
if (debug_1.isTimingMode)
this.webgl.timer.mark('ImagePass.render', { captureStats: true });
if (multi_sample_1.MultiSamplePass.isEnabled(this.props.multiSample)) {
this.multiSampleHelper.render(ctx, this.props, false);
this._colorTarget = this.multiSamplePass.colorTarget;
}
else {
this.drawPass.render(ctx, this.props, false);
this._colorTarget = this.drawPass.getColorTarget(this.props.postprocessing);
}
if (debug_1.isTimingMode)
this.webgl.timer.markEnd('ImagePass.render');
}
if (debug_1.isTimingMode) {
const timerResults = this.webgl.timer.resolve();
if (timerResults) {
for (const result of timerResults) {
(0, timer_1.printTimerResults)([result]);
}
}
}
if (debug_1.isDebugMode) {
console.log(`image pass byte count ${(this.getByteCount() / 1024 / 1024).toFixed(3)} MiB`);
}
}
async getImageData(runtime, width, height, viewport) {
var _a, _b;
this.setSize(width, height);
await this.render(runtime);
this.colorTarget.bind();
const w = (_a = viewport === null || viewport === void 0 ? void 0 : viewport.width) !== null && _a !== void 0 ? _a : width, h = (_b = viewport === null || viewport === void 0 ? void 0 : viewport.height) !== null && _b !== void 0 ? _b : height;
const array = new Uint8Array(w * h * 4);
if (!viewport) {
this.webgl.readPixels(0, 0, w, h, array);
}
else {
this.webgl.readPixels(viewport.x, height - viewport.y - viewport.height, w, h, array);
}
const pixelData = image_1.PixelData.create(array, w, h);
image_1.PixelData.flipY(pixelData);
image_1.PixelData.divideByAlpha(pixelData);
return new ImageData(new Uint8ClampedArray(array), w, h);
}
}
exports.ImagePass = ImagePass;