@itwin/core-frontend
Version:
iTwin.js frontend components
271 lines • 12 kB
JavaScript
"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.PrimitiveCommand = exports.PopClipCommand = exports.PushClipCommand = exports.PopBranchCommand = exports.PushBranchCommand = exports.PushStateCommand = exports.PushBatchCommand = exports.PopBatchCommand = exports.DrawOpCode = exports.DrawParams = exports.ShaderProgramParams = void 0;
exports.extractFlashedVolumeClassifierCommands = extractFlashedVolumeClassifierCommands;
exports.extractHilitedVolumeClassifierCommands = extractHilitedVolumeClassifierCommands;
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const FeatureOverrides_1 = require("./FeatureOverrides");
const System_1 = require("./System");
const TechniqueFlags_1 = require("./TechniqueFlags");
/* eslint-disable no-restricted-syntax */
/** @internal */
class ShaderProgramParams {
_target;
_renderPass = 255 /* RenderPass.None */;
get target() {
(0, core_bentley_1.assert)(undefined !== this._target);
return this._target;
}
get renderPass() { return this._renderPass; }
get projectionMatrix() { return this.target.uniforms.getProjectionMatrix32(this.isViewCoords); }
bindProjectionMatrix(uniform) { this.target.uniforms.bindProjectionMatrix(uniform, this.isViewCoords); }
get isViewCoords() { return 13 /* RenderPass.ViewOverlay */ === this.renderPass || 0 /* RenderPass.Background */ === this.renderPass; }
get isOverlayPass() { return 12 /* RenderPass.WorldOverlay */ === this.renderPass || 13 /* RenderPass.ViewOverlay */ === this.renderPass; }
get context() { return System_1.System.instance.context; }
init(target, pass = 5 /* RenderPass.OpaqueGeneral */) {
this._renderPass = pass;
this._target = target;
}
}
exports.ShaderProgramParams = ShaderProgramParams;
/** @internal */
class DrawParams {
_programParams;
_geometry;
get geometry() {
(0, core_bentley_1.assert)(undefined !== this._geometry);
return this._geometry;
}
get programParams() {
(0, core_bentley_1.assert)(undefined !== this._programParams);
return this._programParams;
}
get target() { return this.programParams.target; }
get renderPass() { return this.programParams.renderPass; }
get projectionMatrix() { return this.programParams.projectionMatrix; }
get isViewCoords() {
return this.programParams.isViewCoords || this.target.currentBranch.forceViewCoords;
}
get isOverlayPass() { return this.programParams.isOverlayPass; }
get context() { return this.programParams.context; }
init(programParams, geometry) {
this._programParams = programParams;
this._geometry = geometry;
}
}
exports.DrawParams = DrawParams;
/** Represents a command to be executed within a RenderPass. The most common command is
* to draw a primitive; others involve state changes such as pushing/popping transforms
* and symbology overrides, which require that commands be executed in order.
* @internal
*/
var DrawOpCode;
(function (DrawOpCode) {
DrawOpCode["Primitive"] = "drawPrimitive";
DrawOpCode["PushBranch"] = "pushBranch";
DrawOpCode["PopBranch"] = "popBranch";
DrawOpCode["PushBatch"] = "pushBatch";
DrawOpCode["PopBatch"] = "popBatch";
DrawOpCode["PushState"] = "pushState";
DrawOpCode["PushClip"] = "pushClip";
DrawOpCode["PopClip"] = "popClip";
})(DrawOpCode || (exports.DrawOpCode = DrawOpCode = {}));
/** @internal */
class PopBatchCommand {
opcode = "popBatch";
constructor() { }
static instance = new PopBatchCommand();
execute(exec) {
exec.target.popBatch();
}
}
exports.PopBatchCommand = PopBatchCommand;
/** @internal */
class PushBatchCommand {
batch;
opcode = "pushBatch";
constructor(batch) {
this.batch = batch;
}
execute(exec) {
exec.target.pushBatch(this.batch);
}
}
exports.PushBatchCommand = PushBatchCommand;
/** @internal */
class PushStateCommand {
state;
opcode = "pushState";
constructor(state) {
this.state = state;
}
execute(exec) {
exec.target.pushState(this.state);
}
}
exports.PushStateCommand = PushStateCommand;
/** @internal */
class PushBranchCommand {
branch;
opcode = "pushBranch";
constructor(branch) {
this.branch = branch;
}
execute(exec) {
exec.pushBranch(this.branch);
}
}
exports.PushBranchCommand = PushBranchCommand;
/** @internal */
class PopBranchCommand {
opcode = "popBranch";
constructor() { }
static instance = new PopBranchCommand();
execute(exec) {
exec.popBranch();
}
}
exports.PopBranchCommand = PopBranchCommand;
/** @internal */
class PushClipCommand {
clip;
opcode = "pushClip";
constructor(clip) {
this.clip = clip;
}
execute(exec) {
exec.target.uniforms.branch.clipStack.push(this.clip);
}
}
exports.PushClipCommand = PushClipCommand;
/** @internal */
class PopClipCommand {
opcode = "popClip";
constructor() { }
static instance = new PopClipCommand();
execute(exec) {
exec.target.uniforms.branch.clipStack.pop();
}
}
exports.PopClipCommand = PopClipCommand;
/** @internal */
class PrimitiveCommand {
primitive;
opcode = "drawPrimitive";
constructor(primitive) {
this.primitive = primitive;
}
static _scratchTechniqueFlags = new TechniqueFlags_1.TechniqueFlags();
execute(exec) {
if (exec.target.isGeometryOutsideActiveVolume(this.primitive.cachedGeometry))
return;
const techniqueId = this.primitive.techniqueId;
if (-1 /* TechniqueId.Invalid */ === techniqueId)
return;
const target = exec.target;
const thematic = this.primitive.cachedGeometry.supportsThematicDisplay && target.wantThematicDisplay;
const shadowable = (techniqueId === 0 /* TechniqueId.Surface */ || techniqueId === 7 /* TechniqueId.RealityMesh */) && target.solarShadowMap.isReady && target.currentViewFlags.shadows && !thematic;
const isShadowable = shadowable ? 1 /* IsShadowable.Yes */ : 0 /* IsShadowable.No */;
let isThematic = thematic ? 1 /* IsThematic.Yes */ : 0 /* IsThematic.No */;
const isClassified = (undefined !== target.currentPlanarClassifierOrDrape || undefined !== target.activeVolumeClassifierTexture) ? 1 /* IsClassified.Yes */ : 0 /* IsClassified.No */;
const isInstanced = this.primitive.isInstanced ? 1 /* IsInstanced.Yes */ : 0 /* IsInstanced.No */;
const isAnimated = this.primitive.hasAnimation ? 1 /* IsAnimated.Yes */ : 0 /* IsAnimated.No */;
// Point clouds do not support hillshade or slope mode for thematic display.
if (isThematic && (undefined !== this.primitive.cachedGeometry.asPointCloud) && (target.uniforms.thematic.wantSlopeMode || target.uniforms.thematic.wantHillShadeMode))
isThematic = 0 /* IsThematic.No */;
const wiremesh = target.currentViewFlags.wiremesh && (techniqueId === 0 /* TechniqueId.Surface */ || techniqueId === 7 /* TechniqueId.RealityMesh */);
const isWiremesh = wiremesh ? 1 /* IsWiremesh.Yes */ : 0 /* IsWiremesh.No */;
const flags = PrimitiveCommand._scratchTechniqueFlags;
const posType = this.primitive.cachedGeometry.usesQuantizedPositions ? "quantized" : "unquantized";
const enableAtmosphere = target.wantAtmosphere ? 1 /* EnableAtmosphere.Yes */ : 0 /* EnableAtmosphere.No */;
flags.init(target, exec.renderPass, isInstanced, isAnimated, isClassified, isShadowable, isThematic, isWiremesh, posType, enableAtmosphere);
const technique = target.techniques.getTechnique(techniqueId);
const program = technique.getShader(flags);
if (exec.setProgram(program))
exec.target.compositor.drawPrimitive(this.primitive, exec, program.outputsToPick);
}
get hasFeatures() { return this.primitive.hasFeatures; }
get renderOrder() { return this.primitive.renderOrder; }
getPass(target) {
return this.primitive.getPass(target);
}
}
exports.PrimitiveCommand = PrimitiveCommand;
/** Extracts the commands for rendering the flashed classifier (if any) from the by-index set of volume classifier commands.
* NB: Cmds will be sets of some pushes, a primitive, and then some pops (equal to number of pushes).
* The primitive should be right in the middle of a set. We need to find the set which matches the flashID.
* @internal
*/
function extractFlashedVolumeClassifierCommands(flashedId, cmds, numCmdsPerClassifier) {
if (!core_bentley_1.Id64.isValid(flashedId) || 0 === numCmdsPerClassifier)
return undefined;
const firstPrim = (numCmdsPerClassifier - 1) / 2;
for (let i = firstPrim; i < cmds.length; i += numCmdsPerClassifier) {
(0, core_bentley_1.assert)("drawPrimitive" === cmds[i].opcode, "Command list not configured as expected.");
const pc = cmds[i];
const surface = pc.primitive.cachedGeometry.asSurface;
if (undefined !== surface && undefined !== surface.mesh.uniformFeatureId) {
let j = i - 1;
while (j >= 0 && "pushBatch" !== cmds[j].opcode) // Find batch for this primitive
j--;
if (j < 0)
continue;
const pushBatch = cmds[j];
const elemId = pushBatch.batch.featureTable.findElementId(surface.mesh.uniformFeatureId);
if (undefined !== elemId && elemId === flashedId) {
return cmds.slice(i - firstPrim, i + firstPrim + 1);
}
}
}
return undefined;
}
const scratchFeature = core_common_1.PackedFeature.create();
/** @internal */
function extractHilitedVolumeClassifierCommands(hilites, cmds) {
// TODO: This could really be done at the time the HiliteClassification render pass commands are being generated
// by just not putting the ones which are not hilited into the ClassificationHilite command list.
const result = [];
let batch;
for (const cmd of cmds) {
switch (cmd.opcode) {
case "popBranch":
if (result.length > 0 && "pushBranch" === result[result.length - 1].opcode) {
result.pop(); // remove empty push/pop pairs
continue;
}
break;
case "popBatch":
batch = undefined;
if (result.length > 0 && "pushBatch" === result[result.length - 1].opcode) {
result.pop(); // remove empty push/pop pairs
continue;
}
break;
case "pushBatch":
batch = cmd.batch;
break;
case "drawPrimitive":
if (undefined !== batch) {
// Skip any primitives that are not hilited.
const surface = cmd.primitive.cachedGeometry.asSurface;
if (undefined === surface || undefined === surface.mesh.uniformFeatureId)
continue;
const feature = batch.featureTable.getPackedFeature(surface.mesh.uniformFeatureId, scratchFeature);
if (undefined === feature || !(0, FeatureOverrides_1.isFeatureHilited)(feature, hilites, hilites.models.hasId(core_bentley_1.Id64.fromUint32PairObject(feature.modelId))))
continue;
break;
}
}
result.push(cmd);
}
return result;
}
//# sourceMappingURL=DrawCommand.js.map