@kitware/vtk.js
Version:
Visualization Toolkit for the Web
193 lines (154 loc) • 8.9 kB
JavaScript
import { mat3, mat4 } from 'gl-matrix';
import { newInstance as newInstance$1, obj, setGet, get, vtkErrorMacro as vtkErrorMacro$1 } from '../../macros.js';
import vtkDataArray from '../../Common/Core/DataArray.js';
import vtkHelper from './Helper.js';
import vtkViewNode from '../SceneGraph/ViewNode.js';
import vtkOpenGLTexture from './Texture.js';
import { Representation } from '../Core/Property/Constants.js';
import { registerOverride } from './ViewNodeFactory.js';
var vtkErrorMacro = vtkErrorMacro$1; // ----------------------------------------------------------------------------
// vtkOpenGLSkybox methods
// ----------------------------------------------------------------------------
function vtkOpenGLSkybox(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkOpenGLSkybox'); // Builds myself.
publicAPI.buildPass = function (prepass) {
if (prepass) {
model._openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
model._openGLRenderWindow = model._openGLRenderer.getParent();
model.context = model._openGLRenderWindow.getContext();
model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
var ren = model._openGLRenderer.getRenderable();
model.openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera());
}
};
publicAPI.queryPass = function (prepass, renderPass) {
if (prepass) {
if (!model.renderable || !model.renderable.getVisibility()) {
return;
}
renderPass.incrementOpaqueActorCount();
}
};
publicAPI.opaquePass = function (prepass, renderPass) {
if (prepass && !model._openGLRenderer.getSelector()) {
publicAPI.updateBufferObjects();
model.context.depthMask(true);
model._openGLRenderWindow.getShaderCache().readyShaderProgram(model.tris.getProgram());
model.openGLTexture.render(model._openGLRenderWindow);
var texUnit = model.openGLTexture.getTextureUnit();
model.tris.getProgram().setUniformi('sbtexture', texUnit);
var ren = model._openGLRenderer.getRenderable();
var keyMats = model.openGLCamera.getKeyMatrices(ren);
var imat = new Float64Array(16);
mat4.invert(imat, keyMats.wcpc);
model.tris.getProgram().setUniformMatrix('IMCPCMatrix', imat);
if (model.lastFormat === 'box') {
var camPos = ren.getActiveCamera().getPosition();
model.tris.getProgram().setUniform3f('camPos', camPos[0], camPos[1], camPos[2]);
}
model.tris.getVAO().bind(); // draw polygons
model.context.drawArrays(model.context.TRIANGLES, 0, model.tris.getCABO().getElementCount());
model.tris.getVAO().release();
model.openGLTexture.deactivate();
}
};
publicAPI.updateBufferObjects = function () {
// build the VBO if needed, only happens once
if (!model.tris.getCABO().getElementCount()) {
var ptsArray = new Float32Array(12);
for (var i = 0; i < 4; i++) {
ptsArray[i * 3] = i % 2 * 2 - 1.0;
ptsArray[i * 3 + 1] = i > 1 ? 1.0 : -1.0;
ptsArray[i * 3 + 2] = 1.0;
}
var points = vtkDataArray.newInstance({
numberOfComponents: 3,
values: ptsArray
});
points.setName('points');
var cellArray = new Uint16Array(8);
cellArray[0] = 3;
cellArray[1] = 0;
cellArray[2] = 1;
cellArray[3] = 3;
cellArray[4] = 3;
cellArray[5] = 0;
cellArray[6] = 3;
cellArray[7] = 2;
var cells = vtkDataArray.newInstance({
numberOfComponents: 1,
values: cellArray
});
model.tris.getCABO().createVBO(cells, 'polys', Representation.SURFACE, {
points: points,
cellOffset: 0
});
} // update the program?
if (model.renderable.getFormat() !== model.lastFormat) {
model.lastFormat = model.renderable.getFormat();
if (model.lastFormat === 'box') {
// we invert Y below because opengl is messed up!
// Cube Maps have been specified to follow the RenderMan
// specification (for whatever reason), and RenderMan
// assumes the images' origin being in the upper left,
// contrary to the usual OpenGL behaviour of having the
// image origin in the lower left. That's why things get
// swapped in the Y direction. It totally breaks with the usual
// OpenGL semantics and doesn't make sense at all.
// But now we're stuck with it. From
// https://stackoverflow.com/questions/11685608/convention-of-faces-in-opengl-cubemapping
//
model.tris.setProgram(model._openGLRenderWindow.getShaderCache().readyShaderProgramArray("//VTK::System::Dec\n attribute vec3 vertexMC;\n uniform mat4 IMCPCMatrix;\n varying vec3 TexCoords;\n void main () {\n gl_Position = vec4(vertexMC.xyz, 1.0);\n vec4 wpos = IMCPCMatrix * gl_Position;\n TexCoords = wpos.xyz/wpos.w;\n }", "//VTK::System::Dec\n //VTK::Output::Dec\n varying vec3 TexCoords;\n uniform samplerCube sbtexture;\n uniform vec3 camPos;\n void main () {\n // skybox looks from inside out\n // which means we have to adjust\n // our tcoords. Otherwise text would\n // be flipped\n vec3 tc = normalize(TexCoords - camPos);\n if (abs(tc.z) < max(abs(tc.x),abs(tc.y)))\n {\n tc = vec3(1.0, 1.0, -1.0) * tc;\n }\n else\n {\n tc = vec3(-1.0, 1.0, 1.0) * tc;\n }\n gl_FragData[0] = textureCube(sbtexture, tc);\n }", ''));
}
if (model.lastFormat === 'background') {
// maps the texture to the window
model.tris.setProgram(model._openGLRenderWindow.getShaderCache().readyShaderProgramArray("//VTK::System::Dec\n attribute vec3 vertexMC;\n uniform mat4 IMCPCMatrix;\n varying vec2 TexCoords;\n void main () {\n gl_Position = vec4(vertexMC.xyz, 1.0);\n vec4 wpos = IMCPCMatrix * gl_Position;\n TexCoords = vec2(vertexMC.x, vertexMC.y)*0.5 + 0.5;\n }", "//VTK::System::Dec\n //VTK::Output::Dec\n varying vec2 TexCoords;\n uniform sampler2D sbtexture;\n void main () {\n gl_FragData[0] = texture2D(sbtexture, TexCoords);\n }", ''));
}
model.tris.getShaderSourceTime().modified();
model.tris.getVAO().bind();
if (!model.tris.getVAO().addAttributeArray(model.tris.getProgram(), model.tris.getCABO(), 'vertexMC', model.tris.getCABO().getVertexOffset(), model.tris.getCABO().getStride(), model.context.FLOAT, 3, model.context.FALSE)) {
vtkErrorMacro('Error setting vertexMC in shader VAO.');
}
} // set/update the texture map if needed
var tmaps = model.renderable.getTextures();
if (!tmaps.length) {
vtkErrorMacro('vtkSkybox requires a texture map');
}
if (model.openGLTexture.getRenderable() !== tmaps[0]) {
model.openGLTexture.releaseGraphicsResources(model._openGLRenderWindow);
model.openGLTexture.setRenderable(tmaps[0]);
}
};
} // ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
var DEFAULT_VALUES = {
context: null
}; // ----------------------------------------------------------------------------
function extend(publicAPI, model) {
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance
vtkViewNode.extend(publicAPI, model, initialValues);
model.openGLTexture = vtkOpenGLTexture.newInstance();
model.tris = vtkHelper.newInstance();
model.keyMatrixTime = {};
obj(model.keyMatrixTime, {
mtime: 0
});
model.keyMatrices = {
normalMatrix: mat3.identity(new Float64Array(9)),
mcwc: mat4.identity(new Float64Array(16))
}; // Build VTK API
setGet(publicAPI, model, ['context']);
get(publicAPI, model, ['activeTextures']); // Object methods
vtkOpenGLSkybox(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = newInstance$1(extend); // ----------------------------------------------------------------------------
var vtkSkybox = {
newInstance: newInstance,
extend: extend
}; // Register ourself to OpenGL backend if imported
registerOverride('vtkSkybox', newInstance);
export { vtkSkybox as default, extend, newInstance };