@thewtex/vtk.js-esm
Version:
Visualization Toolkit for the Web
406 lines (335 loc) • 17.3 kB
JavaScript
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import macro from '../../../macro.js';
import { v as vtkLineIntegralConvolution2D_LIC0 } from './glsl/vtkLineIntegralConvolution2D_LIC0.glsl.js';
import { v as vtkLineIntegralConvolution2D_LICI } from './glsl/vtkLineIntegralConvolution2D_LICI.glsl.js';
import { v as vtkLineIntegralConvolution2D_LICN } from './glsl/vtkLineIntegralConvolution2D_LICN.glsl.js';
import { v as vtkLineIntegralConvolution2D_CE } from './glsl/vtkLineIntegralConvolution2D_CE.glsl.js';
import { v as vtkLineIntegralConvolution2D_EE } from './glsl/vtkLineIntegralConvolution2D_EE.glsl.js';
import { v as vtkLineIntegralConvolution2D_AAH } from './glsl/vtkLineIntegralConvolution2D_AAH.glsl.js';
import { v as vtkLineIntegralConvolution2D_VT } from './glsl/vtkLineIntegralConvolution2D_VT.glsl.js';
import { v as vtkLineIntegralConvolution2D_AAV } from './glsl/vtkLineIntegralConvolution2D_AAV.glsl.js';
import { v as vtkLineIntegralConvolution2D_quadVS } from './glsl/vtkLineIntegralConvolution2D_quadVS.glsl.js';
import vtkShaderProgram from '../ShaderProgram.js';
import vtkOpenGLFramebuffer from '../Framebuffer.js';
import vtkLICPingPongBufferManager from './LineIntegralConvolution2D/pingpong.js';
import { ContrastEnhanceMode } from '../../Core/SurfaceLICInterface/Constants.js';
function getVectorLookupProgram() {
var normalize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
// lookup the vector and normalize
var getNormVecSrc = "\n vec2 getVector( vec2 vectc )\n\n {\n\n vec2 V = texture2D( texVectors, vectc ).xy;\n\n // normalize if |V| not 0\n\n float lenV = length( V );\n\n if ( lenV > 1.0e-8 )\n\n {\n\n return V/lenV;\n\n }\n\n else\n\n {\n\n return vec2( 0.0, 0.0 );\n\n }\n\n }\n\n "; // lookup the vector
var getVecSrc = "\n vec2 getVector( vec2 vectc )\n\n {\n\n return texture2D( texVectors, vectc ).xy;\n\n }\n\n ";
if (normalize) {
return getNormVecSrc;
}
return getVecSrc;
}
function vtkLineIntegralConvolution2D(publicAPI, model) {
model.classHierarchy.push('vtkLineIntegralConvolution2D');
publicAPI.buildAShader = function (fSource) {
return model.openGLRenderWindow.getShaderCache().readyShaderProgramArray(vtkLineIntegralConvolution2D_quadVS, fSource, '');
};
publicAPI.dumpTextureValues = function (texture, _ref) {
var _ref2 = _slicedToArray(_ref, 2),
width = _ref2[0],
height = _ref2[1];
var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : model.context;
var openGLRenderWindow = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : model.openGLRenderWindow;
var nComp = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 4;
// To get texture values in es 2.0, we need to attach the texture to a fbo,
// then use glReadPixels
var fb = vtkOpenGLFramebuffer.newInstance();
var gl = context;
var pixels = null;
fb.setOpenGLRenderWindow(openGLRenderWindow);
fb.saveCurrentBindingsAndBuffers();
fb.create(width, height);
fb.populateFramebuffer();
fb.setColorBuffer(texture);
pixels = new Float32Array(width * height * nComp);
gl.readPixels(0, 0, width, height, nComp === 4 ? gl.RGBA : gl.RGB, gl.FLOAT, pixels);
fb.restorePreviousBindingsAndBuffers();
return pixels;
};
publicAPI.getTextureMinMax = function (texture, size) {
var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : model.context;
var openGLRenderWindow = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : model.openGLRenderWindow;
var values = publicAPI.dumpTextureValues(texture, size, context, openGLRenderWindow, 4);
var min = Number.MAX_VALUE;
var max = Number.MIN_VALUE;
for (var i = 0; i < values.length; i += 4) {
// Make sure the current pixel is inside the rendered geometry (g === 0)
if (values[i + 1] === 0.0) {
var val = values[i];
if (val < min) {
min = val;
}
if (val > max) {
max = val;
}
}
}
return {
min: min,
max: max
};
};
publicAPI.getComponentSelectionProgram = function (ids) {
var compNames = 'xyzw';
return ".".concat(compNames[ids[0]]).concat(compNames[ids[1]]);
};
publicAPI.buildShaders = function () {
model.LIC0ShaderProgram = publicAPI.buildAShader(vtkLineIntegralConvolution2D_LIC0);
var VTFSource = vtkShaderProgram.substitute(vtkLineIntegralConvolution2D_VT, '//VTK::LICComponentSelection::Impl', "vec2 V = texture2D(texVectors, tcoordVC.st)".concat(publicAPI.getComponentSelectionProgram(model.componentIds), ";")).result;
model.VTProgram = publicAPI.buildAShader(VTFSource);
var LICISource = vtkShaderProgram.substitute(vtkLineIntegralConvolution2D_LICI, '//VTK::LICVectorLookup::Impl', getVectorLookupProgram(model.normalizeVectors), true).result;
model.LICIShaderProgram = publicAPI.buildAShader(LICISource);
model.LICNShaderProgram = publicAPI.buildAShader(vtkLineIntegralConvolution2D_LICN);
model.CEProgram = publicAPI.buildAShader(vtkLineIntegralConvolution2D_CE);
model.EEProgram = publicAPI.buildAShader(vtkLineIntegralConvolution2D_EE);
model.AAHProgram = publicAPI.buildAShader(vtkLineIntegralConvolution2D_AAH);
model.AAVProgram = publicAPI.buildAShader(vtkLineIntegralConvolution2D_AAV);
}; // factorized out frequent patterns
function setLICUniforms(program, bufs) {
program.setUniformi('texLIC', bufs.getLICTextureUnit());
program.setUniformi('texSeedPts', bufs.getSeedTextureUnit());
}
function renderPingPong(bufs, size, program) {
bufs.attachLICBuffers();
bufs.renderQuad(size, program);
bufs.detachLICBuffers();
bufs.swap();
}
publicAPI.executeLIC = function (size, vectorTexture, maskVectorTexture, noiseTexture, openGLRenderWindow, options) {
model.openGLRenderWindow = openGLRenderWindow;
model.context = openGLRenderWindow.getContext();
Object.assign(model, options);
if (size[0] <= 0.0 || size[1] <= 0.0) {
return null;
}
var tcScale = [1.0 / size[0], 1.0 / size[1]];
var stepSize = model.stepSize * Math.sqrt(tcScale[0] * tcScale[0] + tcScale[1] * tcScale[1]);
if (stepSize <= 0) {
stepSize = 1.0e-10;
}
var gl = model.context;
var fb = model.framebuffer;
if (!fb || size[0] !== fb.getSize()[0] || size[1] !== fb.getSize()[1]) {
var _fb;
fb = vtkOpenGLFramebuffer.newInstance();
fb.setOpenGLRenderWindow(model.openGLRenderWindow);
fb.saveCurrentBindingsAndBuffers();
(_fb = fb).create.apply(_fb, _toConsumableArray(size));
fb.populateFramebuffer();
fb.restorePreviousBindingsAndBuffers();
model.framebuffer = fb;
}
fb.saveCurrentBindingsAndBuffers();
fb.bind();
gl.viewport.apply(gl, [0, 0].concat(_toConsumableArray(size)));
gl.scissor.apply(gl, [0, 0].concat(_toConsumableArray(size)));
if (model.shadersNeedBuild) {
publicAPI.buildShaders();
model.shadersNeedBuild = false;
}
if (!model.bufs) {
model.bufs = vtkLICPingPongBufferManager.newInstance({
openGLRenderWindow: openGLRenderWindow,
doEEPass: model.enhancedLIC,
doVTPass: model.transformVectors,
vectorTexture: vectorTexture,
maskVectorTexture: maskVectorTexture,
noiseTexture: noiseTexture,
framebuffer: fb,
size: size
});
} else {
model.bufs.setVectorTexture(vectorTexture);
model.bufs.setMaskVectorTexture(maskVectorTexture);
model.bufs.setNoiseTexture(noiseTexture);
}
var noiseBoundsPt1 = [(noiseTexture.getWidth() + 1) / size[0], (noiseTexture.getHeight() + 1) / size[1]];
var dx = 1.0 / size[0];
var dy = 1.0 / size[1];
var shaderCache = model.openGLRenderWindow.getShaderCache();
if (model.transformVectors) {
var VTShaderProgram = model.VTProgram;
shaderCache.readyShaderProgram(VTShaderProgram);
model.bufs.attachImageVectorBuffer();
VTShaderProgram.setUniform2f.apply(VTShaderProgram, ['uTexSize'].concat(_toConsumableArray(size)));
VTShaderProgram.setUniformi('texVectors', model.bufs.getVectorTextureUnit());
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
model.bufs.renderQuad(size, VTShaderProgram);
model.bufs.detachImageVectorBuffer();
} // first pass
// initialize convolution and seeds
model.bufs.clearBuffers(model.enhancedLIC);
model.bufs.activateVectorTextures();
model.bufs.activateNoiseTexture(0);
var LIC0ShaderProgram = model.LIC0ShaderProgram;
shaderCache.readyShaderProgram(LIC0ShaderProgram);
LIC0ShaderProgram.setUniformi('uStepNo', 0);
LIC0ShaderProgram.setUniformi('uPassNo', 0);
LIC0ShaderProgram.setUniformf('uMaskThreshold', model.maskThreshold);
LIC0ShaderProgram.setUniform2f.apply(LIC0ShaderProgram, ['uNoiseBoundsPt1'].concat(noiseBoundsPt1));
LIC0ShaderProgram.setUniformi('texMaskVectors', model.bufs.getMaskVectorTextureUnit());
LIC0ShaderProgram.setUniformi('texLIC', model.bufs.getLICTextureUnit());
LIC0ShaderProgram.setUniformi('texNoise', model.bufs.getNoiseTextureUnit(0));
renderPingPong(model.bufs, size, LIC0ShaderProgram); // backward lic
var LICIShaderProgram = model.LICIShaderProgram;
shaderCache.readyShaderProgram(LICIShaderProgram);
LICIShaderProgram.setUniformi('uPassNo', 0);
LICIShaderProgram.setUniformf('uStepSize', -stepSize);
LICIShaderProgram.setUniform2f.apply(LICIShaderProgram, ['uNoiseBoundsPt1'].concat(noiseBoundsPt1));
LICIShaderProgram.setUniformi('texVectors', model.bufs.getImageVectorTextureUnit());
LICIShaderProgram.setUniformi('texNoise', model.bufs.getNoiseTextureUnit(0));
for (var stepIdx = 0; stepIdx < model.numberOfSteps; ++stepIdx) {
setLICUniforms(LICIShaderProgram, model.bufs);
renderPingPong(model.bufs, size, LICIShaderProgram);
} // initialize seeds
shaderCache.readyShaderProgram(LIC0ShaderProgram);
LIC0ShaderProgram.setUniformi('uStepNo', 1);
setLICUniforms(LIC0ShaderProgram, model.bufs);
renderPingPong(model.bufs, size, LIC0ShaderProgram); // forward LIC
shaderCache.readyShaderProgram(LICIShaderProgram);
LICIShaderProgram.setUniformf('uStepSize', stepSize);
for (var _stepIdx = 0; _stepIdx < model.numberOfSteps; ++_stepIdx) {
setLICUniforms(LICIShaderProgram, model.bufs);
renderPingPong(model.bufs, size, LICIShaderProgram);
}
model.bufs.deactivateNoiseTexture(0);
model.bufs.deactivateVectorTextures(); // finalize LIC
var LICNShaderProgram = model.LICNShaderProgram;
shaderCache.readyShaderProgram(LICNShaderProgram);
LICNShaderProgram.setUniformi('texLIC', model.bufs.getLICTextureUnit());
renderPingPong(model.bufs, size, LICNShaderProgram); // end of first-pass lic
if (model.enhancedLIC) {
if (model.enhanceContrast === ContrastEnhanceMode.LIC || model.enhanceContrast === ContrastEnhanceMode.BOTH) {
publicAPI.contrastEnhance(false, size);
} // EE stage
model.bufs.attachEEBuffer();
var EEProgram = model.EEProgram;
shaderCache.readyShaderProgram(EEProgram);
EEProgram.setUniformi('texLIC', model.bufs.getLICTextureUnit());
EEProgram.setUniformf('uDx', dx);
EEProgram.setUniformf('uDy', dy);
model.bufs.renderQuad(size, EEProgram);
model.bufs.detachEEBuffer(); // begin second pass LIC
// clear buffers
model.bufs.detachBuffers();
model.bufs.clearBuffers(false);
model.bufs.activateVectorTextures();
model.bufs.activateNoiseTexture(1); // initialize convolution and seeds
shaderCache.readyShaderProgram(LIC0ShaderProgram);
LIC0ShaderProgram.setUniformi('uStepNo', 0);
LIC0ShaderProgram.setUniformi('uPassNo', 1);
setLICUniforms(LIC0ShaderProgram, model.bufs);
LIC0ShaderProgram.setUniformi('texNoise', model.bufs.getNoiseTextureUnit(1));
renderPingPong(model.bufs, size, LIC0ShaderProgram); // backward LIC
shaderCache.readyShaderProgram(LICIShaderProgram);
LICIShaderProgram.setUniformi('uPassNo', 1);
LICIShaderProgram.setUniformf('uStepSize', -stepSize);
LICIShaderProgram.setUniformi('texNoise', model.bufs.getNoiseTextureUnit(1));
var nSteps = model.numberOfSteps / 2;
for (var _stepIdx2 = 0; _stepIdx2 < nSteps; ++_stepIdx2) {
setLICUniforms(LICIShaderProgram, model.bufs);
renderPingPong(model.bufs, size, LICIShaderProgram);
} // initialize seeds
shaderCache.readyShaderProgram(LIC0ShaderProgram);
LIC0ShaderProgram.setUniformi('uStepNo', 1);
setLICUniforms(LIC0ShaderProgram, model.bufs);
renderPingPong(model.bufs, size, LIC0ShaderProgram); // forward LIC
shaderCache.readyShaderProgram(LICIShaderProgram);
LICIShaderProgram.setUniformf('uStepSize', stepSize);
for (var _stepIdx3 = 0; _stepIdx3 < nSteps; ++_stepIdx3) {
setLICUniforms(LICIShaderProgram, model.bufs);
renderPingPong(model.bufs, size, LICIShaderProgram);
}
model.bufs.deactivateNoiseTexture(1);
model.bufs.deactivateVectorTextures(); // finalize LIC
shaderCache.readyShaderProgram(LICNShaderProgram);
LICNShaderProgram.setUniformi('texLIC', model.bufs.getLICTextureUnit());
LICNShaderProgram.setUniformi('texSeedPts', model.bufs.getSeedTextureUnit());
renderPingPong(model.bufs, size, LICNShaderProgram);
}
if (model.antiAlias) {
var AAHShaderProgram = model.AAHProgram;
shaderCache.readyShaderProgram(AAHShaderProgram);
AAHShaderProgram.setUniformi('texLIC', model.bufs.getLICTextureUnit());
AAHShaderProgram.setUniformf('uDx', dx);
var AAVShaderProgram = model.AAVProgram;
shaderCache.readyShaderProgram(AAVShaderProgram);
AAVShaderProgram.setUniformi('texLIC', model.bufs.getLICTextureUnit());
AAVShaderProgram.setUniformf('uDy', dy);
for (var i = 0; i < model.antiAlias; ++i) {
// Vertical pass
shaderCache.readyShaderProgram(AAHShaderProgram);
setLICUniforms(AAHShaderProgram, model.bufs);
renderPingPong(model.bufs, size, AAHShaderProgram); // Horizontal pass
shaderCache.readyShaderProgram(AAVShaderProgram);
setLICUniforms(AAVShaderProgram, model.bufs);
renderPingPong(model.bufs, size, AAVShaderProgram);
}
}
if (model.enhanceContrast === ContrastEnhanceMode.LIC || model.enhanceContrast === ContrastEnhanceMode.BOTH) {
publicAPI.contrastEnhance(true, size);
}
model.bufs.detachBuffers();
fb.restorePreviousBindingsAndBuffers();
return model.bufs.getLastLICBuffer();
};
publicAPI.contrastEnhance = function (isSecondStage, size) {
var shaderCache = model.openGLRenderWindow.getShaderCache();
var _publicAPI$getTexture = publicAPI.getTextureMinMax(model.bufs.getLastLICBuffer(), size, model.context, model.openGLRenderWindow),
min = _publicAPI$getTexture.min,
max = _publicAPI$getTexture.max;
if (max <= min || max > 1.0 || min < 0) {
console.error('Invalid color range: ', min, max);
min = 0.0;
max = 1.0;
}
var diff = max - min;
if (isSecondStage) {
min += diff * model.lowLICContrastEnhancementFactor;
max -= diff * model.highLICContrastEnhancementFactor;
diff = max - min;
}
var CEProgram = model.CEProgram;
shaderCache.readyShaderProgram(CEProgram);
CEProgram.setUniformi('texLIC', model.bufs.getLICTextureUnit());
CEProgram.setUniformf('uMin', min);
CEProgram.setUniformf('uMaxMinDiff', diff);
renderPingPong(model.bufs, size, CEProgram);
};
}
var DEFAULT_VALUES = {
shadersNeedBuild: true,
stepSize: 1,
numberOfSteps: 10,
enhancedLIC: true,
enhanceContrast: false,
lowContrastEnhancementFactor: 0,
highContrastEnhancementFactor: 0,
antiAlias: 0,
componentIds: [0, 1],
normalizeVectors: true,
maskThreshold: 0.0,
transformVectors: true,
bufs: null,
isComposite: true
};
function extend(publicAPI, model) {
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model);
macro.setGet(publicAPI, model, ['context', 'openGLRenderWindow', 'nuberOfSteps', 'stepSize', 'normalizeVectors', 'maskThreshold', 'enhancedLIC', 'enhanceContrast', 'lowLICContrastEnhancementFactor', 'highLICContrastEnhancementFactor', 'antiAlias', 'componentIds', 'isComposite']); // Object methods
vtkLineIntegralConvolution2D(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = macro.newInstance(extend, 'vtkLineIntegralConvolution2D');
var vtkLineIntegralConvolution2D$1 = {
newInstance: newInstance,
extend: extend
};
export default vtkLineIntegralConvolution2D$1;
export { extend, newInstance };