"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
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Techniques = exports.VariedTechnique = exports.SingularTechnique = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const CachedGeometry_1 = require("./CachedGeometry");
const ClippingProgram_1 = require("./ClippingProgram");
const AmbientOcclusion_1 = require("./glsl/AmbientOcclusion");
const Blur_1 = require("./glsl/Blur");
const EDL_1 = require("./glsl/EDL");
const ClearPickAndColor_1 = require("./glsl/ClearPickAndColor");
const ClearTranslucent_1 = require("./glsl/ClearTranslucent");
const Combine3Textures_1 = require("./glsl/Combine3Textures");
const CombineTextures_1 = require("./glsl/CombineTextures");
const Common_1 = require("./glsl/Common");
const Composite_1 = require("./glsl/Composite");
const CopyColor_1 = require("./glsl/CopyColor");
const CopyPickBuffers_1 = require("./glsl/CopyPickBuffers");
const CopyStencil_1 = require("./glsl/CopyStencil");
const Edge_1 = require("./glsl/Edge");
const EVSMFromDepth_1 = require("./glsl/EVSMFromDepth");
const FeatureSymbology_1 = require("./glsl/FeatureSymbology");
const Fragment_1 = require("./glsl/Fragment");
const LogarithmicDepthBuffer_1 = require("./glsl/LogarithmicDepthBuffer");
const Monochrome_1 = require("./glsl/Monochrome");
const PlanarGrid_1 = __importDefault(require("./glsl/PlanarGrid"));
const PointCloud_1 = require("./glsl/PointCloud");
const PointString_1 = require("./glsl/PointString");
const Polyline_1 = require("./glsl/Polyline");
const RealityMesh_1 = require("./glsl/RealityMesh");
const SkyBox_1 = require("./glsl/SkyBox");
const SkySphere_1 = require("./glsl/SkySphere");
const Surface_1 = require("./glsl/Surface");
const Translucency_1 = require("./glsl/Translucency");
const Vertex_1 = require("./glsl/Vertex");
const ShaderProgram_1 = require("./ShaderProgram");
const System_1 = require("./System");
const TechniqueFlags_1 = require("./TechniqueFlags");
const TechniqueId_1 = require("./TechniqueId");
/** A rendering technique implemented using a single shader program, typically for some specialized purpose.
 * @internal
 */
class SingularTechnique {
    // Note: Technique assumes ownership of a program
    constructor(program) { this.program = program; }
    getShader(_flags) { return this.program; }
    getShaderByIndex(_index) { return this.program; }
    getShaderCount() { return 1; }
    compileShaders() { return this.program.compile() === 0 /* CompileStatus.Success */; }
    get isDisposed() { return this.program.isDisposed; }
    dispose() {
        (0, core_bentley_1.dispose)(this.program);
    }
}
exports.SingularTechnique = SingularTechnique;
function numFeatureVariants(numBaseShaders) {
    return numBaseShaders * 3;
}
const numHiliteVariants = 2; // instanced and non-instanced.
const featureModes = [0 /* FeatureMode.None */, 1 /* FeatureMode.Pick */, 2 /* FeatureMode.Overrides */];
const scratchTechniqueFlags = new TechniqueFlags_1.TechniqueFlags();
const scratchHiliteFlags = new TechniqueFlags_1.TechniqueFlags();
/** A rendering technique implemented using multiple shader programs, selected based on TechniqueFlags.
 * @internal
 */
class VariedTechnique {
    compileShaders() {
        let allCompiled = true;
        for (const program of this._basicPrograms) {
            if (program.compile() !== 0 /* CompileStatus.Success */)
                allCompiled = false;
        }
        for (const clipper of this._clippingPrograms)
            if (!clipper.compile())
                allCompiled = false;
        return allCompiled;
    }
    finishConstruction() {
        this._earlyZFlags.length = 0;
        // Confirm no empty entries in our array.
        let emptyShaderIndex = -1;
        (0, core_bentley_1.assert)(-1 === (emptyShaderIndex = this._basicPrograms.findIndex((prog) => undefined === prog)), `Shader index ${emptyShaderIndex} is undefined in ${this.constructor.name}`);
    }
    get isDisposed() { return this._isDisposed; }
    dispose() {
        if (this._isDisposed)
            return;
        for (const program of this._basicPrograms) {
            (0, core_bentley_1.assert)(undefined !== program);
            (0, core_bentley_1.dispose)(program);
        }
        this._basicPrograms.length = 0;
        for (const clipShaderObj of this._clippingPrograms) {
            (0, core_bentley_1.assert)(undefined !== clipShaderObj);
            clipShaderObj.dispose();
        }
        this._clippingPrograms.length = 0;
        this._isDisposed = true;
    }
    constructor(numPrograms) {
        this._basicPrograms = [];
        this._clippingPrograms = [];
        /** TechniqueFlags identifying shader programs for which the fragment shader writes depth but does not contain any discards.
         * Buggy Intel HD 620/630 drivers incorrectly apply early-Z optimization in this case; we must insert a never-executed
         * conditional discard to prevent that.
         */
        this._earlyZFlags = [];
        this._isDisposed = false;
        this._basicPrograms.length = numPrograms;
    }
    addShader(builder, flags, gl) {
        const descr = `${this._debugDescription}: ${flags.buildDescription()}`;
        builder.setDebugDescription(descr);
        if (System_1.System.instance.supportsLogZBuffer) {
            (0, LogarithmicDepthBuffer_1.addLogDepth)(builder);
            (0, core_bentley_1.assert)(!builder.frag.requiresEarlyZWorkaround);
            if (System_1.System.instance.fragDepthDoesNotDisableEarlyZ)
                builder.frag.requiresEarlyZWorkaround = -1 !== this._earlyZFlags.findIndex((x) => x.equals(flags));
        }
        const index = this.getShaderIndex(flags);
        this.addProgram(builder, index, gl);
        (0, core_bentley_1.assert)(!builder.frag.requiresEarlyZWorkaround);
    }
    addProgram(builder, index, gl) {
        (0, core_bentley_1.assert)(this._basicPrograms[index] === undefined);
        this._basicPrograms[index] = builder.buildProgram(gl);
        (0, core_bentley_1.assert)(this._basicPrograms[index] !== undefined);
        // Clipping programs always include a discard, so never require workaround.
        builder.frag.requiresEarlyZWorkaround = false;
        (0, core_bentley_1.assert)(this._clippingPrograms[index] === undefined);
        this._clippingPrograms[index] = (0, ClippingProgram_1.createClippingProgram)(builder);
        (0, core_bentley_1.assert)(this._clippingPrograms[index] !== undefined);
    }
    addHiliteShader(gl, instanced, classified, posType, create) {
        const builder = create(instanced, classified, posType);
        scratchHiliteFlags.initForHilite(0, instanced, classified, posType);
        this.addShader(builder, scratchHiliteFlags, gl);
    }
    addTranslucentShader(builder, flags, gl) {
        flags.isTranslucent = true;
        (0, Translucency_1.addTranslucency)(builder);
        this.addShader(builder, flags, gl);
    }
    addFeatureId(builder, feat) {
        const frag = builder.frag;
        if (0 /* FeatureMode.None */ === feat) {
            (0, Fragment_1.addFragColorWithPreMultipliedAlpha)(frag);
        }
        else {
            const vert = builder.vert;
            (0, Common_1.addFrustum)(builder);
            (0, Common_1.addEyeSpace)(builder);
            (0, Vertex_1.addModelViewMatrix)(vert);
            (0, FeatureSymbology_1.addRenderOrder)(frag);
            (0, FeatureSymbology_1.addFeatureId)(builder, false);
            (0, Fragment_1.addPickBufferOutputs)(frag);
        }
    }
    getShaderIndex(flags) {
        (0, core_bentley_1.assert)(!flags.isHilite || (!flags.isTranslucent && (flags.isClassified === 1 /* IsClassified.Yes */ || flags.hasFeatures)), "invalid technique flags");
        const index = this.computeShaderIndex(flags);
        (0, core_bentley_1.assert)(index < this._basicPrograms.length, "shader index out of bounds");
        return index;
    }
    getShader(flags) {
        const index = this.getShaderIndex(flags);
        let program;
        if (flags.hasClip) {
            const entry = this._clippingPrograms[index];
            (0, core_bentley_1.assert)(undefined !== entry);
            program = entry.getProgram(flags.numClipPlanes);
        }
        if (program === undefined)
            program = this._basicPrograms[index];
        return program;
    }
    // NB: Will ignore clipping shaders.
    getShaderByIndex(index) {
        return this._basicPrograms[index];
    }
    // NB: Will ignore clipping shaders.
    getShaderCount() {
        return this._basicPrograms.length;
    }
    /** For tests. */
    forEachProgram(func) {
        for (const basic of this._basicPrograms)
            func(basic);
        for (const clip of this._clippingPrograms) {
            const prog = clip.getProgram(1);
            (0, core_bentley_1.assert)(undefined !== prog);
            func(prog);
        }
    }
}
exports.VariedTechnique = VariedTechnique;
const positionTypes = ["quantized", "unquantized"];
class SurfaceTechnique extends VariedTechnique {
    constructor(gl) {
        super(SurfaceTechnique._kUnquantized * 2);
        this._earlyZFlags = [
            TechniqueFlags_1.TechniqueFlags.fromDescription("Opaque-Hilite-Overrides"),
            TechniqueFlags_1.TechniqueFlags.fromDescription("Opaque-Instanced-Hilite-Overrides"),
            TechniqueFlags_1.TechniqueFlags.fromDescription("Opaque-Hilite-Classified"),
            TechniqueFlags_1.TechniqueFlags.fromDescription("Unquantized-Opaque-Hilite-Overrides"),
            TechniqueFlags_1.TechniqueFlags.fromDescription("Unquantized-Opaque-Instanced-Hilite-Overrides"),
            TechniqueFlags_1.TechniqueFlags.fromDescription("Unquantized-Opaque-Hilite-Classified"),
        ];
        const flags = scratchTechniqueFlags;
        for (const posType of positionTypes) {
            for (let instanced = 0 /* IsInstanced.No */; instanced <= 1 /* IsInstanced.Yes */; instanced++) {
                this.addHiliteShader(gl, instanced, 0 /* IsClassified.No */, posType, Surface_1.createSurfaceHiliter);
                for (let iAnimate = 0 /* IsAnimated.No */; iAnimate <= 1 /* IsAnimated.Yes */; iAnimate++) {
                    for (let shadowable = 0 /* IsShadowable.No */; shadowable <= 1 /* IsShadowable.Yes */; shadowable++) {
                        for (let wiremesh = 0 /* IsWiremesh.No */; wiremesh <= 1 /* IsWiremesh.Yes */; wiremesh++) {
                            for (let thematic = 0 /* IsThematic.No */; thematic <= 1 /* IsThematic.Yes */; thematic++) {
                                for (let edgeTestNeeded = 0 /* IsEdgeTestNeeded.No */; edgeTestNeeded <= 1 /* IsEdgeTestNeeded.Yes */; edgeTestNeeded++) {
                                    for (const featureMode of featureModes) {
                                        for (let iTranslucent = 0; iTranslucent <= 1; iTranslucent++) {
                                            if (0 /* FeatureMode.None */ !== featureMode || 0 /* IsEdgeTestNeeded.No */ === edgeTestNeeded) {
                                                if (1 /* IsThematic.Yes */ === thematic && 1 /* IsShadowable.Yes */ === shadowable)
                                                    continue; // currently this combination is disallowed.
                                                flags.reset(featureMode, instanced, shadowable, thematic, posType);
                                                flags.isAnimated = iAnimate;
                                                flags.isEdgeTestNeeded = edgeTestNeeded;
                                                flags.isTranslucent = 1 === iTranslucent;
                                                flags.isWiremesh = wiremesh;
                                                const builder = (0, Surface_1.createSurfaceBuilder)(flags);
                                                this.addShader(builder, flags, gl);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        this.addHiliteShader(gl, 0 /* IsInstanced.No */, 1 /* IsClassified.Yes */, "quantized", Surface_1.createSurfaceHiliter);
        this.addHiliteShader(gl, 0 /* IsInstanced.No */, 1 /* IsClassified.Yes */, "unquantized", Surface_1.createSurfaceHiliter);
        for (const posType of positionTypes) {
            for (let translucent = 0; translucent < 2; translucent++) {
                for (let shadowable = 0 /* IsShadowable.No */; shadowable <= 1 /* IsShadowable.Yes */; shadowable++) {
                    for (let thematic = 0 /* IsThematic.No */; thematic <= 1 /* IsThematic.Yes */; thematic++) {
                        for (const featureMode of featureModes) {
                            if (1 /* IsThematic.Yes */ === thematic && 1 /* IsShadowable.Yes */ === shadowable)
                                continue; // currently this combination is disallowed.
                            flags.reset(featureMode, 0 /* IsInstanced.No */, shadowable, thematic, posType);
                            flags.isClassified = 1 /* IsClassified.Yes */;
                            flags.isTranslucent = (0 !== translucent);
                            const builder = (0, Surface_1.createSurfaceBuilder)(flags);
                            if (flags.isTranslucent)
                                (0, Translucency_1.addTranslucency)(builder);
                            this.addShader(builder, flags, gl);
                        }
                    }
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "Surface"; }
    computeShaderIndex(flags) {
        (0, core_bentley_1.assert)(!(flags.isThematic && flags.isShadowable));
        const idxOffset = flags.positionType === "unquantized" ? SurfaceTechnique._kUnquantized : 0;
        if (flags.isClassified) {
            (0, core_bentley_1.assert)(!flags.isAnimated);
            (0, core_bentley_1.assert)(!flags.isInstanced);
            (0, core_bentley_1.assert)(!flags.isEdgeTestNeeded);
            // First classified shader is for hilite
            if (flags.isHilite)
                return SurfaceTechnique._kClassified + idxOffset;
            // The rest are organized in 3 groups of 6 - one group per feature mode.
            // Each group contains opaque, translucent, opaque+thematic, translucent+thematic, opaque+shadowable, and translucent+shadowable variants.
            let baseIndex = SurfaceTechnique._kClassified + 1;
            if (flags.isTranslucent)
                baseIndex += 1;
            if (flags.isShadowable)
                baseIndex += 2;
            if (flags.isThematic)
                baseIndex += 4;
            const featureOffset = 6 * flags.featureMode;
            return baseIndex + featureOffset + idxOffset;
        }
        else if (flags.isHilite) {
            (0, core_bentley_1.assert)(flags.hasFeatures);
            return SurfaceTechnique._kHilite + flags.isInstanced + idxOffset;
        }
        (0, core_bentley_1.assert)(flags.hasFeatures || flags.isEdgeTestNeeded === 0 /* IsEdgeTestNeeded.No */);
        let index = flags.isTranslucent ? SurfaceTechnique._kTranslucent : SurfaceTechnique._kOpaque;
        index += SurfaceTechnique._kInstanced * flags.isInstanced;
        index += SurfaceTechnique._kAnimated * flags.isAnimated;
        index += SurfaceTechnique._kShadowable * flags.isShadowable;
        index += SurfaceTechnique._kThematic * flags.isThematic;
        index += SurfaceTechnique._kWiremesh * flags.isWiremesh;
        if (flags.isEdgeTestNeeded)
            index += SurfaceTechnique._kEdgeTestNeeded + (flags.featureMode - 1) * SurfaceTechnique._kFeature;
        else
            index += SurfaceTechnique._kFeature * flags.featureMode;
        return index + idxOffset;
    }
}
SurfaceTechnique._kOpaque = 0;
SurfaceTechnique._kTranslucent = 1;
SurfaceTechnique._kInstanced = 2;
SurfaceTechnique._kAnimated = 4;
SurfaceTechnique._kWiremesh = 8;
SurfaceTechnique._kShadowable = 16;
SurfaceTechnique._kThematic = 32;
SurfaceTechnique._kFeature = 48;
SurfaceTechnique._kEdgeTestNeeded = SurfaceTechnique._kFeature * 3; // only when hasFeatures
SurfaceTechnique._kHilite = SurfaceTechnique._kEdgeTestNeeded + SurfaceTechnique._kFeature * 2;
// Classifiers are never animated or instanced. They do support shadows, thematic display, and translucency.
// There are 3 base variations - 1 per feature mode - each with translucent/shadowed/thematic variants; plus 1 for hilite.
SurfaceTechnique._kClassified = SurfaceTechnique._kHilite + numHiliteVariants;
// 3 base classified variations - 1 per feature mode.
// Plus thematic variant of each and shadowable variant of each = 9
// Plus translucent variant of each of those = 18
// Plus 1 hilite shader = 19
SurfaceTechnique._kUnquantized = SurfaceTechnique._kClassified + 19;
class PolylineTechnique extends VariedTechnique {
    constructor(gl) {
        super(PolylineTechnique._kUnquantized * 2);
        this._earlyZFlags = [
            TechniqueFlags_1.TechniqueFlags.fromDescription("Opaque-Hilite-Overrides"),
            TechniqueFlags_1.TechniqueFlags.fromDescription("Opaque-Instanced-Hilite-Overrides"),
            TechniqueFlags_1.TechniqueFlags.fromDescription("Unquantized-Opaque-Hilite-Overrides"),
            TechniqueFlags_1.TechniqueFlags.fromDescription("Unquantized-Opaque-Instanced-Hilite-Overrides"),
        ];
        const flags = scratchTechniqueFlags;
        for (const posType of positionTypes) {
            for (let instanced = 0 /* IsInstanced.No */; instanced <= 1 /* IsInstanced.Yes */; instanced++) {
                this.addHiliteShader(gl, instanced, 0 /* IsClassified.No */, posType, (inst, _class, pos) => (0, Polyline_1.createPolylineHiliter)(inst, pos));
                for (const featureMode of featureModes) {
                    flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                    const builder = (0, Polyline_1.createPolylineBuilder)(instanced, posType);
                    (0, Monochrome_1.addUnlitMonochrome)(builder.frag);
                    // The translucent shaders do not need the element IDs.
                    const builderTrans = (0, Polyline_1.createPolylineBuilder)(instanced, posType);
                    (0, Monochrome_1.addUnlitMonochrome)(builderTrans.frag);
                    if (2 /* FeatureMode.Overrides */ === featureMode) {
                        (0, FeatureSymbology_1.addFeatureSymbology)(builderTrans, featureMode, 31 /* FeatureSymbologyOptions.Linear */);
                        (0, FeatureSymbology_1.addFeatureSymbology)(builder, featureMode, 31 /* FeatureSymbologyOptions.Linear */);
                        this.addTranslucentShader(builderTrans, flags, gl);
                    }
                    else {
                        this.addTranslucentShader(builderTrans, flags, gl);
                        (0, FeatureSymbology_1.addFeatureSymbology)(builder, featureMode, 0 /* FeatureSymbologyOptions.None */);
                    }
                    this.addFeatureId(builder, featureMode);
                    flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                    this.addShader(builder, flags, gl);
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "Polyline"; }
    computeShaderIndex(flags) {
        const idxOffset = flags.positionType === "unquantized" ? PolylineTechnique._kUnquantized : 0;
        if (flags.isHilite) {
            (0, core_bentley_1.assert)(flags.hasFeatures);
            return PolylineTechnique._kHilite + flags.isInstanced + idxOffset;
        }
        let index = flags.isTranslucent ? PolylineTechnique._kTranslucent : PolylineTechnique._kOpaque;
        index += PolylineTechnique._kFeature * flags.featureMode;
        index += PolylineTechnique._kInstanced * flags.isInstanced;
        return index + idxOffset;
    }
}
PolylineTechnique._kOpaque = 0;
PolylineTechnique._kTranslucent = 1;
PolylineTechnique._kInstanced = 2;
PolylineTechnique._kFeature = 4;
PolylineTechnique._kHilite = numFeatureVariants(PolylineTechnique._kFeature);
PolylineTechnique._kUnquantized = PolylineTechnique._kHilite + numHiliteVariants;
class EdgeTechnique extends VariedTechnique {
    constructor(gl, type) {
        super(EdgeTechnique._kUnquantized * 2);
        this._type = type;
        const flags = scratchTechniqueFlags;
        for (const posType of positionTypes) {
            for (let instanced = 0 /* IsInstanced.No */; instanced <= 1 /* IsInstanced.Yes */; instanced++) {
                for (let iAnimate = 0 /* IsAnimated.No */; iAnimate <= 1 /* IsAnimated.Yes */; iAnimate++) {
                    for (const featureMode of featureModes) {
                        flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                        flags.isAnimated = iAnimate;
                        const builder = (0, Edge_1.createEdgeBuilder)(type, flags.isInstanced, flags.isAnimated, posType);
                        (0, Monochrome_1.addUnlitMonochrome)(builder.frag);
                        // The translucent shaders do not need the element IDs.
                        const builderTrans = (0, Edge_1.createEdgeBuilder)(type, flags.isInstanced, flags.isAnimated, posType);
                        (0, Monochrome_1.addUnlitMonochrome)(builderTrans.frag);
                        if (2 /* FeatureMode.Overrides */ === featureMode) {
                            (0, FeatureSymbology_1.addFeatureSymbology)(builderTrans, featureMode, 31 /* FeatureSymbologyOptions.Linear */);
                            (0, FeatureSymbology_1.addFeatureSymbology)(builder, featureMode, 31 /* FeatureSymbologyOptions.Linear */);
                            this.addTranslucentShader(builderTrans, flags, gl);
                        }
                        else {
                            this.addTranslucentShader(builderTrans, flags, gl);
                            (0, FeatureSymbology_1.addFeatureSymbology)(builder, featureMode, 0 /* FeatureSymbologyOptions.None */);
                        }
                        this.addFeatureId(builder, featureMode);
                        flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                        flags.isAnimated = iAnimate;
                        this.addShader(builder, flags, gl);
                    }
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return this._type; }
    computeShaderIndex(flags) {
        let index = flags.isTranslucent ? EdgeTechnique._kTranslucent : EdgeTechnique._kOpaque;
        index += EdgeTechnique._kFeature * flags.featureMode;
        if (flags.isAnimated)
            index += EdgeTechnique._kAnimated;
        if (flags.isInstanced)
            index += EdgeTechnique._kInstanced;
        if ("unquantized" === flags.positionType)
            index += EdgeTechnique._kUnquantized;
        return index;
    }
}
EdgeTechnique._kOpaque = 0;
EdgeTechnique._kTranslucent = 1;
EdgeTechnique._kAnimated = 2;
EdgeTechnique._kInstanced = 4;
EdgeTechnique._kFeature = 8;
EdgeTechnique._kUnquantized = numFeatureVariants(EdgeTechnique._kFeature);
class PointStringTechnique extends VariedTechnique {
    constructor(gl) {
        super(PointStringTechnique._kUnquantized * 2);
        const flags = scratchTechniqueFlags;
        for (const posType of positionTypes) {
            for (let instanced = 0 /* IsInstanced.No */; instanced <= 1 /* IsInstanced.Yes */; instanced++) {
                this.addHiliteShader(gl, instanced, 0 /* IsClassified.No */, posType, (inst, _class, pos) => (0, PointString_1.createPointStringHiliter)(inst, pos));
                for (const featureMode of featureModes) {
                    flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                    const builder = (0, PointString_1.createPointStringBuilder)(instanced, posType);
                    (0, Monochrome_1.addUnlitMonochrome)(builder.frag);
                    // The translucent shaders do not need the element IDs.
                    const builderTrans = (0, PointString_1.createPointStringBuilder)(instanced, posType);
                    (0, Monochrome_1.addUnlitMonochrome)(builderTrans.frag);
                    if (2 /* FeatureMode.Overrides */ === featureMode) {
                        (0, FeatureSymbology_1.addFeatureSymbology)(builderTrans, featureMode, 29 /* FeatureSymbologyOptions.Point */);
                        (0, FeatureSymbology_1.addFeatureSymbology)(builder, featureMode, 29 /* FeatureSymbologyOptions.Point */);
                        this.addTranslucentShader(builderTrans, flags, gl);
                    }
                    else {
                        this.addTranslucentShader(builderTrans, flags, gl);
                        (0, FeatureSymbology_1.addFeatureSymbology)(builder, featureMode, 0 /* FeatureSymbologyOptions.None */);
                    }
                    this.addFeatureId(builder, featureMode);
                    flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                    this.addShader(builder, flags, gl);
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "PointString"; }
    computeShaderIndex(flags) {
        const idxOffset = "quantized" === flags.positionType ? 0 : PointStringTechnique._kUnquantized;
        if (flags.isHilite) {
            (0, core_bentley_1.assert)(flags.hasFeatures);
            return PointStringTechnique._kHilite + flags.isInstanced + idxOffset;
        }
        let index = flags.isTranslucent ? PointStringTechnique._kTranslucent : PointStringTechnique._kOpaque;
        index += PointStringTechnique._kFeature * flags.featureMode;
        index += PointStringTechnique._kInstanced * flags.isInstanced;
        return index + idxOffset;
    }
}
PointStringTechnique._kOpaque = 0;
PointStringTechnique._kTranslucent = 1;
PointStringTechnique._kInstanced = 2;
PointStringTechnique._kFeature = 4;
PointStringTechnique._kHilite = numFeatureVariants(PointStringTechnique._kFeature);
PointStringTechnique._kUnquantized = PointStringTechnique._kHilite + numHiliteVariants;
class PointCloudTechnique extends VariedTechnique {
    constructor(gl) {
        super(PointCloudTechnique._kHilite + 2);
        for (let iClassified = 0 /* IsClassified.No */; iClassified <= 1 /* IsClassified.Yes */; iClassified++) {
            this.addHiliteShader(gl, 0 /* IsInstanced.No */, iClassified, "quantized", (_inst, classified) => (0, PointCloud_1.createPointCloudHiliter)(classified));
            const flags = scratchTechniqueFlags;
            for (let thematic = 0 /* IsThematic.No */; thematic <= 1 /* IsThematic.Yes */; thematic++) {
                const pointCloudFeatureModes = [0 /* FeatureMode.None */, 2 /* FeatureMode.Overrides */];
                for (const featureMode of pointCloudFeatureModes) {
                    flags.reset(featureMode, 0 /* IsInstanced.No */, 0 /* IsShadowable.No */, thematic, "quantized");
                    flags.isClassified = iClassified;
                    const builder = (0, PointCloud_1.createPointCloudBuilder)(flags.isClassified, featureMode, thematic);
                    if (2 /* FeatureMode.Overrides */ === featureMode) {
                        (0, FeatureSymbology_1.addUniformFeatureSymbology)(builder, true);
                        (0, RealityMesh_1.addColorOverrideMix)(builder.vert);
                        builder.vert.set(7 /* VertexShaderComponent.ApplyFeatureColor */, FeatureSymbology_1.mixFeatureColor);
                    }
                    this.addFeatureId(builder, featureMode);
                    this.addShader(builder, flags, gl);
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "PointCloud"; }
    computeShaderIndex(flags) {
        (0, core_bentley_1.assert)(flags.positionType === "quantized", "Unquantized point cloud positions not currently supported");
        if (flags.isHilite)
            return PointCloudTechnique._kHilite + flags.isClassified;
        else {
            let ndx = 0;
            if (flags.isClassified)
                ndx++;
            if (flags.featureMode !== 0 /* FeatureMode.None */)
                ndx += 2;
            if (flags.isThematic)
                ndx += 4;
            return ndx;
        }
    }
}
PointCloudTechnique._kHilite = 8;
class RealityMeshTechnique extends VariedTechnique {
    constructor(gl) {
        super(RealityMeshTechnique._numVariants);
        this._earlyZFlags = [
            TechniqueFlags_1.TechniqueFlags.fromDescription("Opaque-Hilite-Overrides"),
            TechniqueFlags_1.TechniqueFlags.fromDescription("Opaque-Hilite-Classified"),
        ];
        this.addHiliteShader(gl, 0 /* IsInstanced.No */, 0 /* IsClassified.No */, "quantized", RealityMesh_1.createRealityMeshHiliter);
        this.addHiliteShader(gl, 0 /* IsInstanced.No */, 1 /* IsClassified.Yes */, "quantized", RealityMesh_1.createClassifierRealityMeshHiliter);
        for (let iClassified = 0 /* IsClassified.No */; iClassified <= 1 /* IsClassified.Yes */; iClassified++) {
            for (let iTranslucent = 0; iTranslucent <= 1; iTranslucent++) {
                for (let shadowable = 0 /* IsShadowable.No */; shadowable <= 1 /* IsShadowable.Yes */; shadowable++) {
                    for (let thematic = 0 /* IsThematic.No */; thematic <= 1 /* IsThematic.Yes */; thematic++) {
                        for (let wiremesh = 0 /* IsWiremesh.No */; wiremesh <= 1 /* IsWiremesh.Yes */; wiremesh++) {
                            for (let enableAtmosphere = 0 /* EnableAtmosphere.No */; enableAtmosphere <= 1 /* EnableAtmosphere.Yes */; enableAtmosphere++) {
                                const flags = scratchTechniqueFlags;
                                for (const featureMode of featureModes) {
                                    flags.reset(featureMode, 0 /* IsInstanced.No */, shadowable, thematic, "quantized");
                                    flags.isClassified = iClassified;
                                    flags.isWiremesh = wiremesh;
                                    flags.isTranslucent = 1 === iTranslucent;
                                    flags.enableAtmosphere = enableAtmosphere;
                                    const builder = (0, RealityMesh_1.createRealityMeshBuilder)(flags);
                                    if (flags.isTranslucent) {
                                        (0, Common_1.addShaderFlags)(builder);
                                        (0, Translucency_1.addTranslucency)(builder);
                                    }
                                    else
                                        this.addFeatureId(builder, featureMode);
                                    this.addShader(builder, flags, gl);
                                }
                            }
                        }
                    }
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "RealityMesh"; }
    computeShaderIndex(flags) {
        (0, core_bentley_1.assert)("quantized" === flags.positionType, "Unquantized reality mesh positions not currently supported.");
        if (flags.isHilite)
            return flags.isClassified ? 1 : 0;
        let ndx = 2;
        if (flags.isClassified)
            ndx++;
        if (flags.isShadowable)
            ndx += 2;
        if (flags.isTranslucent)
            ndx += 4;
        ndx += 8 * flags.featureMode;
        if (flags.isThematic)
            ndx += 24;
        if (flags.isWiremesh)
            ndx += 48;
        if (flags.enableAtmosphere)
            ndx += 96;
        return ndx;
    }
}
RealityMeshTechnique._numVariants = 194;
/**
 * More generalized version of VariedTechnique, without assuming usage of clipping, logDepth, eyeSpace, etc.
 * Similar to SingularTechnique in its simplicity, but with support for multiple shader programs per technique.
 */
class MultipleTechnique {
    get isDisposed() { return this._isDisposed; }
    constructor(numPrograms) {
        this._programs = [];
        this._isDisposed = false;
        this._programs.length = numPrograms;
    }
    getShaderIndex(flags) {
        (0, core_bentley_1.assert)(!flags.isHilite || (!flags.isTranslucent && (flags.isClassified === 1 /* IsClassified.Yes */ || flags.hasFeatures)), "invalid technique flags");
        const index = this.computeShaderIndex(flags);
        (0, core_bentley_1.assert)(index < this._programs.length, "shader index out of bounds");
        return index;
    }
    getShader(flags) {
        const index = this.getShaderIndex(flags);
        let program;
        if (program === undefined)
            program = this._programs[index];
        return program;
    }
    getShaderByIndex(index) {
        return this._programs[index];
    }
    getShaderCount() {
        return this._programs.length;
    }
    compileShaders() {
        let allCompiled = true;
        for (const program of this._programs) {
            if (program.compile() !== 0 /* CompileStatus.Success */)
                allCompiled = false;
        }
        return allCompiled;
    }
    dispose() {
        if (this._isDisposed)
            return;
        for (const program of this._programs) {
            (0, core_bentley_1.assert)(undefined !== program);
            (0, core_bentley_1.dispose)(program);
        }
        this._programs.length = 0;
        this._isDisposed = true;
    }
    addShader(builder, flags, gl) {
        const descr = `${this._debugDescription}: ${flags.buildDescription()}`;
        builder.setDebugDescription(descr);
        const index = this.getShaderIndex(flags);
        this.addProgram(builder, index, gl);
        (0, core_bentley_1.assert)(!builder.frag.requiresEarlyZWorkaround);
    }
    addProgram(builder, index, gl) {
        (0, core_bentley_1.assert)(this._programs[index] === undefined);
        this._programs[index] = builder.buildProgram(gl);
        (0, core_bentley_1.assert)(this._programs[index] !== undefined);
    }
    finishConstruction() {
        // Confirm no empty entries in our array.
        let emptyShaderIndex = -1;
        (0, core_bentley_1.assert)(-1 === (emptyShaderIndex = this._programs.findIndex((prog) => undefined === prog)), `Shader index ${emptyShaderIndex} is undefined in ${this.constructor.name}`);
    }
}
class SkySphereTechnique extends MultipleTechnique {
    constructor(gl, isGradient) {
        super(SkySphereTechnique._numVariants);
        this._isGradient = isGradient;
        for (let enableAtmosphere = 0 /* EnableAtmosphere.No */; enableAtmosphere <= 1 /* EnableAtmosphere.Yes */; enableAtmosphere++) {
            const tempFlags = scratchTechniqueFlags;
            tempFlags.reset(0 /* FeatureMode.None */, 0 /* IsInstanced.No */, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, "quantized");
            tempFlags.enableAtmosphere = enableAtmosphere;
            const builder = (0, SkySphere_1.createSkySphereBuilder)(isGradient, tempFlags);
            this.addShader(builder, tempFlags, gl);
        }
        this.finishConstruction();
    }
    get _debugDescription() { return `SkySphere-${this._isGradient ? "Gradient" : "Texture"}`; }
    computeShaderIndex(flags) {
        let index = 0;
        if (flags.enableAtmosphere)
            index += 1 << 0;
        return index;
    }
}
SkySphereTechnique._numVariants = 2; // one binary flag (2 ** 1)
const techniquesByPriority = [
    // Compile these specific shader variations first because they seem most likely to be used immediately upon opening a file.
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 0 /* FeatureMode.None */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 1 /* FeatureMode.Pick */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 1 /* FeatureMode.Pick */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 1 /* IsEdgeTestNeeded.Yes */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 2 /* FeatureMode.Overrides */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 2 /* FeatureMode.Overrides */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 1 /* IsEdgeTestNeeded.Yes */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 0 /* FeatureMode.None */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: true } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 1 /* FeatureMode.Pick */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: true } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 1 /* FeatureMode.Pick */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 1 /* IsEdgeTestNeeded.Yes */, isTranslucent: true } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 2 /* FeatureMode.Overrides */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: true } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 2 /* FeatureMode.Overrides */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 1 /* IsEdgeTestNeeded.Yes */, isTranslucent: true } },
    // Next, compile all shaders in specific techniques.
    // Do surfaces first because (1) they are the most commonly used and (2) they take longer to compile.
    { techniqueId: 0 /* TechniqueId.Surface */ },
    { techniqueId: 4 /* TechniqueId.Edge */ },
    { techniqueId: 5 /* TechniqueId.SilhouetteEdge */ },
    { techniqueId: 1 /* TechniqueId.Polyline */ },
    { techniqueId: 3 /* TechniqueId.PointString */ },
    { techniqueId: 2 /* TechniqueId.PointCloud */ },
    { techniqueId: 7 /* TechniqueId.RealityMesh */ },
    // The following techniques take a trivial amount of time to compile - do them last
    { techniqueId: 16 /* TechniqueId.OITClearTranslucent */ },
    { techniqueId: 17 /* TechniqueId.CopyPickBuffers */ },
    { techniqueId: 18 /* TechniqueId.CopyColor */ },
    { techniqueId: 19 /* TechniqueId.CopyColorNoAlpha */ },
    { techniqueId: 21 /* TechniqueId.ClearPickAndColor */ },
    { techniqueId: 10 /* TechniqueId.CompositeTranslucent */ },
    { techniqueId: 9 /* TechniqueId.CompositeHilite */ },
    { techniqueId: 11 /* TechniqueId.CompositeHiliteAndTranslucent */ },
    { techniqueId: 12 /* TechniqueId.CompositeOcclusion */ },
    { techniqueId: 13 /* TechniqueId.CompositeTranslucentAndOcclusion */ },
    { techniqueId: 14 /* TechniqueId.CompositeHiliteAndOcclusion */ },
    { techniqueId: 15 /* TechniqueId.CompositeAll */ },
    { techniqueId: 20 /* TechniqueId.VolClassColorUsingStencil */ },
    { techniqueId: 22 /* TechniqueId.EVSMFromDepth */ },
    { techniqueId: 23 /* TechniqueId.SkyBox */ },
    { techniqueId: 24 /* TechniqueId.SkySphereGradient */ },
    { techniqueId: 25 /* TechniqueId.SkySphereTexture */ },
    { techniqueId: 26 /* TechniqueId.AmbientOcclusion */ },
    { techniqueId: 27 /* TechniqueId.Blur */ },
    { techniqueId: 28 /* TechniqueId.BlurTestOrder */ },
    { techniqueId: 29 /* TechniqueId.CombineTextures */ },
    { techniqueId: 31 /* TechniqueId.VolClassCopyZ */ },
    { techniqueId: 32 /* TechniqueId.VolClassSetBlend */ },
    { techniqueId: 33 /* TechniqueId.VolClassBlend */ },
    { techniqueId: 30 /* TechniqueId.Combine3Textures */ },
    { techniqueId: 8 /* TechniqueId.PlanarGrid */ },
    { techniqueId: 34 /* TechniqueId.EDLCalcBasic */ },
    { techniqueId: 35 /* TechniqueId.EDLCalcFull */ },
    { techniqueId: 36 /* TechniqueId.EDLFilter */ },
    { techniqueId: 37 /* TechniqueId.EDLMix */ },
];
const numTechniquesByPriority = techniquesByPriority.length;
/** A collection of rendering techniques accessed by ID.
 * @internal
 */
class Techniques {
    static create(gl) {
        const techs = new Techniques();
        techs.initializeBuiltIns(gl);
        return techs;
    }
    getTechnique(id) {
        (0, core_bentley_1.assert)(id < this._list.length, "technique index out of bounds");
        return this._list[id];
    }
    get numTechniques() {
        return this._list.length;
    }
    addDynamicTechnique(technique, name) {
        const id = this.getDynamicTechniqueId(name);
        if (undefined !== id)
            return id;
        this._dynamicTechniqueIds.push(name);
        this._list.push(technique);
        return 38 /* TechniqueId.NumBuiltIn */ + this._dynamicTechniqueIds.length - 1;
    }
    getDynamicTechniqueId(name) {
        const index = this._dynamicTechniqueIds.indexOf(name);
        return -1 !== index ? index + 38 /* TechniqueId.NumBuiltIn */ + index : undefined;
    }
    /** Execute each command in the list */
    execute(target, commands, renderPass) {
        (0, core_bentley_1.assert)(255 /* RenderPass.None */ !== renderPass, "invalid render pass");
        (0, core_bentley_1.using)(new ShaderProgram_1.ShaderProgramExecutor(target, renderPass), (executor) => {
            for (const command of commands)
                command.execute(executor);
        });
        System_1.System.instance.frameBufferStack.markTargetsDirty();
    }
    /** Execute the commands for a single given classification primitive (the first 3 commands should be a push, the primitive, then a pop) */
    executeForIndexedClassifier(target, cmdsByIndex, renderPass) {
        // ###TODO: Disable shadows. Probably in the ClassifierTileTree's ViewFlagOverrides.
        this.execute(target, cmdsByIndex, renderPass);
    }
    /** Draw a single primitive. Usually used for special-purpose rendering techniques. */
    draw(params) {
        const tech = this.getTechnique(params.geometry.techniqueId);
        const program = tech.getShader(TechniqueFlags_1.TechniqueFlags.defaults);
        (0, core_bentley_1.using)(new ShaderProgram_1.ShaderProgramExecutor(params.target, params.renderPass, program), (executor) => {
            (0, core_bentley_1.assert)(executor.isValid);
            if (executor.isValid) {
                executor.draw(params);
            }
        });
        System_1.System.instance.frameBufferStack.markTargetsDirty();
    }
    get isDisposed() { return 0 === this._list.length; }
    dispose() {
        for (const tech of this._list)
            (0, core_bentley_1.dispose)(tech);
        this._list.length = 0;
    }
    // Chiefly for tests - compiles all shader programs - more generally programs are compiled on demand.
    compileShaders() {
        let allCompiled = true;
        for (const tech of this._list) {
            if (!tech.compileShaders())
                allCompiled = false;
        }
        return allCompiled;
    }
    /** Compile shader of next highest priority. Called when possible during an idle situation before any viewports exist. */
    idleCompileNextShader() {
        let compileStatus = 0 /* CompileStatus.Success */;
        let wasPreviouslyCompiled = false;
        do {
            if (this._techniqueByPriorityIndex >= numTechniquesByPriority)
                return false;
            let shader;
            let numShaders = 0;
            const pTech = techniquesByPriority[this._techniqueByPriorityIndex];
            const tech = this._list[pTech.techniqueId];
            if (pTech.specificShader !== undefined) { // if this entry consists of a specific shader, just compile that
                const flags = scratchTechniqueFlags;
                flags.reset(pTech.specificShader.featureMode, pTech.specificShader.isInstanced, pTech.specificShader.isShadowable, 0 /* IsThematic.No */, "quantized");
                flags.isEdgeTestNeeded = pTech.specificShader.isEdgeTestedNeeded;
                flags.isTranslucent = pTech.specificShader.isTranslucent;
                shader = tech.getShader(flags);
            }
            else { // if this entry only contains a techniqueId, then compile all uncompiled shaders for that technique
                shader = tech.getShaderByIndex(this._shaderIndex);
                this._shaderIndex++;
                numShaders = tech.getShaderCount();
            }
            if (shader.isCompiled)
                wasPreviouslyCompiled = true;
            else {
                compileStatus = shader.compile();
                wasPreviouslyCompiled = false;
            }
            if (this._shaderIndex >= numShaders) {
                this._techniqueByPriorityIndex++;
                this._shaderIndex = 0;
            }
        } while (wasPreviouslyCompiled);
        return compileStatus === 0 /* CompileStatus.Success */;
    }
    /** For tests. */
    forEachVariedProgram(func) {
        for (const technique of this._list)
            if (technique instanceof VariedTechnique)
                technique.forEachProgram(func);
    }
    constructor() {
        this._list = new Array(); // indexed by TechniqueId, which may exceed TechniqueId.NumBuiltIn for dynamic techniques.
        this._dynamicTechniqueIds = new Array(); // technique ID = (index in this array) + TechniqueId.NumBuiltIn
        this._techniqueByPriorityIndex = 0;
        this._shaderIndex = 0;
    }
    initializeBuiltIns(gl) {
        this._list[16 /* TechniqueId.OITClearTranslucent */] = new SingularTechnique((0, ClearTranslucent_1.createClearTranslucentProgram)(gl));
        this._list[21 /* TechniqueId.ClearPickAndColor */] = new SingularTechnique((0, ClearPickAndColor_1.createClearPickAndColorProgram)(gl));
        this._list[18 /* TechniqueId.CopyColor */] = new SingularTechnique((0, CopyColor_1.createCopyColorProgram)(gl));
        this._list[19 /* TechniqueId.CopyColorNoAlpha */] = new SingularTechnique((0, CopyColor_1.createCopyColorProgram)(gl, false));
        this._list[17 /* TechniqueId.CopyPickBuffers */] = new SingularTechnique((0, CopyPickBuffers_1.createCopyPickBuffersProgram)(gl));
        this._list[22 /* TechniqueId.EVSMFromDepth */] = new SingularTechnique((0, EVSMFromDepth_1.createEVSMProgram)(gl));
        this._list[23 /* TechniqueId.SkyBox */] = new SingularTechnique((0, SkyBox_1.createSkyBoxProgram)(gl));
        this._list[24 /* TechniqueId.SkySphereGradient */] = new SkySphereTechnique(gl, true);
        this._list[25 /* TechniqueId.SkySphereTexture */] = new SkySphereTechnique(gl, false);
        this._list[26 /* TechniqueId.AmbientOcclusion */] = new SingularTechnique((0, AmbientOcclusion_1.createAmbientOcclusionProgram)(gl));
        this._list[27 /* TechniqueId.Blur */] = new SingularTechnique((0, Blur_1.createBlurProgram)(gl, CachedGeometry_1.BlurType.NoTest));
        this._list[28 /* TechniqueId.BlurTestOrder */] = new SingularTechnique((0, Blur_1.createBlurProgram)(gl, CachedGeometry_1.BlurType.TestOrder));
        this._list[29 /* TechniqueId.CombineTextures */] = new SingularTechnique((0, CombineTextures_1.createCombineTexturesProgram)(gl));
        this._list[30 /* TechniqueId.Combine3Textures */] = new SingularTechnique((0, Combine3Textures_1.createCombine3TexturesProgram)(gl));
        this._list[0 /* TechniqueId.Surface */] = new SurfaceTechnique(gl);
        this._list[4 /* TechniqueId.Edge */] = new EdgeTechnique(gl, "SegmentEdge");
        this._list[5 /* TechniqueId.SilhouetteEdge */] = new EdgeTechnique(gl, "Silhouette");
        this._list[1 /* TechniqueId.Polyline */] = new PolylineTechnique(gl);
        this._list[3 /* TechniqueId.PointString */] = new PointStringTechnique(gl);
        this._list[2 /* TechniqueId.PointCloud */] = new PointCloudTechnique(gl);
        this._list[7 /* TechniqueId.RealityMesh */] = new RealityMeshTechnique(gl);
        this._list[8 /* TechniqueId.PlanarGrid */] = new SingularTechnique((0, PlanarGrid_1.default)(gl));
        this._list[34 /* TechniqueId.EDLCalcBasic */] = new SingularTechnique((0, EDL_1.createEDLCalcBasicProgram)(gl));
        this._list[35 /* TechniqueId.EDLCalcFull */] = new SingularTechnique((0, EDL_1.createEDLCalcFullProgram)(gl));
        this._list[36 /* TechniqueId.EDLFilter */] = new SingularTechnique((0, EDL_1.createEDLFilterProgram)(gl));
        this._list[37 /* TechniqueId.EDLMix */] = new SingularTechnique((0, EDL_1.createEDLMixProgram)(gl));
        this._list[6 /* TechniqueId.IndexedEdge */] = new EdgeTechnique(gl, "IndexedEdge");
        this._list[31 /* TechniqueId.VolClassCopyZ */] = new SingularTechnique((0, CopyStencil_1.createVolClassCopyZProgram)(gl));
        this._list[32 /* TechniqueId.VolClassSetBlend */] = new SingularTechnique((0, CopyStencil_1.createVolClassSetBlendProgram)(gl));
        this._list[33 /* TechniqueId.VolClassBlend */] = new SingularTechnique((0, CopyStencil_1.createVolClassBlendProgram)(gl));
        this._list[20 /* TechniqueId.VolClassColorUsingStencil */] = new SingularTechnique((0, CopyStencil_1.createVolClassColorUsingStencilProgram)(gl));
        for (let compositeFlags = 1; compositeFlags <= 7; compositeFlags++) {
            const techId = (0, TechniqueId_1.computeCompositeTechniqueId)(compositeFlags);
            this._list[techId] = new SingularTechnique((0, Composite_1.createCompositeProgram)(compositeFlags, gl));
        }
        (0, core_bentley_1.assert)(this._list.length === 38 /* TechniqueId.NumBuiltIn */, "unexpected number of built-in techniques");
    }
}
exports.Techniques = Techniques;
//# sourceMappingURL=Technique.js.map