@itwin/core-frontend
Version:
iTwin.js frontend components
317 lines • 13.3 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* 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.lateVertexDiscard = exports.vertexDiscard = exports.earlyVertexDiscard = exports.unquantizePosition = void 0;
exports.addSamplePosition = addSamplePosition;
exports.addModelViewProjectionMatrix = addModelViewProjectionMatrix;
exports.addProjectionMatrix = addProjectionMatrix;
exports.addInstancedRtcMatrix = addInstancedRtcMatrix;
exports.addModelViewMatrix = addModelViewMatrix;
exports.addNormalMatrix = addNormalMatrix;
exports.addPosition = addPosition;
exports.addAlpha = addAlpha;
exports.addLineWeight = addLineWeight;
exports.replaceLineWeight = replaceLineWeight;
exports.addLineCode = addLineCode;
exports.replaceLineCode = replaceLineCode;
const core_bentley_1 = require("@itwin/core-bentley");
const Matrix_1 = require("../Matrix");
const RenderFlags_1 = require("../RenderFlags");
const Decode_1 = require("./Decode");
const Instancing_1 = require("./Instancing");
const LookupTable_1 = require("./LookupTable");
const initializeVertLUTCoords = `
g_vertexLUTIndex = decodeUInt24(qpos);
g_vertexBaseCoords = compute_vert_coords(g_vertexLUTIndex);
`;
/** @internal */
exports.unquantizePosition = `
vec4 unquantizePosition(vec3 pos, vec3 origin, vec3 scale) { return vec4(origin + scale * pos, 1.0); }
`;
const computeQuantizedPosition = `
vec4 computeVertexPosition(vec3 pos) { return unquantizePosition(pos, u_qOrigin, u_qScale); }
`;
// Need to read 2 rgba values to obtain 6 16-bit integers for position
const computeVertexPositionFromLUT = `
vec4 computeVertexPosition(vec3 encodedIndex) {
vec3 qpos = vec3(decodeUInt16(g_vertLutData0.xy), decodeUInt16(g_vertLutData0.zw), decodeUInt16(g_vertLutData1.xy));
g_featureAndMaterialIndex = g_vertLutData2;
return unquantizePosition(qpos, u_qOrigin, u_qScale);
}
`;
const computeUnquantizedPosition = `
vec4 computeVertexPosition(vec3 encodedIndex) {
uvec3 vux = uvec3(g_vertLutData0.xyz);
g_featureAndMaterialIndex.x = g_vertLutData0.w;
uvec3 vuy = uvec3(g_vertLutData1.xyz);
g_featureAndMaterialIndex.y = g_vertLutData1.w;
uvec3 vuz = uvec3(g_vertLutData2.xyz);
g_featureAndMaterialIndex.z = g_vertLutData2.w;
uvec3 vuw = uvec3(g_vertLutData3.xyz);
g_featureAndMaterialIndex.w = g_vertLutData3.w;
uvec3 u = (vuw << 24) | (vuz << 16) | (vuy << 8) | vux;
return vec4(uintBitsToFloat(u), 1.0);
}
`;
const computeLineWeight = "\nfloat computeLineWeight() { return g_lineWeight; }\n";
const computeLineCode = "\nfloat computeLineCode() { return g_lineCode; }\n";
function addSamplePosition(vert) {
vert.addFunction(getSamplePosition(vert.positionType));
}
const getSamplePositionPrelude = `
vec4 samplePosition(float index) {
vec2 tc = compute_vert_coords(index);`;
const getSamplePositionQuantizedPostlude = `
vec4 e0 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5);
tc.x += g_vert_stepX;
vec4 e1 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5);
vec3 qpos = vec3(decodeUInt16(e0.xy), decodeUInt16(e0.zw), decodeUInt16(e1.xy));
return unquantizePosition(qpos, u_qOrigin, u_qScale);
}
`;
const getSamplePositionUnquantizedPostlude = `
uvec3 vux = uvec3(floor(TEXTURE(u_vertLUT, tc).xyz * 255.0 + 0.5));
tc.x += g_vert_stepX;
uvec3 vuy = uvec3(floor(TEXTURE(u_vertLUT, tc).xyz * 255.0 + 0.5));
tc.x += g_vert_stepX;
uvec3 vuz = uvec3(floor(TEXTURE(u_vertLUT, tc).xyz * 255.0 + 0.5));
tc.x += g_vert_stepX;
uvec3 vuw = uvec3(floor(TEXTURE(u_vertLUT, tc).xyz * 255.0 + 0.5));
uvec3 u = (vuw << 24) | (vuz << 16) | (vuy << 8) | vux;
return vec4(uintBitsToFloat(u), 1.0);
}
`;
function getSamplePosition(type) {
return `${getSamplePositionPrelude}${"quantized" === type ? getSamplePositionQuantizedPostlude : getSamplePositionUnquantizedPostlude}`;
}
/** @internal */
function addModelViewProjectionMatrix(vert) {
if (vert.usesInstancedGeometry) {
addModelViewMatrix(vert);
addProjectionMatrix(vert);
vert.addGlobal("g_mvp", 7 /* VariableType.Mat4 */);
vert.addInitializer("g_mvp = u_proj * g_mv;");
}
else {
vert.addUniform("u_mvp", 7 /* VariableType.Mat4 */, (prog) => {
prog.addGraphicUniform("u_mvp", (uniform, params) => {
params.target.uniforms.branch.bindModelViewProjectionMatrix(uniform, params.geometry, params.isViewCoords);
});
});
}
}
/** @internal */
function addProjectionMatrix(vert) {
vert.addUniform("u_proj", 7 /* VariableType.Mat4 */, (prog) => {
prog.addProgramUniform("u_proj", (uniform, params) => {
params.bindProjectionMatrix(uniform);
});
});
}
const computeInstancedRtcMatrix = `
g_instancedRtcMatrix = u_instanced_rtc * g_modelMatrixRTC;
`;
/** @internal */
function addInstancedRtcMatrix(vert) {
if (!vert.usesInstancedGeometry)
return;
(0, core_bentley_1.assert)(undefined !== vert.find("g_modelMatrixRTC")); // set up in VertexShaderBuilder constructor...
vert.addUniform("u_instanced_rtc", 7 /* VariableType.Mat4 */, (prog) => {
prog.addGraphicUniform("u_instanced_rtc", (uniform, params) => {
const modelt = (0, core_bentley_1.expectDefined)(params.geometry.asInstanced).getRtcOnlyTransform();
uniform.setMatrix4(Matrix_1.Matrix4.fromTransform(modelt));
});
});
vert.addGlobal("g_instancedRtcMatrix", 7 /* VariableType.Mat4 */);
vert.addInitializer(computeInstancedRtcMatrix);
}
/** @internal */
function addModelViewMatrix(vert) {
const bind = (uniform, params) => {
params.target.uniforms.branch.bindModelViewMatrix(uniform, params.geometry, params.isViewCoords);
};
if (vert.usesInstancedGeometry) {
vert.addUniform("u_instanced_modelView", 7 /* VariableType.Mat4 */, (prog) => {
prog.addGraphicUniform("u_instanced_modelView", bind);
});
vert.addGlobal("g_mv", 7 /* VariableType.Mat4 */);
vert.addInitializer("g_mv = u_instanced_modelView * g_modelMatrixRTC;");
}
else {
vert.addUniform("u_mv", 7 /* VariableType.Mat4 */, (prog) => {
// ###TODO: We only need 3 rows, not 4...
prog.addGraphicUniform("u_mv", bind);
});
}
}
const computeNormalMatrix = `
g_nmx = transpose(inverse(mat3(MAT_MV)));
g_nmx[0][0] *= u_frustumScale.x;
g_nmx[1][1] *= u_frustumScale.y;
`;
/** @internal */
function addNormalMatrix(vert) {
vert.addGlobal("g_nmx", 6 /* VariableType.Mat3 */);
vert.addUniform("u_frustumScale", 3 /* VariableType.Vec2 */, (prog) => {
prog.addGraphicUniform("u_frustumScale", (uniform, params) => {
const scale = params.target.uniforms.branch.top.frustumScale;
uniform.setUniform2fv([scale.x, scale.y]);
});
});
vert.addInitializer(computeNormalMatrix);
}
function readVertexData(index) {
return `g_vertLutData${index} = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5);`;
}
const nextVertexData = "tc.x += g_vert_stepX;";
function readNextVertexData(index) {
return `
${nextVertexData}
${readVertexData(index)}`;
}
const prereadVertexDataPrelude = `
vec2 tc = g_vertexBaseCoords;
${readVertexData(0)}
${readNextVertexData(1)}
${readNextVertexData(2)}
`;
const prereadQuantizedVertexData = `${prereadVertexDataPrelude}
if (3.0 < u_vertParams.z) {
${readNextVertexData(3)}
}
`;
const prereadUnquantizedVertexData = `${prereadVertexDataPrelude}
${readNextVertexData(3)}
${readNextVertexData(4)}
if (5.0 < u_vertParams.z) {
${readNextVertexData(5)}
}
`;
const scratchLutParams = new Float32Array(4);
function addPositionFromLUT(vert) {
vert.addGlobal("g_vertexLUTIndex", 2 /* VariableType.Float */);
vert.addGlobal("g_vertexBaseCoords", 3 /* VariableType.Vec2 */);
const unquantized = "unquantized" === vert.positionType;
const maxRgbaPerVert = unquantized ? 6 : 4;
for (let i = 0; i < maxRgbaPerVert; i++)
vert.addGlobal(`g_vertLutData${i}`, 5 /* VariableType.Vec4 */);
vert.addFunction(Decode_1.decodeUint24);
vert.addFunction(Decode_1.decodeUint16);
vert.addFunction(unquantized ? computeUnquantizedPosition : computeVertexPositionFromLUT);
vert.addUniform("u_vertLUT", 8 /* VariableType.Sampler2D */, (prog) => {
prog.addGraphicUniform("u_vertLUT", (uniform, params) => {
(0, core_bentley_1.expectDefined)(params.geometry.asLUT).lut.texture.bindSampler(uniform, RenderFlags_1.TextureUnit.VertexLUT);
});
});
vert.addUniform("u_vertParams", 5 /* VariableType.Vec4 */, (prog) => {
prog.addGraphicUniform("u_vertParams", (uniform, params) => {
(0, core_bentley_1.assert)(undefined !== params.geometry.asLUT);
const lut = params.geometry.asLUT.lut;
const lutParams = scratchLutParams;
lutParams[0] = lut.texture.width;
lutParams[1] = lut.texture.height;
lutParams[2] = lut.numRgbaPerVertex;
lutParams[3] = lut.numVertices;
uniform.setUniform4fv(lutParams);
});
});
(0, LookupTable_1.addLookupTable)(vert, "vert", "u_vertParams.z");
vert.addInitializer(initializeVertLUTCoords);
vert.addGlobal("g_featureAndMaterialIndex", 5 /* VariableType.Vec4 */);
// Read the vertex data from the vertex table up front. Yields a consistent (if unexplainable) small performance boost.
vert.addInitializer(unquantized ? prereadUnquantizedVertexData : prereadQuantizedVertexData);
}
/** @internal */
function addPosition(vert, fromLUT) {
if (!fromLUT || "quantized" === vert.positionType) {
vert.addFunction(exports.unquantizePosition);
vert.addUniform("u_qScale", 4 /* VariableType.Vec3 */, (prog) => {
prog.addGraphicUniform("u_qScale", (uniform, params) => {
(0, core_bentley_1.assert)(params.geometry.usesQuantizedPositions);
uniform.setUniform3fv(params.geometry.qScale);
});
});
vert.addUniform("u_qOrigin", 4 /* VariableType.Vec3 */, (prog) => {
prog.addGraphicUniform("u_qOrigin", (uniform, params) => {
(0, core_bentley_1.assert)(params.geometry.usesQuantizedPositions);
uniform.setUniform3fv(params.geometry.qOrigin);
});
});
}
if (!fromLUT) {
vert.addFunction(computeQuantizedPosition);
}
else {
addPositionFromLUT(vert);
}
}
/** @internal */
function addAlpha(vert) {
vert.addUniform("u_hasAlpha", 2 /* VariableType.Float */, (prog) => {
prog.addGraphicUniform("u_hasAlpha", (uniform, params) => {
uniform.setUniform1f(RenderFlags_1.Pass.rendersTranslucent(params.geometry.getPass(params.target)) ? 1 : 0);
});
});
}
/** @internal */
function addLineWeight(vert) {
vert.addUniform("u_lineWeight", 2 /* VariableType.Float */, (prog) => {
prog.addGraphicUniform("u_lineWeight", (attr, params) => {
attr.setUniform1f(params.geometry.getLineWeight(params.programParams));
});
});
vert.addGlobal("g_lineWeight", 2 /* VariableType.Float */);
if (vert.usesInstancedGeometry) {
(0, Instancing_1.addInstanceOverrides)(vert);
vert.addInitializer("g_lineWeight = mix(u_lineWeight, a_instanceOverrides.g, extractInstanceBit(kOvrBit_Weight));");
}
else {
vert.addInitializer("g_lineWeight = u_lineWeight;");
}
vert.addFunction(computeLineWeight);
}
/** @internal */
function replaceLineWeight(vert, func) {
vert.replaceFunction(computeLineWeight, func);
}
/** @internal */
function addLineCode(vert) {
vert.addUniform("u_lineCode", 2 /* VariableType.Float */, (prog) => {
prog.addGraphicUniform("u_lineCode", (attr, params) => {
attr.setUniform1f(params.geometry.getLineCode(params.programParams));
});
});
vert.addGlobal("g_lineCode", 2 /* VariableType.Float */);
if (vert.usesInstancedGeometry) {
(0, Instancing_1.addInstanceOverrides)(vert);
vert.addInitializer("g_lineCode = mix(u_lineCode, a_instanceOverrides.b, extractInstanceBit(kOvrBit_LineCode));");
}
else {
vert.addInitializer("g_lineCode = u_lineCode;");
}
vert.addFunction(computeLineCode);
}
/** @internal */
function replaceLineCode(vert, func) {
vert.replaceFunction(computeLineCode, func);
}
// This vertex belongs to a triangle which should not be rendered. Produce a degenerate triangle.
// Also place it outside NDC range (for GL_POINTS)
const discardVertex = ` {
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
return;
}
`;
/** @internal */
exports.earlyVertexDiscard = ` if (checkForEarlyDiscard(rawPosition))${discardVertex}`;
/** @internal */
exports.vertexDiscard = ` if (checkForDiscard())${discardVertex}`;
/** @internal */
exports.lateVertexDiscard = ` if (checkForLateDiscard())${discardVertex}`;
//# sourceMappingURL=Vertex.js.map