UNPKG

@itwin/core-frontend

Version:
267 lines (259 loc) • 12.1 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module WebGL */ Object.defineProperty(exports, "__esModule", { value: true }); exports.addAnimation = addAnimation; const core_bentley_1 = require("@itwin/core-bentley"); const core_common_1 = require("@itwin/core-common"); const RenderFlags_1 = require("../RenderFlags"); const Surface_1 = require("./Surface"); const Vertex_1 = require("./Vertex"); const initialize = ` g_anim_step = vec2(1.0) / u_animLUTParams.xy; g_anim_center = g_anim_step * 0.5; `; // The vertex index is an integer in [0..numVertices]. // The frame index is an integer in [0..numBytesPerVertex/2]. // Therefore each frame index points at 2 bytes within the texture. // The third component of the return value is 0.0 if the input index points to the first 2 bytes of the texel, or 1.0 if pointing to the second 2 bytes const computeAnimLUTCoords = ` vec3 computeAnimLUTCoords(float vertIndex, float frameIndex) { // float baseIndex = (vertIndex * 2.0) + frameIndex; float baseIndex = (vertIndex * u_animLUTParams.z) + frameIndex; float halfIndex = baseIndex * 0.5; float index = floor(halfIndex); float epsilon = 0.5 / u_animLUTParams.x; float yId = floor(index / u_animLUTParams.x + epsilon); float xId = index - u_animLUTParams.x * yId; vec2 texCoord = g_anim_center + vec2(xId / u_animLUTParams.x, yId / u_animLUTParams.y); return vec3(texCoord, 2.0 * (halfIndex - index)); } `; // Sample 2 bytes at the specified index. const sampleAnimVec2 = ` vec2 sampleAnimVec2(float vertIndex, float frameIndex) { vec3 tc = computeAnimLUTCoords(vertIndex, frameIndex); vec4 texel = floor(TEXTURE(u_animLUT, tc.xy) * 255.0 + 0.5); return texel.xy * (1.0 - tc.z) + texel.zw * tc.z; } `; // Position is quantized to 6 bytes (2 bytes per component). So we always must sample two adjacent texels. We discard two bytes based on whether the index is even or odd. const computeAnimationFrameDisplacement = ` vec3 computeAnimationFrameDisplacement(float vertIndex, float frameIndex, vec3 origin, vec3 scale) { vec3 tc = computeAnimLUTCoords(vertIndex, frameIndex); vec4 enc1 = floor(TEXTURE(u_animLUT, tc.xy) * 255.0 + 0.5); tc.x += g_anim_step.x; vec4 enc2 = floor(TEXTURE(u_animLUT, tc.xy) * 255.0 + 0.5); vec2 ex = enc1.xy * (1.0 - tc.z) + enc1.zw * tc.z; vec2 ey = enc1.zw * (1.0 - tc.z) + enc2.xy * tc.z; vec2 ez = enc2.xy * (1.0 - tc.z) + enc2.zw * tc.z; vec3 qpos = vec3(decodeUInt16(ex), decodeUInt16(ey), decodeUInt16(ez)); return unquantizePosition(qpos, origin, scale).xyz; } `; const computeAnimationDisplacement = ` vec3 computeAnimationDisplacement(float vertIndex, float frameIndex0, float frameIndex1, float fraction, vec3 origin, vec3 scale) { if (frameIndex0 < 0.0) return vec3(0.0, 0.0, 0.0); vec3 displacement = computeAnimationFrameDisplacement(vertIndex, frameIndex0, origin, scale); if (fraction > 0.0) { vec3 displacement1 = computeAnimationFrameDisplacement(vertIndex, frameIndex1, origin, scale); displacement += fraction * (displacement1 - displacement); } return displacement; } `; const adjustRawPosition = ` rawPos.xyz += computeAnimationDisplacement(g_vertexLUTIndex, u_animDispParams.x, u_animDispParams.y, u_animDispParams.z, u_qAnimDispOrigin, u_qAnimDispScale); return rawPos; `; const computeAnimationFrameNormal = ` vec3 computeAnimationFrameNormal(float frameIndex) { vec2 enc = sampleAnimVec2(g_vertexLUTIndex, frameIndex); return octDecodeNormal(enc); } `; const computeAnimationNormal = ` vec3 computeAnimationNormal(float frameIndex0, float frameIndex1, float fraction) { vec3 normal = computeAnimationFrameNormal(frameIndex0); if (fraction > 0.0) { vec3 normal1 = computeAnimationFrameNormal(frameIndex1); normal += fraction * (normal1 - normal); } return normal; } `; const computeAnimationFrameParam = ` float computeAnimationFrameParam(float frameIndex, float origin, float scale) { vec2 enc = sampleAnimVec2(g_vertexLUTIndex, frameIndex); return clamp((origin + scale * decodeUInt16(enc)), 0.0, 1.0); } `; const computeAnimationParam = ` vec2 computeAnimationParam(float frameIndex0, float frameIndex1, float fraction, float origin, float scale) { float param = computeAnimationFrameParam(frameIndex0, origin, scale); if (fraction > 0.0) { float param1 = computeAnimationFrameParam(frameIndex1, origin, scale); param += fraction * (param1 - param); } return vec2(.5, param); } `; const scratchAnimParams = [ undefined, undefined, new Float32Array(2), // origin, scale new Float32Array(3), // index0, index1, fraction ]; function getAnimParams(size, initialValue) { // Elements 2 and 3 are guaranteed to be defined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const array = scratchAnimParams[size]; if (undefined !== initialValue) for (let i = 0; i < array.length; i++) array[i] = initialValue; return array; } function getDisplacementChannel(params) { const displacement = params.target.analysisStyle?.displacement; if (!displacement) return undefined; const channel = params.geometry.asLUT?.lut.auxChannels?.displacements?.get(displacement.channelName); return channel ? { channel, displacement } : undefined; } function getNormalChannel(params) { const channelName = params.target.analysisStyle?.normalChannelName; if (undefined === channelName) return undefined; return params.geometry.asLUT?.lut.auxChannels?.normals?.get(channelName); } function getScalarChannel(params) { const scalar = params.target.analysisStyle?.thematic; if (!scalar) return undefined; const channel = params.geometry.asMesh?.lut.auxChannels?.params?.get(scalar.channelName); return channel ? { channel, scalar } : undefined; } function computeAnimParams(params, channel, fraction) { const { inputs, indices } = channel; const inputValue = fraction * inputs[inputs.length - 1]; for (let i = 0; i < inputs.length - 1; i++) { if (inputValue >= inputs[i] && inputValue < inputs[i + 1]) { params[0] = indices[i]; params[1] = indices[i + 1]; params[2] = inputValue - inputs[i] / (inputs[i + 1] - inputs[i]); return; } } params[0] = params[1] = indices[inputs.length - 1]; params[2] = 0.0; } /** @internal */ function addAnimation(vert, isSurface) { // Lookup table vert.addGlobal("g_anim_step", 3 /* VariableType.Vec2 */); vert.addGlobal("g_anim_center", 3 /* VariableType.Vec2 */); vert.addInitializer(initialize); vert.addFunction(Vertex_1.unquantizePosition); vert.addUniform("u_animLUT", 8 /* VariableType.Sampler2D */, (prog) => { prog.addGraphicUniform("u_animLUT", (uniform, params) => { const channels = (0, core_bentley_1.expectDefined)(params.geometry.asLUT?.lut.auxChannels); (0, core_bentley_1.assert)(undefined !== channels); channels.texture.bindSampler(uniform, RenderFlags_1.TextureUnit.AuxChannelLUT); }); }); vert.addUniform("u_animLUTParams", 4 /* VariableType.Vec3 */, (prog) => { prog.addGraphicUniform("u_animLUTParams", (uniform, params) => { const geom = (0, core_bentley_1.expectDefined)(params.geometry.asLUT); (0, core_bentley_1.assert)(undefined !== geom && undefined !== geom.lut.auxChannels); const tex = geom.lut.auxChannels.texture; const array = getAnimParams(3); array[0] = tex.width; array[1] = tex.height; array[2] = geom.lut.auxChannels.numBytesPerVertex / 2; uniform.setUniform3fv(array); }); }); vert.addFunction(computeAnimLUTCoords); vert.addFunction(sampleAnimVec2); // Displacement vert.addFunction(computeAnimationFrameDisplacement); vert.addFunction(computeAnimationDisplacement); vert.set(1 /* VertexShaderComponent.AdjustRawPosition */, adjustRawPosition); vert.addUniform("u_animDispParams", 4 /* VariableType.Vec3 */, (prog) => { prog.addGraphicUniform("u_animDispParams", (uniform, params) => { const animParams = getAnimParams(3, 0.0); const disp = getDisplacementChannel(params); if (undefined !== disp) computeAnimParams(animParams, disp.channel, params.target.analysisFraction); uniform.setUniform3fv(animParams); }); }); vert.addUniform("u_qAnimDispScale", 4 /* VariableType.Vec3 */, (prog) => { prog.addGraphicUniform("u_qAnimDispScale", (uniform, params) => { const animParams = getAnimParams(3, 0.0); const disp = getDisplacementChannel(params); if (undefined !== disp) for (let i = 0; i < 3; i++) animParams[i] = disp.channel.qScale[i] * disp.displacement.scale; uniform.setUniform3fv(animParams); }); }); vert.addUniform("u_qAnimDispOrigin", 4 /* VariableType.Vec3 */, (prog) => { prog.addGraphicUniform("u_qAnimDispOrigin", (uniform, params) => { const animParams = getAnimParams(3, 0.0); const disp = getDisplacementChannel(params); if (undefined !== disp) for (let i = 0; i < 3; i++) animParams[i] = disp.channel.qOrigin[i] * disp.displacement.scale; uniform.setUniform3fv(animParams); }); }); // Normal and param if (isSurface) { vert.addFunction(Surface_1.octDecodeNormal); vert.addFunction(computeAnimationFrameNormal); vert.addFunction(computeAnimationNormal); vert.addFunction(computeAnimationFrameParam); vert.addFunction(computeAnimationParam); vert.addUniform("u_animNormalParams", 4 /* VariableType.Vec3 */, (prog) => { prog.addGraphicUniform("u_animNormalParams", (uniform, params) => { const animParams = getAnimParams(3, -1.0); const channel = getNormalChannel(params); if (undefined !== channel) computeAnimParams(animParams, channel, params.target.analysisFraction); uniform.setUniform3fv(animParams); }); }); vert.addUniform("u_animScalarParams", 4 /* VariableType.Vec3 */, (prog) => { prog.addGraphicUniform("u_animScalarParams", (uniform, params) => { const scalars = getScalarChannel(params); const animParams = getAnimParams(3, -1.0); if (scalars) computeAnimParams(animParams, scalars.channel, params.target.analysisFraction); uniform.setUniform3fv(animParams); }); }); vert.addUniform("u_animScalarQParams", 3 /* VariableType.Vec2 */, (prog) => { prog.addGraphicUniform("u_animScalarQParams", (uniform, params) => { const scalars = getScalarChannel(params); const animParams = getAnimParams(2, 1.0); if (scalars) { const range = scalars.scalar.range; let rangeScale = range.high - range.low; if (rangeScale === 0) rangeScale = 1; animParams[0] = core_common_1.ThematicGradientSettings.margin + (scalars.channel.qOrigin - range.low) / rangeScale; animParams[1] = core_common_1.ThematicGradientSettings.contentRange * scalars.channel.qScale / rangeScale; } uniform.setUniform2fv(animParams); }); }); } } //# sourceMappingURL=Animation.js.map