@thewtex/vtk.js-esm
Version:
Visualization Toolkit for the Web
984 lines (795 loc) • 61.2 kB
JavaScript
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import { i as identity, b as mat3 } from '../../vendor/gl-matrix/esm/mat3.js';
import { i as identity$1, j as transpose, q as mat4 } from '../../vendor/gl-matrix/esm/mat4.js';
import { t as transformMat4 } from '../../vendor/gl-matrix/esm/vec3.js';
import { setGet, obj, newInstance as newInstance$1, vtkErrorMacro as vtkErrorMacro$1 } from '../../macro.js';
import vtkHelper from './Helper.js';
import vtkMapper from '../Core/Mapper.js';
import { l as normalize, u as uninitializeBounds } from '../../Common/Core/Math/index.js';
import vtkOpenGLTexture from './Texture.js';
import vtkProperty from '../Core/Property.js';
import vtkShaderProgram from './ShaderProgram.js';
import vtkViewNode from '../SceneGraph/ViewNode.js';
import { v as vtkPolyDataVS } from './glsl/vtkPolyDataVS.glsl.js';
import { v as vtkPolyDataFS } from './glsl/vtkPolyDataFS.glsl.js';
import vtkReplacementShaderMapper from './ReplacementShaderMapper.js';
import { registerOverride } from './ViewNodeFactory.js';
/* eslint-disable no-lonely-if */
var primTypes = {
Start: 0,
Points: 0,
Lines: 1,
Tris: 2,
TriStrips: 3,
TrisEdges: 4,
TriStripsEdges: 5,
End: 6
};
var Representation = vtkProperty.Representation,
Shading = vtkProperty.Shading;
var ScalarMode = vtkMapper.ScalarMode;
var Filter = vtkOpenGLTexture.Filter,
Wrap = vtkOpenGLTexture.Wrap;
var vtkErrorMacro = vtkErrorMacro$1;
var StartEvent = {
type: 'StartEvent'
};
var EndEvent = {
type: 'EndEvent'
}; // ----------------------------------------------------------------------------
// vtkOpenGLPolyDataMapper methods
// ----------------------------------------------------------------------------
function vtkOpenGLPolyDataMapper(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkOpenGLPolyDataMapper');
publicAPI.buildPass = function (prepass) {
if (prepass) {
model.openGLActor = publicAPI.getFirstAncestorOfType('vtkOpenGLActor');
model.openGLRenderer = model.openGLActor.getFirstAncestorOfType('vtkOpenGLRenderer');
model.openGLRenderWindow = model.openGLRenderer.getParent();
model.openGLCamera = model.openGLRenderer.getViewNodeFor(model.openGLRenderer.getRenderable().getActiveCamera());
}
}; // Renders myself
publicAPI.translucentPass = function (prepass) {
if (prepass) {
publicAPI.render();
}
};
publicAPI.opaqueZBufferPass = function (prepass) {
if (prepass) {
model.haveSeenDepthRequest = true;
model.renderDepth = true;
publicAPI.render();
model.renderDepth = false;
}
};
publicAPI.opaquePass = function (prepass) {
if (prepass) {
publicAPI.render();
}
};
publicAPI.render = function () {
var ctx = model.openGLRenderWindow.getContext();
if (model.context !== ctx) {
model.context = ctx;
for (var i = primTypes.Start; i < primTypes.End; i++) {
model.primitives[i].setOpenGLRenderWindow(model.openGLRenderWindow);
}
}
var actor = model.openGLActor.getRenderable();
var ren = model.openGLRenderer.getRenderable();
publicAPI.renderPiece(ren, actor);
};
publicAPI.buildShaders = function (shaders, ren, actor) {
publicAPI.getShaderTemplate(shaders, ren, actor); // user specified pre replacements
var openGLSpec = model.renderable.getViewSpecificProperties().OpenGL;
var shaderReplacements = null;
if (openGLSpec) {
shaderReplacements = openGLSpec.ShaderReplacements;
}
if (shaderReplacements) {
for (var i = 0; i < shaderReplacements.length; i++) {
var currReplacement = shaderReplacements[i];
if (currReplacement.replaceFirst) {
var shaderType = currReplacement.shaderType;
var ssrc = shaders[shaderType];
var substituteRes = vtkShaderProgram.substitute(ssrc, currReplacement.originalValue, currReplacement.replacementValue, currReplacement.replaceAll);
shaders[shaderType] = substituteRes.result;
}
}
}
publicAPI.replaceShaderValues(shaders, ren, actor); // user specified post replacements
if (shaderReplacements) {
for (var _i = 0; _i < shaderReplacements.length; _i++) {
var _currReplacement = shaderReplacements[_i];
if (!_currReplacement.replaceFirst) {
var _shaderType = _currReplacement.shaderType;
var _ssrc = shaders[_shaderType];
var _substituteRes = vtkShaderProgram.substitute(_ssrc, _currReplacement.originalValue, _currReplacement.replacementValue, _currReplacement.replaceAll);
shaders[_shaderType] = _substituteRes.result;
}
}
}
};
publicAPI.getShaderTemplate = function (shaders, ren, actor) {
var openGLSpecProp = model.renderable.getViewSpecificProperties().OpenGL;
var vertexShaderCode = vtkPolyDataVS;
if (openGLSpecProp) {
var vertexSpecProp = openGLSpecProp.VertexShaderCode;
if (vertexSpecProp !== undefined && vertexSpecProp !== '') {
vertexShaderCode = vertexSpecProp;
}
}
shaders.Vertex = vertexShaderCode;
var fragmentShaderCode = vtkPolyDataFS;
if (openGLSpecProp) {
var fragmentSpecProp = openGLSpecProp.FragmentShaderCode;
if (fragmentSpecProp !== undefined && fragmentSpecProp !== '') {
fragmentShaderCode = fragmentSpecProp;
}
}
shaders.Fragment = fragmentShaderCode;
var geometryShaderCode = '';
if (openGLSpecProp) {
var geometrySpecProp = openGLSpecProp.GeometryShaderCode;
if (geometrySpecProp !== undefined) {
geometryShaderCode = geometrySpecProp;
}
}
shaders.Geometry = geometryShaderCode;
};
publicAPI.replaceShaderColor = function (shaders, ren, actor) {
var VSSource = shaders.Vertex;
var GSSource = shaders.Geometry;
var FSSource = shaders.Fragment;
var lastLightComplexity = model.lastBoundBO.getReferenceByName('lastLightComplexity'); // create the material/color property declarations, and VS implementation
// these are always defined
var colorDec = ['uniform float ambient;', 'uniform float diffuse;', 'uniform float specular;', 'uniform float opacityUniform; // the fragment opacity', 'uniform vec3 ambientColorUniform;', 'uniform vec3 diffuseColorUniform;']; // add more for specular
if (lastLightComplexity) {
colorDec = colorDec.concat(['uniform vec3 specularColorUniform;', 'uniform float specularPowerUniform;']);
} // now handle the more complex fragment shader implementation
// the following are always defined variables. We start
// by assigning a default value from the uniform
var colorImpl = ['vec3 ambientColor;', ' vec3 diffuseColor;', ' float opacity;'];
if (lastLightComplexity) {
colorImpl = colorImpl.concat([' vec3 specularColor;', ' float specularPower;']);
}
colorImpl = colorImpl.concat([' ambientColor = ambientColorUniform;', ' diffuseColor = diffuseColorUniform;', ' opacity = opacityUniform;']);
if (lastLightComplexity) {
colorImpl = colorImpl.concat([' specularColor = specularColorUniform;', ' specularPower = specularPowerUniform;']);
} // add scalar vertex coloring
if (model.lastBoundBO.getCABO().getColorComponents() !== 0 && !model.drawingEdges) {
colorDec = colorDec.concat(['varying vec4 vertexColorVSOutput;']);
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Color::Dec', ['attribute vec4 scalarColor;', 'varying vec4 vertexColorVSOutput;']).result;
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Color::Impl', ['vertexColorVSOutput = scalarColor;']).result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::Color::Dec', ['in vec4 vertexColorVSOutput[];', 'out vec4 vertexColorGSOutput;']).result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::Color::Impl', ['vertexColorGSOutput = vertexColorVSOutput[i];']).result;
}
if (model.lastBoundBO.getCABO().getColorComponents() !== 0 && !model.drawingEdges) {
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Impl', colorImpl.concat([' diffuseColor = vertexColorVSOutput.rgb;', ' ambientColor = vertexColorVSOutput.rgb;', ' opacity = opacity*vertexColorVSOutput.a;'])).result;
} else {
if (model.renderable.getInterpolateScalarsBeforeMapping() && model.renderable.getColorCoordinates() && !model.drawingEdges) {
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Impl', colorImpl.concat([' vec4 texColor = texture2D(texture1, tcoordVCVSOutput.st);', ' diffuseColor = texColor.rgb;', ' ambientColor = texColor.rgb;', ' opacity = opacity*texColor.a;'])).result;
} else {
if (actor.getBackfaceProperty() && !model.drawingEdges) {
colorDec = colorDec.concat(['uniform float opacityUniformBF; // the fragment opacity', 'uniform float ambientIntensityBF; // the material ambient', 'uniform float diffuseIntensityBF; // the material diffuse', 'uniform vec3 ambientColorUniformBF; // ambient material color', 'uniform vec3 diffuseColorUniformBF; // diffuse material color']);
if (lastLightComplexity) {
colorDec = colorDec.concat(['uniform float specularIntensityBF; // the material specular intensity', 'uniform vec3 specularColorUniformBF; // intensity weighted color', 'uniform float specularPowerUniformBF;']);
colorImpl = colorImpl.concat(['if (gl_FrontFacing == false) {', ' ambientColor = ambientIntensityBF * ambientColorUniformBF;', ' diffuseColor = diffuseIntensityBF * diffuseColorUniformBF;', ' specularColor = specularIntensityBF * specularColorUniformBF;', ' specularPower = specularPowerUniformBF;', ' opacity = opacityUniformBF; }']);
} else {
colorImpl = colorImpl.concat(['if (gl_FrontFacing == false) {', ' ambientColor = ambientIntensityBF * ambientColorUniformBF;', ' diffuseColor = diffuseIntensityBF * diffuseColorUniformBF;', ' opacity = opacityUniformBF; }']);
}
}
if (model.haveCellScalars && !model.drawingEdges) {
colorDec = colorDec.concat(['uniform samplerBuffer texture1;']);
}
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Impl', colorImpl).result;
}
}
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Dec', colorDec).result;
shaders.Vertex = VSSource;
shaders.Geometry = GSSource;
shaders.Fragment = FSSource;
};
publicAPI.replaceShaderLight = function (shaders, ren, actor) {
var FSSource = shaders.Fragment; // check for shadow maps
var shadowFactor = '';
var lastLightComplexity = model.lastBoundBO.getReferenceByName('lastLightComplexity');
var lastLightCount = model.lastBoundBO.getReferenceByName('lastLightCount');
var sstring = [];
switch (lastLightComplexity) {
case 0:
// no lighting or RENDER_VALUES
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Light::Impl', [' gl_FragData[0] = vec4(ambientColor * ambient + diffuseColor * diffuse, opacity);', ' //VTK::Light::Impl'], false).result;
break;
case 1:
// headlight
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Light::Impl', [' float df = max(0.0, normalVCVSOutput.z);', ' float sf = pow(df, specularPower);', ' vec3 diffuseL = df * diffuseColor;', ' vec3 specularL = sf * specularColor;', ' gl_FragData[0] = vec4(ambientColor * ambient + diffuseL * diffuse + specularL * specular, opacity);', ' //VTK::Light::Impl'], false).result;
break;
case 2:
// light kit
for (var lc = 0; lc < lastLightCount; ++lc) {
sstring = sstring.concat(["uniform vec3 lightColor".concat(lc, ";"), "uniform vec3 lightDirectionVC".concat(lc, "; // normalized"), "uniform vec3 lightHalfAngleVC".concat(lc, "; // normalized")]);
}
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Light::Dec', sstring).result;
sstring = ['vec3 diffuseL = vec3(0,0,0);', ' vec3 specularL = vec3(0,0,0);', ' float df;'];
for (var _lc = 0; _lc < lastLightCount; ++_lc) {
sstring = sstring.concat([" df = max(0.0, dot(normalVCVSOutput, -lightDirectionVC".concat(_lc, "));"), " diffuseL += ((df".concat(shadowFactor, ") * lightColor").concat(_lc, ");"), " if (dot(normalVCVSOutput, lightDirectionVC".concat(_lc, ") < 0.0)"), ' {', " float sf = pow( max(0.0, dot(lightHalfAngleVC".concat(_lc, ",normalVCVSOutput)), specularPower);"), " specularL += ((sf".concat(shadowFactor, ") * lightColor").concat(_lc, ");"), ' }']);
}
sstring = sstring.concat([' diffuseL = diffuseL * diffuseColor;', ' specularL = specularL * specularColor;', ' gl_FragData[0] = vec4(ambientColor * ambient + diffuseL * diffuse + specularL * specular, opacity);', ' //VTK::Light::Impl']);
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Light::Impl', sstring, false).result;
break;
case 3:
// positional
for (var _lc2 = 0; _lc2 < lastLightCount; ++_lc2) {
sstring = sstring.concat(["uniform vec3 lightColor".concat(_lc2, ";"), "uniform vec3 lightDirectionVC".concat(_lc2, "; // normalized"), "uniform vec3 lightHalfAngleVC".concat(_lc2, "; // normalized"), "uniform vec3 lightPositionVC".concat(_lc2, ";"), "uniform vec3 lightAttenuation".concat(_lc2, ";"), "uniform float lightConeAngle".concat(_lc2, ";"), "uniform float lightExponent".concat(_lc2, ";"), "uniform int lightPositional".concat(_lc2, ";")]);
}
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Light::Dec', sstring).result;
sstring = ['vec3 diffuseL = vec3(0,0,0);', ' vec3 specularL = vec3(0,0,0);', ' vec3 vertLightDirectionVC;', ' float attenuation;', ' float df;'];
for (var _lc3 = 0; _lc3 < lastLightCount; ++_lc3) {
sstring = sstring.concat([' attenuation = 1.0;', " if (lightPositional".concat(_lc3, " == 0)"), ' {', " vertLightDirectionVC = lightDirectionVC".concat(_lc3, ";"), ' }', ' else', ' {', " vertLightDirectionVC = vertexVC.xyz - lightPositionVC".concat(_lc3, ";"), ' float distanceVC = length(vertLightDirectionVC);', ' vertLightDirectionVC = normalize(vertLightDirectionVC);', ' attenuation = 1.0 /', " (lightAttenuation".concat(_lc3, ".x"), " + lightAttenuation".concat(_lc3, ".y * distanceVC"), " + lightAttenuation".concat(_lc3, ".z * distanceVC * distanceVC);"), ' // per OpenGL standard cone angle is 90 or less for a spot light', " if (lightConeAngle".concat(_lc3, " <= 90.0)"), ' {', " float coneDot = dot(vertLightDirectionVC, lightDirectionVC".concat(_lc3, ");"), ' // if inside the cone', " if (coneDot >= cos(radians(lightConeAngle".concat(_lc3, ")))"), ' {', " attenuation = attenuation * pow(coneDot, lightExponent".concat(_lc3, ");"), ' }', ' else', ' {', ' attenuation = 0.0;', ' }', ' }', ' }', ' df = max(0.0, attenuation*dot(normalVCVSOutput, -vertLightDirectionVC));', " diffuseL += ((df".concat(shadowFactor, ") * lightColor").concat(_lc3, ");"), ' if (dot(normalVCVSOutput, vertLightDirectionVC) < 0.0)', ' {', " float sf = attenuation*pow( max(0.0, dot(lightHalfAngleVC".concat(_lc3, ",normalVCVSOutput)), specularPower);"), " specularL += ((sf".concat(shadowFactor, ") * lightColor").concat(_lc3, ");"), ' }']);
}
sstring = sstring.concat([' diffuseL = diffuseL * diffuseColor;', ' specularL = specularL * specularColor;', ' gl_FragData[0] = vec4(ambientColor * ambient + diffuseL * diffuse + specularL * specular, opacity);', ' //VTK::Light::Impl']);
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Light::Impl', sstring, false).result;
break;
default:
vtkErrorMacro('bad light complexity');
}
shaders.Fragment = FSSource;
};
publicAPI.replaceShaderNormal = function (shaders, ren, actor) {
var lastLightComplexity = model.lastBoundBO.getReferenceByName('lastLightComplexity');
if (lastLightComplexity > 0) {
var VSSource = shaders.Vertex;
var GSSource = shaders.Geometry;
var FSSource = shaders.Fragment;
if (model.lastBoundBO.getCABO().getNormalOffset()) {
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Normal::Dec', ['attribute vec3 normalMC;', 'uniform mat3 normalMatrix;', 'varying vec3 normalVCVSOutput;']).result;
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Normal::Impl', ['normalVCVSOutput = normalMatrix * normalMC;']).result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::Normal::Dec', ['in vec3 normalVCVSOutput[];', 'out vec3 normalVCGSOutput;']).result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::Normal::Impl', ['normalVCGSOutput = normalVCVSOutput[i];']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Normal::Dec', ['varying vec3 normalVCVSOutput;']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Normal::Impl', ['vec3 normalVCVSOutput = normalize(normalVCVSOutput);', // if (!gl_FrontFacing) does not work in intel hd4000 mac
// if (int(gl_FrontFacing) == 0) does not work on mesa
' if (gl_FrontFacing == false) { normalVCVSOutput = -normalVCVSOutput; }']).result;
} else {
if (model.haveCellNormals) {
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Normal::Dec', ['uniform mat3 normalMatrix;', 'uniform samplerBuffer textureN;']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Normal::Impl', ['vec3 normalVCVSOutput = normalize(normalMatrix *', ' texelFetchBuffer(textureN, gl_PrimitiveID + PrimitiveIDOffset).xyz);', ' if (gl_FrontFacing == false) { normalVCVSOutput = -normalVCVSOutput; }']).result;
} else {
if (publicAPI.getOpenGLMode(actor.getProperty().getRepresentation(), model.lastBoundBO.getPrimitiveType()) === model.context.LINES) {
// generate a normal for lines, it will be perpendicular to the line
// and maximally aligned with the camera view direction
// no clue if this is the best way to do this.
// the code below has been optimized a bit so what follows is
// an explanation of the basic approach. Compute the gradient of the line
// with respect to x and y, the the larger of the two
// cross that with the camera view direction. That gives a vector
// orthogonal to the camera view and the line. Note that the line and the camera
// view are probably not orthogonal. Which is why when we cross result that with
// the line gradient again we get a reasonable normal. It will be othogonal to
// the line (which is a plane but maximally aligned with the camera view.
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::UniformFlow::Impl', [' vec3 fdx = vec3(dFdx(vertexVC.x),dFdx(vertexVC.y),dFdx(vertexVC.z));', ' vec3 fdy = vec3(dFdy(vertexVC.x),dFdy(vertexVC.y),dFdy(vertexVC.z));', ' //VTK::UniformFlow::Impl'] // For further replacements
).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Normal::Impl', ['vec3 normalVCVSOutput;', ' fdx = normalize(fdx);', ' fdy = normalize(fdy);', ' if (abs(fdx.x) > 0.0)', ' { normalVCVSOutput = normalize(cross(vec3(fdx.y, -fdx.x, 0.0), fdx)); }', ' else { normalVCVSOutput = normalize(cross(vec3(fdy.y, -fdy.x, 0.0), fdy));}']).result;
} else {
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Normal::Dec', ['uniform int cameraParallel;']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::UniformFlow::Impl', [// ' vec3 fdx = vec3(dFdx(vertexVC.x),dFdx(vertexVC.y),dFdx(vertexVC.z));',
// ' vec3 fdy = vec3(dFdy(vertexVC.x),dFdy(vertexVC.y),dFdy(vertexVC.z));',
' vec3 fdx = dFdx(vertexVC.xyz);', ' vec3 fdy = dFdy(vertexVC.xyz);', ' //VTK::UniformFlow::Impl'] // For further replacements
).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Normal::Impl', [' fdx = normalize(fdx);', ' fdy = normalize(fdy);', ' vec3 normalVCVSOutput = normalize(cross(fdx,fdy));', // the code below is faster, but does not work on some devices
// 'vec3 normalVC = normalize(cross(dFdx(vertexVC.xyz), dFdy(vertexVC.xyz)));',
' if (cameraParallel == 1 && normalVCVSOutput.z < 0.0) { normalVCVSOutput = -1.0*normalVCVSOutput; }', ' if (cameraParallel == 0 && dot(normalVCVSOutput,vertexVC.xyz) > 0.0) { normalVCVSOutput = -1.0*normalVCVSOutput; }']).result;
}
}
}
shaders.Vertex = VSSource;
shaders.Geometry = GSSource;
shaders.Fragment = FSSource;
}
};
publicAPI.replaceShaderPositionVC = function (shaders, ren, actor) {
var VSSource = shaders.Vertex;
var GSSource = shaders.Geometry;
var FSSource = shaders.Fragment; // for points make sure to add in the point size
if (actor.getProperty().getRepresentation() === Representation.POINTS || model.lastBoundBO.getPrimitiveType() === primTypes.Points) {
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::PositionVC::Impl', ['//VTK::PositionVC::Impl', " gl_PointSize = ".concat(actor.getProperty().getPointSize(), ".0;")], false).result;
} // do we need the vertex in the shader in View Coordinates
var lastLightComplexity = model.lastBoundBO.getReferenceByName('lastLightComplexity');
if (lastLightComplexity > 0) {
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::PositionVC::Dec', ['varying vec4 vertexVCVSOutput;']).result;
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::PositionVC::Impl', ['vertexVCVSOutput = MCVCMatrix * vertexMC;', ' gl_Position = MCPCMatrix * vertexMC;']).result;
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Camera::Dec', ['uniform mat4 MCPCMatrix;', 'uniform mat4 MCVCMatrix;']).result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::PositionVC::Dec', ['in vec4 vertexVCVSOutput[];', 'out vec4 vertexVCGSOutput;']).result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::PositionVC::Impl', ['vertexVCGSOutput = vertexVCVSOutput[i];']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::PositionVC::Dec', ['varying vec4 vertexVCVSOutput;']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::PositionVC::Impl', ['vec4 vertexVC = vertexVCVSOutput;']).result;
} else {
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Camera::Dec', ['uniform mat4 MCPCMatrix;']).result;
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::PositionVC::Impl', [' gl_Position = MCPCMatrix * vertexMC;']).result;
}
shaders.Vertex = VSSource;
shaders.Geometry = GSSource;
shaders.Fragment = FSSource;
};
publicAPI.replaceShaderTCoord = function (shaders, ren, actor) {
if (model.lastBoundBO.getCABO().getTCoordOffset()) {
var VSSource = shaders.Vertex;
var GSSource = shaders.Geometry;
var FSSource = shaders.Fragment;
if (model.drawingEdges) {
return;
}
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Impl', 'tcoordVCVSOutput = tcoordMC;').result; // we only handle the first texture by default
// additional textures are activated and we set the uniform
// for the texture unit they are assigned to, but you have to
// add in the shader code to do something with them
var tus = model.openGLActor.getActiveTextures();
var tNumComp = 2;
var tcdim = 2;
if (tus && tus.length > 0) {
tNumComp = tus[0].getComponents();
if (tus[0].getTarget() === model.context.TEXTURE_CUBE_MAP) {
tcdim = 3;
}
}
if (model.renderable.getColorTextureMap()) {
tNumComp = model.renderable.getColorTextureMap().getPointData().getScalars().getNumberOfComponents();
tcdim = 2;
}
if (tcdim === 2) {
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Dec', 'attribute vec2 tcoordMC; varying vec2 tcoordVCVSOutput;').result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::TCoord::Dec', ['in vec2 tcoordVCVSOutput[];', 'out vec2 tcoordVCGSOutput;']).result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::TCoord::Impl', 'tcoordVCGSOutput = tcoordVCVSOutput[i];').result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Dec', ['varying vec2 tcoordVCVSOutput;', 'uniform sampler2D texture1;']).result;
if (tus && tus.length >= 1) {
switch (tNumComp) {
case 1:
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', ['vec4 tcolor = texture2D(texture1, tcoordVCVSOutput);', 'gl_FragData[0] = clamp(gl_FragData[0],0.0,1.0)*', ' vec4(tcolor.r,tcolor.r,tcolor.r,1.0);']).result;
break;
case 2:
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', ['vec4 tcolor = texture2D(texture1, tcoordVCVSOutput);', 'gl_FragData[0] = clamp(gl_FragData[0],0.0,1.0)*', ' vec4(tcolor.r,tcolor.r,tcolor.r,tcolor.g);']).result;
break;
default:
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', 'gl_FragData[0] = clamp(gl_FragData[0],0.0,1.0)*texture2D(texture1, tcoordVCVSOutput.st);').result;
}
}
} else {
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Dec', 'attribute vec3 tcoordMC; varying vec3 tcoordVCVSOutput;').result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::TCoord::Dec', ['in vec3 tcoordVCVSOutput[];', 'out vec3 tcoordVCGSOutput;']).result;
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::TCoord::Impl', 'tcoordVCGSOutput = tcoordVCVSOutput[i];').result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Dec', ['varying vec3 tcoordVCVSOutput;', 'uniform samplerCube texture1;']).result;
switch (tNumComp) {
case 1:
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', ['vec4 tcolor = textureCube(texture1, tcoordVCVSOutput);', 'gl_FragData[0] = clamp(gl_FragData[0],0.0,1.0)*', ' vec4(tcolor.r,tcolor.r,tcolor.r,1.0);']).result;
break;
case 2:
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', ['vec4 tcolor = textureCube(texture1, tcoordVCVSOutput);', 'gl_FragData[0] = clamp(gl_FragData[0],0.0,1.0)*', ' vec4(tcolor.r,tcolor.r,tcolor.r,tcolor.g);']).result;
break;
default:
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', 'gl_FragData[0] = clamp(gl_FragData[0],0.0,1.0)*textureCube(texture1, tcoordVCVSOutput);').result;
}
}
shaders.Vertex = VSSource;
shaders.Geometry = GSSource;
shaders.Fragment = FSSource;
}
};
publicAPI.replaceShaderClip = function (shaders, ren, actor) {
var VSSource = shaders.Vertex;
var FSSource = shaders.Fragment;
if (model.renderable.getNumberOfClippingPlanes()) {
var numClipPlanes = model.renderable.getNumberOfClippingPlanes();
if (numClipPlanes > 6) {
vtkErrorMacro$1('OpenGL has a limit of 6 clipping planes');
numClipPlanes = 6;
}
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Clip::Dec', ['uniform int numClipPlanes;', 'uniform vec4 clipPlanes[6];', 'varying float clipDistancesVSOutput[6];']).result;
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Clip::Impl', ['for (int planeNum = 0; planeNum < 6; planeNum++)', ' {', ' if (planeNum >= numClipPlanes)', ' {', ' break;', ' }', ' clipDistancesVSOutput[planeNum] = dot(clipPlanes[planeNum], vertexMC);', ' }']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Clip::Dec', ['uniform int numClipPlanes;', 'varying float clipDistancesVSOutput[6];']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Clip::Impl', ['for (int planeNum = 0; planeNum < 6; planeNum++)', ' {', ' if (planeNum >= numClipPlanes)', ' {', ' break;', ' }', ' if (clipDistancesVSOutput[planeNum] < 0.0) discard;', ' }']).result;
}
shaders.Vertex = VSSource;
shaders.Fragment = FSSource;
};
publicAPI.getCoincidentParameters = function (ren, actor) {
// 1. ResolveCoincidentTopology is On and non zero for this primitive
// type
var cp = null;
var prop = actor.getProperty();
if (model.renderable.getResolveCoincidentTopology() || prop.getEdgeVisibility() && prop.getRepresentation() === Representation.SURFACE) {
var primType = model.lastBoundBO.getPrimitiveType();
if (primType === primTypes.Points || prop.getRepresentation() === Representation.POINTS) {
cp = model.renderable.getCoincidentTopologyPointOffsetParameter();
} else if (primType === primTypes.Lines || prop.getRepresentation() === Representation.WIREFRAME) {
cp = model.renderable.getCoincidentTopologyLineOffsetParameters();
} else if (primType === primTypes.Tris || primType === primTypes.TriStrips) {
cp = model.renderable.getCoincidentTopologyPolygonOffsetParameters();
}
if (primType === primTypes.TrisEdges || primType === primTypes.TriStripsEdges) {
cp = model.renderable.getCoincidentTopologyPolygonOffsetParameters();
cp.factor /= 2.0;
cp.offset /= 2.0;
}
} // hardware picking always offset due to saved zbuffer
// This gets you above the saved surface depth buffer.
// vtkHardwareSelector* selector = ren->GetSelector();
// if (selector &&
// selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
// {
// offset -= 2.0;
// return;
// }
return cp;
};
publicAPI.replaceShaderPicking = function (shaders, ren, actor) {
var FSSource = shaders.Fragment;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Picking::Dec', ['uniform vec3 mapperIndex;', 'uniform int picking;']).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Picking::Impl', ' gl_FragData[0] = picking != 0 ? vec4(mapperIndex,1.0) : gl_FragData[0];').result;
shaders.Fragment = FSSource;
};
publicAPI.replaceShaderValues = function (shaders, ren, actor) {
publicAPI.replaceShaderColor(shaders, ren, actor);
publicAPI.replaceShaderNormal(shaders, ren, actor);
publicAPI.replaceShaderLight(shaders, ren, actor);
publicAPI.replaceShaderTCoord(shaders, ren, actor);
publicAPI.replaceShaderPicking(shaders, ren, actor);
publicAPI.replaceShaderClip(shaders, ren, actor);
publicAPI.replaceShaderCoincidentOffset(shaders, ren, actor);
publicAPI.replaceShaderPositionVC(shaders, ren, actor);
if (model.haveSeenDepthRequest) {
var FSSource = shaders.Fragment;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Dec', 'uniform int depthRequest;').result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Impl', ['if (depthRequest == 1) {', 'float iz = floor(gl_FragCoord.z*65535.0 + 0.1);', 'float rf = floor(iz/256.0)/255.0;', 'float gf = mod(iz,256.0)/255.0;', 'gl_FragData[0] = vec4(rf, gf, 0.0, 1.0); }']).result;
shaders.Fragment = FSSource;
}
};
publicAPI.getNeedToRebuildShaders = function (cellBO, ren, actor) {
var lightComplexity = 0;
var numberOfLights = 0;
var primType = cellBO.getPrimitiveType();
var poly = model.currentInput; // different algo from C++ as of 5/2019
var needLighting = false;
var pointNormals = poly.getPointData().getNormals();
var cellNormals = poly.getCellData().getNormals();
var flat = actor.getProperty().getInterpolation() === Shading.FLAT;
var representation = actor.getProperty().getRepresentation();
var mode = publicAPI.getOpenGLMode(representation, primType); // 1) all surfaces need lighting
if (mode === model.context.TRIANGLES) {
needLighting = true; // 2) all cell normals without point normals need lighting
} else if (cellNormals && !pointNormals) {
needLighting = true; // 3) Phong + pointNormals need lighting
} else if (!flat && pointNormals) {
needLighting = true; // 4) Phong Lines need lighting
} else if (!flat && mode === model.context.LINES) {
needLighting = true;
} // 5) everything else is unlit
// do we need lighting?
if (actor.getProperty().getLighting() && needLighting) {
// consider the lighting complexity to determine which case applies
// simple headlight, Light Kit, the whole feature set of VTK
lightComplexity = 0;
var lights = ren.getLightsByReference();
for (var index = 0; index < lights.length; ++index) {
var light = lights[index];
var status = light.getSwitch();
if (status > 0) {
numberOfLights++;
if (lightComplexity === 0) {
lightComplexity = 1;
}
}
if (lightComplexity === 1 && (numberOfLights > 1 || light.getIntensity() !== 1.0 || !light.lightTypeIsHeadLight())) {
lightComplexity = 2;
}
if (lightComplexity < 3 && light.getPositional()) {
lightComplexity = 3;
}
}
}
var needRebuild = false;
var lastLightComplexity = model.lastBoundBO.getReferenceByName('lastLightComplexity');
var lastLightCount = model.lastBoundBO.getReferenceByName('lastLightCount');
if (lastLightComplexity !== lightComplexity || lastLightCount !== numberOfLights) {
model.lastBoundBO.set({
lastLightComplexity: lightComplexity
}, true);
model.lastBoundBO.set({
lastLightCount: numberOfLights
}, true);
needRebuild = true;
} // has something changed that would require us to recreate the shader?
// candidates are
// property modified (representation interpolation and lighting)
// input modified
// light complexity changed
if (model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram() === 0 || cellBO.getShaderSourceTime().getMTime() < publicAPI.getMTime() || cellBO.getShaderSourceTime().getMTime() < actor.getMTime() || cellBO.getShaderSourceTime().getMTime() < model.renderable.getMTime() || cellBO.getShaderSourceTime().getMTime() < model.currentInput.getMTime() || needRebuild) {
model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
return true;
}
return false;
};
publicAPI.updateShaders = function (cellBO, ren, actor) {
model.lastBoundBO = cellBO; // has something changed that would require us to recreate the shader?
if (publicAPI.getNeedToRebuildShaders(cellBO, ren, actor)) {
var shaders = {
Vertex: null,
Fragment: null,
Geometry: null
};
publicAPI.buildShaders(shaders, ren, actor); // compile and bind the program if needed
var newShader = model.openGLRenderWindow.getShaderCache().readyShaderProgramArray(shaders.Vertex, shaders.Fragment, shaders.Geometry); // if the shader changed reinitialize the VAO
if (newShader !== cellBO.getProgram()) {
cellBO.setProgram(newShader); // reset the VAO as the shader has changed
cellBO.getVAO().releaseGraphicsResources();
}
cellBO.getShaderSourceTime().modified();
} else {
model.openGLRenderWindow.getShaderCache().readyShaderProgram(cellBO.getProgram());
}
cellBO.getVAO().bind();
publicAPI.setMapperShaderParameters(cellBO, ren, actor);
publicAPI.setPropertyShaderParameters(cellBO, ren, actor);
publicAPI.setCameraShaderParameters(cellBO, ren, actor);
publicAPI.setLightingShaderParameters(cellBO, ren, actor);
var listCallbacks = model.renderable.getViewSpecificProperties().ShadersCallbacks;
if (listCallbacks) {
listCallbacks.forEach(function (object) {
object.callback(object.userData, cellBO, ren, actor);
});
}
};
publicAPI.setMapperShaderParameters = function (cellBO, ren, actor) {
// Now to update the VAO too, if necessary.
if (cellBO.getProgram().isUniformUsed('PrimitiveIDOffset')) {
cellBO.getProgram().setUniformi('PrimitiveIDOffset', model.primitiveIDOffset);
}
if (cellBO.getCABO().getElementCount() && (model.VBOBuildTime.getMTime() > cellBO.getAttributeUpdateTime().getMTime() || cellBO.getShaderSourceTime().getMTime() > cellBO.getAttributeUpdateTime().getMTime())) {
var lastLightComplexity = model.lastBoundBO.getReferenceByName('lastLightComplexity');
if (cellBO.getProgram().isAttributeUsed('vertexMC')) {
if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO(), 'vertexMC', cellBO.getCABO().getVertexOffset(), cellBO.getCABO().getStride(), model.context.FLOAT, 3, false)) {
vtkErrorMacro('Error setting vertexMC in shader VAO.');
}
}
if (cellBO.getProgram().isAttributeUsed('normalMC') && cellBO.getCABO().getNormalOffset() && lastLightComplexity > 0) {
if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO(), 'normalMC', cellBO.getCABO().getNormalOffset(), cellBO.getCABO().getStride(), model.context.FLOAT, 3, false)) {
vtkErrorMacro('Error setting normalMC in shader VAO.');
}
} else {
cellBO.getVAO().removeAttributeArray('normalMC');
}
model.renderable.getCustomShaderAttributes().forEach(function (attrName, idx) {
if (cellBO.getProgram().isAttributeUsed("".concat(attrName, "MC"))) {
if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO(), "".concat(attrName, "MC"), cellBO.getCABO().getCustomData()[idx].offset, cellBO.getCABO().getStride(), model.context.FLOAT, cellBO.getCABO().getCustomData()[idx].components, false)) {
vtkErrorMacro("Error setting ".concat(attrName, "MC in shader VAO."));
}
}
});
if (cellBO.getProgram().isAttributeUsed('tcoordMC') && cellBO.getCABO().getTCoordOffset()) {
if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO(), 'tcoordMC', cellBO.getCABO().getTCoordOffset(), cellBO.getCABO().getStride(), model.context.FLOAT, cellBO.getCABO().getTCoordComponents(), false)) {
vtkErrorMacro('Error setting tcoordMC in shader VAO.');
}
} else {
cellBO.getVAO().removeAttributeArray('tcoordMC');
}
if (cellBO.getProgram().isAttributeUsed('scalarColor') && cellBO.getCABO().getColorComponents()) {
if (!cellBO.getVAO().addAttributeArray(cellBO.getProgram(), cellBO.getCABO().getColorBO(), 'scalarColor', cellBO.getCABO().getColorOffset(), cellBO.getCABO().getColorBOStride(), model.context.UNSIGNED_BYTE, 4, true)) {
vtkErrorMacro('Error setting scalarColor in shader VAO.');
}
} else {
cellBO.getVAO().removeAttributeArray('scalarColor');
}
cellBO.getAttributeUpdateTime().modified();
}
if (model.renderable.getNumberOfClippingPlanes()) {
// add all the clipping planes
var numClipPlanes = model.renderable.getNumberOfClippingPlanes();
if (numClipPlanes > 6) {
vtkErrorMacro$1('OpenGL has a limit of 6 clipping planes');
numClipPlanes = 6;
}
var planeEquations = [];
for (var i = 0; i < numClipPlanes; i++) {
var planeEquation = [];
model.renderable.getClippingPlaneInDataCoords(actor.getMatrix(), i, planeEquation);
for (var j = 0; j < 4; j++) {
planeEquations.push(planeEquation[j]);
}
}
cellBO.getProgram().setUniformi('numClipPlanes', numClipPlanes);
cellBO.getProgram().setUniform4fv('clipPlanes', 6, planeEquations);
}
if (model.internalColorTexture && cellBO.getProgram().isUniformUsed('texture1')) {
cellBO.getProgram().setUniformi('texture1', model.internalColorTexture.getTextureUnit());
}
var tus = model.openGLActor.getActiveTextures();
if (tus) {
for (var index = 0; index < tus.length; ++index) {
var tex = tus[index];
var texUnit = tex.getTextureUnit();
var tname = "texture".concat(texUnit + 1);
if (cellBO.getProgram().isUniformUsed(tname)) {
cellBO.getProgram().setUniformi(tname, texUnit);
}
}
} // handle depth requests
if (model.haveSeenDepthRequest) {
cellBO.getProgram().setUniformi('depthRequest', model.renderDepth ? 1 : 0);
} // handle coincident
if (cellBO.getProgram().isUniformUsed('coffset')) {
var cp = publicAPI.getCoincidentParameters(ren, actor);
cellBO.getProgram().setUniformf('coffset', cp.offset); // cfactor isn't always used when coffset is.
if (cellBO.getProgram().isUniformUsed('cfactor')) {
cellBO.getProgram().setUniformf('cfactor', cp.factor);
}
}
var selector = model.openGLRenderer.getSelector();
cellBO.getProgram().setUniform3fArray('mapperIndex', selector ? selector.getPropColorValue() : [0.0, 0.0, 0.0]);
cellBO.getProgram().setUniformi('picking', selector ? selector.getCurrentPass() + 1 : 0);
};
publicAPI.setLightingShaderParameters = function (cellBO, ren, actor) {
// for unlit and headlight there are no lighting parameters
var lastLightComplexity = model.lastBoundBO.getReferenceByName('lastLightComplexity');
if (lastLightComplexity < 2) {
return;
}
var program = cellBO.getProgram(); // bind some light settings
var numberOfLights = 0;
var lights = ren.getLightsByReference();
for (var index = 0; index < lights.length; ++index) {
var light = lights[index];
var status = light.getSwitch();
if (status > 0.0) {
var dColor = light.getColorByReference();
var intensity = light.getIntensity();
model.lightColor[0] = dColor[0] * intensity;
model.lightColor[1] = dColor[1] * intensity;
model.lightColor[2] = dColor[2] * intensity; // get required info from light
var ld = light.getDirection();
var transform = ren.getActiveCamera().getViewMatrix();
var newLightDirection = _toConsumableArray(ld);
if (light.lightTypeIsSceneLight()) {
newLightDirection[0] = transform[0] * ld[0] + transform[1] * ld[1] + transform[2] * ld[2];
newLightDirection[1] = transform[4] * ld[0] + transform[5] * ld[1] + transform[6] * ld[2];
newLightDirection[2] = transform[8] * ld[0] + transform[9] * ld[1] + transform[10] * ld[2];
normalize(newLightDirection);
}
model.lightDirection[0] = newLightDirection[0];
model.lightDirection[1] = newLightDirection[1];
model.lightDirection[2] = newLightDirection[2];
model.lightHalfAngle[0] = -model.lightDirection[0];
model.lightHalfAngle[1] = -model.lightDirection[1];
model.lightHalfAngle[2] = -model.lightDirection[2] + 1.0;
normalize(model.lightDirection);
program.setUniform3fArray("lightColor".concat(numberOfLights), model.lightColor);
program.setUniform3fArray("lightDirectionVC".concat(numberOfLights), model.lightDirection);
program.setUniform3fArray("lightHalfAngleVC".concat(numberOfLights), model.lightHalfAngle);
numberOfLights++;
}
} // we are done unless we have positional lights
if (lastLightComplexity < 3) {
return;
} // for lightkit case there are some parameters to set
var cam = ren.getActiveCamera();
var viewTF = cam.getViewMatrix();
transpose(viewTF, viewTF);
numberOfLights = 0;
for (var _index = 0; _index < lights.length; ++_index) {
var _light = lights[_index];
var _status = _light.getSwitch();
if (_status > 0.0) {
var lp = _light.getTransformedPosition();
var np = new Float64Array(3);
transformMat4(np, lp, viewTF);
program.setUniform3fArray("lightAttenuation".concat(numberOfLights), _light.getAttenuationValuesByReference());
program.setUniformi("lightPositional".concat(numberOfLights), _light.getPositional());
program.setUniformf("lightExponent".concat(numberOfLights), _light.getExponent());
program.setUniformf("lightConeAngle".concat(numberOfLights), _light.getConeAngle());
program.setUniform3fArray("lightPositionVC".concat(numberOfLights), [np[0], np[1], np[2]]);
numberOfLights++;
}
}
};
function safeMatrixMultiply(matrixArray, matrixType, tmpMat) {
matrixType.identity(tmpMat);
return matrixArray.reduce(function (res, matrix, index) {
if (index === 0) {
return matrix ? matrixType.copy(res, matrix) : matrixType.identity(res);
}
return matrix ? matrixType.multiply(res, res, matrix) : res;
}, tmpMat);
}
publicAPI.setCameraShaderParameters = function (cellBO, ren, actor) {
var program = cellBO.getProgram(); // [WMVP]C == {world, model, view, projection} coordinates
// E.g., WCPC == world to projection coordinate transformation
var keyMats = model.openGLCamera.getKeyMatrices(ren);
var cam = ren.getActiveCamera();
var camm = model.openGLCamera.getKeyMatrixTime().getMTime();
var progm = program.getLastCameraMTime();
var shiftScaleEnabled = cellBO.getCABO().getCoordShiftAndScaleEnabled();
var inverseShiftScaleMatrix = shiftScaleEnabled ? cellBO.getCABO().getInverseShiftAndScaleMatrix() : null;
var actorIsIdentity = actor.getIsIdentity();
var actMats = actorIsIdentity ? {
mcwc: null,
normalMatrix: null
} : model.openGLActor.getKeyMatrices();
program.setUniformMatrix('MCPCMatrix', safeMatrixMultiply([keyMats.wcpc, actMats.mcwc, inverseShiftScaleMatrix], mat4, model.tmpMat4));
if (program.isUniformUsed('MCVCMatrix')) {
program.setUniformMatrix('MCVCMatrix', safeMatrixMultiply([keyMats.wcvc, actMats.mcwc, inverseShiftScaleMatrix], mat4, model.tmpMat4));
}
if (program.isUniformUsed('normalMatrix')) {
program.setUniformMatrix3x3('normalMatrix', safeMatrixMultiply([keyMats.normalMatrix, actMats.normalMatrix], mat3, model.tmpMat3));
}
if (progm !== camm) {
if (program.isUniformUsed('cameraParallel')) {
program.setUniformi('cameraParallel', cam.getParallelProjection());
}
program.setLastCameraMTime(camm);
}
if (!actorIsIdentity) {
// reset the cam mtime as actor modified the shader values
program.setLastCameraMTime(0);
}
};
publicAPI.setPropertyShaderParameters = function (cellBO, ren, actor) {
var program = cellBO.getProgram();
var ppty = actor.getProperty();
var opacity = ppty.getOpacity();
var aColor = model.drawingEdges ? ppty.getEdgeColorByReference() : ppty.getAmbientColorByReference();
var dColor = model.drawingEdges ? ppty.getEdgeColorByReference() : ppty.getDiffuseColorByReference();
var aIntensity = model.drawingEdges ? 1.0 : ppty.getAmbient();
var dIntensity = model.drawingEdges ? 0.0 : ppty.getDiffuse();
var sIntensity = model.drawingEdges ? 0.0 : ppty.getSpecular();
var specularPower = ppty.getSpecularPower();
program.setUniformf('opacityUniform', opacity);
program.setUniform3fArray('ambientColorUniform', aColor);
program.setUniform3fArray('diffuseColorUniform', dColor);
program.setUniformf('ambient', aIntensity);
program.setUniformf('diffuse', dIntensity); // we are done unless we have lighting
var lastLightComplexity = model.lastBoundBO.getReferenceByName('lastLightComplexity');
if (lastLightComplexity < 1) {
return;
}
var sColor = ppty.getSpecularColorByReference();
program.setUniform3fArray('specularColorUniform', sColor);
program.setUniformf('specularPowerUniform', specularPower);
program.setUniformf('specular', sIntensity); // now set the backface properties if we have them
if (program.isUniformUsed('ambientIntensityBF')) {
ppty = actor.getBackfaceProperty();
opacity = ppty.getOpacity();
aColor = ppty.getAmbientColor();
aIntensity = ppty.getAmbient();
dColor = ppty.getDiffuseColor();
dIntensity = ppty.getDiffuse();
sColor = ppty.getSpecularColor();
sIntensity = ppty.getSpecular();
program.setUniformf('ambientIntensityBF', aIntensity);
program.setUniformf('diffuseIntensityBF', dIntensity);
program.setUniformf('opacityUniformBF', opacity);
program.setUniform3fArray('ambientColorUniformBF', aColor);
program.setUniform3fArray('diffuseColorUniformBF', dColor); // we are done unless we have lighting
if (lastLightComplexity < 1) {
return;
}
program.setUniformf('specularIntensityBF', sIntensity);
program.setUniform3fArray('specularColorUniformBF', sColor);
program.setUniformf('specularPowerUniformBF', specularPower);
}
};
publicAPI.renderPieceStart = function (ren, actor) {
model.primitiveIDOffset = 0;
if (model.openGLRenderer.getSelector()) {
switch (model.openGLRenderer.getSelector().getCurrentPass()) {
default:
model.openGLRenderer.getSelector().renderProp(actor);
}
} // make sure the BOs are up to date
publicAPI.updateBufferObjects(ren, actor); // If we are coloring by texture, then load the texture map.
// Use Map as indicator, because texture hangs around.
if (model.renderable.getColorTextureMap()) {
model.internalColorTexture.activate();
} // Bind the OpenGL, this is shared between the different primitive/cell types.
model.lastBoundBO = null;
};
publ