UNPKG

molstar

Version:

A comprehensive macromolecular library.

158 lines 7.97 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> */ 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