molstar
Version:
A comprehensive macromolecular library.
158 lines • 7.97 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>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createHistogramPyramid = void 0;
var tslib_1 = require("tslib");
var renderable_1 = require("../../renderable");
var render_item_1 = require("../../webgl/render-item");
var schema_1 = require("../../renderable/schema");
var shader_code_1 = require("../../../mol-gl/shader-code");
var mol_util_1 = require("../../../mol-util");
var util_1 = require("../util");
var sum_1 = require("./sum");
var misc_1 = require("../../../mol-math/misc");
var quad_vert_1 = require("../../../mol-gl/shader/quad.vert");
var reduction_frag_1 = require("../../../mol-gl/shader/histogram-pyramid/reduction.frag");
var compat_1 = require("../../webgl/compat");
var HistopyramidReductionSchema = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, util_1.QuadSchema), { tInputLevel: (0, schema_1.TextureSpec)('texture', 'rgba', 'float', 'nearest'), tPreviousLevel: (0, schema_1.TextureSpec)('texture', 'rgba', 'float', 'nearest'), uSize: (0, schema_1.UniformSpec)('f'), uTexSize: (0, schema_1.UniformSpec)('f'), uFirst: (0, schema_1.UniformSpec)('b') });
var HistogramPyramidName = 'histogram-pyramid';
function getHistopyramidReductionRenderable(ctx, inputLevel, previousLevel) {
if (ctx.namedComputeRenderables[HistogramPyramidName]) {
var v = ctx.namedComputeRenderables[HistogramPyramidName].values;
mol_util_1.ValueCell.update(v.tInputLevel, inputLevel);
mol_util_1.ValueCell.update(v.tPreviousLevel, previousLevel);
ctx.namedComputeRenderables[HistogramPyramidName].update();
}
else {
ctx.namedComputeRenderables[HistogramPyramidName] = createHistopyramidReductionRenderable(ctx, inputLevel, previousLevel);
}
return ctx.namedComputeRenderables[HistogramPyramidName];
}
function createHistopyramidReductionRenderable(ctx, inputLevel, previousLevel) {
var values = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, util_1.QuadValues), { tInputLevel: mol_util_1.ValueCell.create(inputLevel), tPreviousLevel: mol_util_1.ValueCell.create(previousLevel), uSize: mol_util_1.ValueCell.create(0), uTexSize: mol_util_1.ValueCell.create(0), uFirst: mol_util_1.ValueCell.create(true) });
var schema = (0, tslib_1.__assign)({}, HistopyramidReductionSchema);
var shaderCode = (0, shader_code_1.ShaderCode)('reduction', quad_vert_1.quad_vert, reduction_frag_1.reduction_frag, {}, { 0: 'ivec4' });
var renderItem = (0, render_item_1.createComputeRenderItem)(ctx, 'triangles', shaderCode, schema, values);
return (0, renderable_1.createComputeRenderable)(renderItem, values);
}
function getLevelTextureFramebuffer(ctx, level) {
var size = Math.pow(2, level);
var name = "level" + level;
var texture = ctx.isWebGL2
? getTexture(name, ctx, 'image-int32', 'alpha', 'int', 'nearest')
: getTexture(name, ctx, 'image-uint8', 'rgba', 'ubyte', 'nearest');
texture.define(size, size);
var framebuffer = tryGetFramebuffer(name, ctx);
if (!framebuffer) {
framebuffer = getFramebuffer(name, ctx);
texture.attachFramebuffer(framebuffer, 0);
}
return { texture: texture, framebuffer: framebuffer };
}
function setRenderingDefaults(ctx) {
var gl = ctx.gl, state = ctx.state;
state.disable(gl.CULL_FACE);
state.disable(gl.BLEND);
state.disable(gl.DEPTH_TEST);
state.enable(gl.SCISSOR_TEST);
state.depthMask(false);
state.colorMask(true, true, true, true);
state.clearColor(0, 0, 0, 0);
}
function getFramebuffer(name, webgl) {
var _name = HistogramPyramidName + "-" + name;
if (!webgl.namedFramebuffers[_name]) {
webgl.namedFramebuffers[_name] = webgl.resources.framebuffer();
}
return webgl.namedFramebuffers[_name];
}
function getTexture(name, webgl, kind, format, type, filter) {
var _name = HistogramPyramidName + "-" + name;
if (!webgl.namedTextures[_name]) {
webgl.namedTextures[_name] = webgl.resources.texture(kind, format, type, filter);
}
return webgl.namedTextures[_name];
}
function tryGetFramebuffer(name, webgl) {
var _name = HistogramPyramidName + "-" + name;
return webgl.namedFramebuffers[_name];
}
function createHistogramPyramid(ctx, inputTexture, scale, gridTexDim) {
var gl = ctx.gl;
var w = inputTexture.getWidth();
var h = inputTexture.getHeight();
// printTexture(ctx, inputTexture, 2)
if (w !== h || !(0, misc_1.isPowerOfTwo)(w)) {
throw new Error('inputTexture must be of square power-of-two size');
}
// This part set the levels
var levels = Math.ceil(Math.log(w) / Math.log(2));
var maxSize = Math.pow(2, levels);
var maxSizeX = Math.pow(2, levels);
var maxSizeY = Math.pow(2, levels - 1);
// console.log('levels', levels, 'maxSize', maxSize, [maxSizeX, maxSizeY], 'input', w);
var pyramidTex = ctx.isWebGL2
? getTexture('pyramid', ctx, 'image-int32', 'alpha', 'int', 'nearest')
: getTexture('pyramid', ctx, 'image-uint8', 'rgba', 'ubyte', 'nearest');
pyramidTex.define(maxSizeX, maxSizeY);
var framebuffer = getFramebuffer('pyramid', ctx);
pyramidTex.attachFramebuffer(framebuffer, 0);
gl.viewport(0, 0, maxSizeX, maxSizeY);
if ((0, compat_1.isWebGL2)(gl)) {
gl.clearBufferiv(gl.COLOR, 0, [0, 0, 0, 0]);
}
else {
gl.clear(gl.COLOR_BUFFER_BIT);
}
var levelTexturesFramebuffers = [];
for (var i = 0; i < levels; ++i)
levelTexturesFramebuffers.push(getLevelTextureFramebuffer(ctx, i));
var renderable = getHistopyramidReductionRenderable(ctx, inputTexture, levelTexturesFramebuffers[0].texture);
ctx.state.currentRenderItemId = -1;
setRenderingDefaults(ctx);
var offset = 0;
for (var i = 0; i < levels; i++) {
var currLevel = levels - 1 - i;
var tf = levelTexturesFramebuffers[currLevel];
tf.framebuffer.bind();
var size = Math.pow(2, currLevel);
// console.log('size', size, 'draw-level', currLevel, 'read-level', levels - i);
mol_util_1.ValueCell.update(renderable.values.uSize, Math.pow(2, i + 1) / maxSize);
mol_util_1.ValueCell.update(renderable.values.uTexSize, size);
mol_util_1.ValueCell.updateIfChanged(renderable.values.uFirst, i === 0);
if (i > 0) {
mol_util_1.ValueCell.update(renderable.values.tPreviousLevel, levelTexturesFramebuffers[levels - i].texture);
renderable.update();
}
ctx.state.currentRenderItemId = -1;
gl.viewport(0, 0, size, size);
gl.scissor(0, 0, size, size);
if ((0, compat_1.isWebGL2)(gl)) {
gl.clearBufferiv(gl.COLOR, 0, [0, 0, 0, 0]);
}
else {
gl.clear(gl.COLOR_BUFFER_BIT);
}
gl.scissor(0, 0, gridTexDim[0], gridTexDim[1]);
renderable.render();
pyramidTex.bind(0);
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, offset, 0, 0, 0, size, size);
pyramidTex.unbind(0);
offset += size;
}
gl.finish();
// printTexture(ctx, pyramidTex, 2)
//
// return at least a count of one to avoid issues downstram
var count = Math.max(1, (0, sum_1.getHistopyramidSum)(ctx, levelTexturesFramebuffers[0].texture));
var height = Math.ceil(count / Math.pow(2, levels));
// const scale = Vec2.create(maxSize / inputTexture.width, maxSize / inputTexture.height);
// console.log('height', height, 'finalCount', count, 'scale', scale);
return { pyramidTex: pyramidTex, count: count, height: height, levels: levels, scale: scale };
}
exports.createHistogramPyramid = createHistogramPyramid;
//# sourceMappingURL=reduction.js.map