@itwin/core-frontend
Version:
iTwin.js frontend components
994 lines • 47.9 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.PolylineBuffers = exports.ScreenPointsGeometry = exports.VolumeClassifierGeometry = exports.BoundaryType = exports.SingleTexturedViewportQuadGeometry = exports.Combine3TexturesGeometry = exports.CombineTexturesGeometry = exports.CopyPickBufferGeometry = exports.CompositeGeometry = exports.EVSMGeometry = exports.EDLMixGeometry = exports.EDLFilterGeometry = exports.EDLCalcFullGeometry = exports.EDLCalcBasicGeometry = exports.BlurGeometry = exports.BlurType = exports.AmbientOcclusionGeometry = exports.SkySphereViewportQuadGeometry = exports.TexturedViewportQuadGeometry = exports.ViewportQuadGeometry = exports.SkyBoxQuadsGeometry = exports.SkyBoxGeometryParams = exports.IndexedGeometry = exports.IndexedGeometryParams = exports.LUTGeometry = exports.CachedGeometry = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_geometry_1 = require("@itwin/core-geometry");
const core_common_1 = require("@itwin/core-common");
const FlashSettings_1 = require("../../../FlashSettings");
const RenderMemory_1 = require("../../../render/RenderMemory");
const AttributeMap_1 = require("./AttributeMap");
const LineCode_1 = require("./LineCode");
const FrustumUniforms_1 = require("./FrustumUniforms");
const GL_1 = require("./GL");
const AttributeBuffers_1 = require("./AttributeBuffers");
const System_1 = require("./System");
const TechniqueId_1 = require("./TechniqueId");
const Texture_1 = require("./Texture");
const scratchVec3a = new core_geometry_1.Vector3d();
const scratchVec3b = new core_geometry_1.Vector3d();
const scratchVec3c = new core_geometry_1.Vector3d();
const scratchPoint3a = new core_geometry_1.Point3d();
const scratchPoint3b = new core_geometry_1.Point3d();
const scratchPoint3c = new core_geometry_1.Point3d();
const scratchPoint3d = new core_geometry_1.Point3d();
/** Represents a geometric primitive ready to be submitted to the GPU for rendering.
* @internal
*/
class CachedGeometry {
_range;
/**
* Functions for obtaining a subclass of CachedGeometry.
* IMPORTANT: Do NOT use code like `const surface = cachedGeom as SurfaceGeometry`.
* Instanced geometry holds a reference to the shared geometry rendered for each instance - such casts will fail,
* while the casting `functions` will forward to the shared geometry.
*/
get asLUT() { return undefined; }
get asSurface() { return undefined; }
get asMesh() { return undefined; }
get asEdge() { return undefined; }
get asIndexedEdge() { return undefined; }
get asRealityMesh() { return undefined; }
get asSilhouette() { return undefined; }
get asInstanced() { return undefined; }
get isInstanced() { return undefined !== this.asInstanced; }
get asPointCloud() { return undefined; }
get asPlanarGrid() { return undefined; }
get alwaysRenderTranslucent() { return false; }
get allowColorOverride() { return true; }
// Returns the edge/line weight used to render this geometry
_getLineWeight(_params) { return 0; }
// Returns the edge/line pattern used to render this geometry
_getLineCode(_params) { return LineCode_1.LineCode.solid; }
// Returns true if this is a lit surface
get isLitSurface() { return false; }
// Returns true if this is an unlit surface with baked-in lighting (e.g. 3mx, scalable mesh reality models)
get hasBakedLighting() { return false; }
// Returns true if this primitive contains auxillary animation data.
get hasAnimation() { return false; }
/** If false, the geometry's positions are not quantized.
* qOrigin and qScale can still be used to derive the geometry's range, but will not be passed to the shader.
* see VertexLUT.usesQuantizedPositions.
*/
get usesQuantizedPositions() { return true; }
// Intended to be overridden by specific subclasses
get materialInfo() { return undefined; }
get hasMaterialAtlas() {
const mat = this.materialInfo;
return undefined !== mat && mat.isAtlas;
}
get polylineBuffers() { return undefined; }
get hasFeatures() { return false; }
get viewIndependentOrigin() { return undefined; }
get isViewIndependent() { return undefined !== this.viewIndependentOrigin; }
get supportsThematicDisplay() { return false; }
get isEdge() {
switch (this.renderOrder) {
case 6 /* RenderOrder.Edge */:
case 7 /* RenderOrder.Silhouette */:
case 14 /* RenderOrder.PlanarEdge */:
case 15 /* RenderOrder.PlanarSilhouette */:
return true;
default:
return false;
}
}
wantWoWReversal(params) {
return params.target.currentViewFlags.whiteOnWhiteReversal && this._wantWoWReversal(params.target);
}
getLineCode(params) {
return params.target.currentViewFlags.styles ? this._getLineCode(params) : LineCode_1.LineCode.solid;
}
getLineWeight(params) {
if (!params.target.currentViewFlags.weights) {
return 1.0;
}
const minWeight = 1;
let weight = this._getLineWeight(params);
weight = Math.max(weight, minWeight);
weight = Math.min(weight, 31.0);
return weight;
}
getFlashMode(params) {
// By default only surfaces rendered with lighting get brightened. Overridden for reality meshes since they have lighting baked-in.
// NB: If the reality model is classified, the classifiers are drawn without lighting, therefore we mix the hilite color.
if (this.hasBakedLighting)
return FlashSettings_1.FlashMode.Hilite;
const vf = params.target.currentViewFlags;
if (!this.isLitSurface || core_common_1.RenderMode.SmoothShade !== vf.renderMode)
return FlashSettings_1.FlashMode.Hilite;
return vf.lighting ? params.target.plan.flashSettings.litMode : FlashSettings_1.FlashMode.Hilite;
}
wantMixMonochromeColor(_target) { return false; }
wantMonochrome(_target) { return true; }
computeRange(output) {
if (undefined === this._range) {
const lowX = this.qOrigin[0];
const lowY = this.qOrigin[1];
const lowZ = this.qOrigin[2];
const hiX = 0xffff * this.qScale[0] + lowX;
const hiY = 0xffff * this.qScale[1] + lowY;
const hiZ = 0xffff * this.qScale[2] + lowZ;
this._range = core_geometry_1.Range3d.createXYZXYZ(lowX, lowY, lowZ, hiX, hiY, hiZ);
}
return this._range.clone(output);
}
}
exports.CachedGeometry = CachedGeometry;
/** Geometry which is drawn using indices into a look-up texture of vertex data, via gl.drawArrays()
* @internal
*/
class LUTGeometry extends CachedGeometry {
_viewIndependentOrigin;
get asLUT() { return this; }
get viewIndependentOrigin() { return this._viewIndependentOrigin; }
draw() { this._draw(0); }
drawInstanced(numInstances, instanceBuffersContainer) { this._draw(numInstances, instanceBuffersContainer); }
// Override this if your color varies based on the target
getColor(_target) { return this.lut.colorInfo; }
get usesQuantizedPositions() { return this.lut.usesQuantizedPositions; }
get qOrigin() { return this.lut.qOrigin; }
get qScale() { return this.lut.qScale; }
get hasAnimation() { return this.lut.hasAnimation; }
constructor(viewIndependentOrigin) {
super();
this._viewIndependentOrigin = viewIndependentOrigin;
}
}
exports.LUTGeometry = LUTGeometry;
/** Parameters used to construct an IndexedGeometry
* @internal
*/
class IndexedGeometryParams {
buffers;
positions;
indices;
numIndices;
constructor(positions, indices, numIndices) {
this.buffers = AttributeBuffers_1.BuffersContainer.create();
const attrPos = AttributeMap_1.AttributeMap.findAttribute("a_pos", undefined, false);
(0, core_bentley_1.assert)(attrPos !== undefined);
this.buffers.addBuffer(positions, [AttributeBuffers_1.BufferParameters.create(attrPos.location, 3, GL_1.GL.DataType.UnsignedShort, false, 0, 0, false)]);
this.buffers.addBuffer(indices, []);
this.positions = positions;
this.indices = indices;
this.numIndices = numIndices;
}
static create(positions, qParams, indices) {
const posBuf = AttributeBuffers_1.QBufferHandle3d.create(qParams, positions);
const indBuf = AttributeBuffers_1.BufferHandle.createBuffer(GL_1.GL.Buffer.Target.ElementArrayBuffer, indices);
if (undefined === posBuf || undefined === indBuf)
return undefined;
return new IndexedGeometryParams(posBuf, indBuf, indices.length);
}
static createFromList(positions, indices) {
return IndexedGeometryParams.create(positions.toTypedArray(), positions.params, indices);
}
get isDisposed() {
return this.buffers.isDisposed
&& this.positions.isDisposed
&& this.indices.isDisposed;
}
[Symbol.dispose]() {
(0, core_bentley_1.dispose)(this.buffers);
(0, core_bentley_1.dispose)(this.positions);
(0, core_bentley_1.dispose)(this.indices);
}
}
exports.IndexedGeometryParams = IndexedGeometryParams;
/** A geometric primitive which is rendered using gl.drawElements() with one or more vertex buffers indexed by an index buffer.
* @internal
*/
class IndexedGeometry extends CachedGeometry {
_params;
_wantWoWReversal(_target) { return false; }
constructor(params) {
super();
this._params = params;
}
get isDisposed() { return this._params.isDisposed; }
[Symbol.dispose]() {
(0, core_bentley_1.dispose)(this._params);
}
draw() {
this._params.buffers.bind();
System_1.System.instance.context.drawElements(GL_1.GL.PrimitiveType.Triangles, this._params.numIndices, GL_1.GL.DataType.UnsignedInt, 0);
this._params.buffers.unbind();
}
get qOrigin() { return this._params.positions.origin; }
get qScale() { return this._params.positions.scale; }
}
exports.IndexedGeometry = IndexedGeometry;
/** a cube of quads in normalized device coordinates for skybox rendering techniques
* @internal
*/
class SkyBoxQuads {
vertices;
vertexParams;
constructor() {
const skyBoxSz = 1.0;
const qVerts = new core_common_1.QPoint3dList(core_common_1.QParams3d.fromNormalizedRange());
// NB: After applying the rotation matrix in the shader, Back becomes (Bottom), etc.
// See the notes in the parens below.
// ###TODO: Make this indexed. Currently not indexed because of previous six-sided texture system.
// Back (Bottom after rotation)
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
// Front (Top after rotation)
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
// Top (Front after rotation)
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
// Bottom (Back after rotation)
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
// Left (Right after rotation)
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
// Right (Left after rotation)
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7
qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
this.vertices = qVerts.toTypedArray();
this.vertexParams = qVerts.params;
}
createParams() {
return SkyBoxGeometryParams.create(this.vertices, this.vertexParams);
}
}
/** Parameters used to construct an SkyBox
* @internal
*/
class SkyBoxGeometryParams {
buffers;
positions;
constructor(positions) {
this.buffers = AttributeBuffers_1.BuffersContainer.create();
const attrPos = AttributeMap_1.AttributeMap.findAttribute("a_pos", undefined, false);
(0, core_bentley_1.assert)(attrPos !== undefined);
this.buffers.addBuffer(positions, [AttributeBuffers_1.BufferParameters.create(attrPos.location, 3, GL_1.GL.DataType.UnsignedShort, false, 0, 0, false)]);
this.positions = positions;
}
static create(positions, qparams) {
const posBuf = AttributeBuffers_1.QBufferHandle3d.create(qparams, positions);
if (undefined === posBuf)
return undefined;
return new SkyBoxGeometryParams(posBuf);
}
get isDisposed() { return this.buffers.isDisposed && this.positions.isDisposed; }
[Symbol.dispose]() {
(0, core_bentley_1.dispose)(this.buffers);
(0, core_bentley_1.dispose)(this.positions);
}
}
exports.SkyBoxGeometryParams = SkyBoxGeometryParams;
/** @internal */
(function (SkyBoxQuads) {
let skyBoxQuads;
function getInstance() {
if (undefined === skyBoxQuads)
skyBoxQuads = new SkyBoxQuads();
return skyBoxQuads;
}
SkyBoxQuads.getInstance = getInstance;
})(SkyBoxQuads || (SkyBoxQuads = {}));
/** Geometry used for view-space rendering techniques.
* @internal
*/
class SkyBoxQuadsGeometry extends CachedGeometry {
_techniqueId;
cube;
_params;
constructor(ndxGeomParams, texture) {
super();
this.cube = texture;
this._techniqueId = 23 /* TechniqueId.SkyBox */;
this._params = ndxGeomParams;
}
static create(texture) {
const sbxGeomParams = SkyBoxQuads.getInstance().createParams();
return undefined !== sbxGeomParams ? new SkyBoxQuadsGeometry(sbxGeomParams, texture) : undefined;
}
collectStatistics(_stats) {
// Not interested in tracking this.
}
get techniqueId() { return this._techniqueId; }
getPass() { return "skybox"; }
get renderOrder() { return 3 /* RenderOrder.UnlitSurface */; }
draw() {
this._params.buffers.bind();
System_1.System.instance.context.drawArrays(GL_1.GL.PrimitiveType.Triangles, 0, 36);
this._params.buffers.unbind();
}
get qOrigin() { return this._params.positions.origin; }
get qScale() { return this._params.positions.scale; }
get isDisposed() { return this._params.isDisposed; }
[Symbol.dispose]() {
(0, core_bentley_1.dispose)(this._params);
}
_wantWoWReversal(_target) { return false; }
}
exports.SkyBoxQuadsGeometry = SkyBoxQuadsGeometry;
/** A quad with its corners mapped to the dimensions as the viewport, used for special rendering techniques.
* @internal
*/
class ViewportQuad {
vertices;
vertexParams;
indices = new Uint32Array(6);
constructor() {
const pt = new core_geometry_1.Point3d(-1, -1, 0);
const vertices = new core_common_1.QPoint3dList(core_common_1.QParams3d.fromNormalizedRange());
vertices.add(pt);
pt.x = 1;
vertices.add(pt);
pt.y = 1;
vertices.add(pt);
pt.x = -1;
vertices.add(pt);
this.vertices = vertices.toTypedArray();
this.vertexParams = vertices.params;
this.indices[0] = 0;
this.indices[1] = 1;
this.indices[2] = 2;
this.indices[3] = 0;
this.indices[4] = 2;
this.indices[5] = 3;
}
createParams() {
return IndexedGeometryParams.create(this.vertices, this.vertexParams, this.indices);
}
}
/** @internal */
(function (ViewportQuad) {
let viewportQuad;
function getInstance() {
if (undefined === viewportQuad)
viewportQuad = new ViewportQuad();
return viewportQuad;
}
ViewportQuad.getInstance = getInstance;
})(ViewportQuad || (ViewportQuad = {}));
/** Geometry used for view-space rendering techniques.
* @internal
*/
class ViewportQuadGeometry extends IndexedGeometry {
_techniqueId;
constructor(params, techniqueId) {
super(params);
this._techniqueId = techniqueId;
}
static create(techniqueId) {
const params = ViewportQuad.getInstance().createParams();
return undefined !== params ? new this(params, techniqueId) : undefined;
}
get techniqueId() { return this._techniqueId; }
getPass() { return "opaque"; }
get renderOrder() { return 3 /* RenderOrder.UnlitSurface */; }
collectStatistics(_stats) {
// NB: These don't really count...
}
}
exports.ViewportQuadGeometry = ViewportQuadGeometry;
/** Geometry used for view-space rendering techniques which involve sampling one or more textures.
* @internal
*/
class TexturedViewportQuadGeometry extends ViewportQuadGeometry {
_textures;
constructor(params, techniqueId, textures) {
super(params, techniqueId);
this._textures = textures;
// TypeScript compiler will happily accept TextureHandle (or any other type) in place of WebGLTexture.
// There is no such 'type' as WebGLTexture at run-time.
(0, core_bentley_1.assert)(this._textures.every((tx) => !(tx instanceof Texture_1.TextureHandle)));
}
static createTexturedViewportQuadGeometry(techniqueId, textures) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params)
return undefined;
return new this(params, techniqueId, textures);
}
}
exports.TexturedViewportQuadGeometry = TexturedViewportQuadGeometry;
/** Geometry used for rendering default gradient-style or single texture spherical skybox.
* @internal
*/
class SkySphereViewportQuadGeometry extends ViewportQuadGeometry {
worldPos; // LeftBottom, RightBottom, RightTop, LeftTop worl pos of frustum at mid depth.
typeAndExponents; // [0] -1.0 for 2-color gradient, 1.0 for 4-color gradient, 0.0 for texture; [1] sky exponent (4-color only) [2] ground exponent (4-color only)
zOffset;
rotation;
zenithColor;
skyColor;
groundColor;
nadirColor;
skyTexture;
_worldPosBuff;
_isWorldPosSet = false;
initWorldPos(target) {
if (this._isWorldPosSet)
return;
this._isWorldPosSet = true;
this._setPointsFromFrustum(target);
this._worldPosBuff.bindData(this.worldPos, GL_1.GL.Buffer.Usage.StreamDraw);
const attrWorldPos = AttributeMap_1.AttributeMap.findAttribute("a_worldPos", 24 /* TechniqueId.SkySphereGradient */, false);
(0, core_bentley_1.assert)(attrWorldPos !== undefined);
this._params.buffers.addBuffer(this._worldPosBuff, [AttributeBuffers_1.BufferParameters.create(attrWorldPos.location, 3, GL_1.GL.DataType.Float, false, 0, 0, false)]);
}
_setPointsFromFrustum(target) {
const frustum = target.planFrustum;
const wp = this.worldPos;
const lb = frustum.getCorner(core_common_1.Npc.LeftBottomRear).interpolate(0.5, frustum.getCorner(core_common_1.Npc.LeftBottomFront), scratchPoint3a);
const rb = frustum.getCorner(core_common_1.Npc.RightBottomRear).interpolate(0.5, frustum.getCorner(core_common_1.Npc.RightBottomFront), scratchPoint3b);
const rt = frustum.getCorner(core_common_1.Npc.RightTopRear).interpolate(0.5, frustum.getCorner(core_common_1.Npc.RightTopFront), scratchPoint3c);
if (!target.plan.backgroundMapOn || !target.plan.isGlobeMode3D) {
wp[0] = lb.x;
wp[1] = lb.y;
wp[2] = lb.z;
wp[3] = rb.x;
wp[4] = rb.y;
wp[5] = rb.z;
wp[6] = rt.x;
wp[7] = rt.y;
wp[8] = rt.z;
const lt = frustum.getCorner(core_common_1.Npc.LeftTopRear).interpolate(0.5, frustum.getCorner(core_common_1.Npc.LeftTopFront), scratchPoint3d);
wp[9] = lt.x;
wp[10] = lt.y;
wp[11] = lt.z;
}
else {
// Need to fake a different frustum to orient the 4 corners properly.
// First find true frustum center & size.
const fCenter = lb.interpolate(0.5, rt, scratchPoint3d);
const upScreen = core_geometry_1.Vector3d.createStartEnd(rb, rt, scratchVec3a);
let rightScreen = core_geometry_1.Vector3d.createStartEnd(lb, rb, scratchVec3b);
const halfWidth = upScreen.magnitude() * 0.5;
const halfHeight = rightScreen.magnitude() * 0.5;
// Find the projection of the globe up onto the frustum plane.
upScreen.normalizeInPlace();
rightScreen.normalizeInPlace();
const projUp = target.plan.upVector.dotProduct(upScreen);
const projRt = target.plan.upVector.dotProduct(rightScreen);
// Find camera position (create one for ortho).
let camPos;
if (2 /* FrustumUniformType.Perspective */ === target.uniforms.frustum.type) {
const farLowerLeft = frustum.getCorner(core_common_1.Npc.LeftBottomRear);
const nearLowerLeft = frustum.getCorner(core_common_1.Npc.LeftBottomFront);
const scale = 1.0 / (1.0 - target.planFraction);
const zVec = core_geometry_1.Vector3d.createStartEnd(farLowerLeft, nearLowerLeft, scratchVec3c);
camPos = (0, FrustumUniforms_1.fromSumOf)(farLowerLeft, zVec, scale, scratchPoint3a);
}
else {
const delta = core_geometry_1.Vector3d.createStartEnd(frustum.getCorner(core_common_1.Npc.LeftBottomRear), frustum.getCorner(core_common_1.Npc.LeftBottomFront), scratchVec3c);
const pseudoCameraHalfAngle = 22.5;
const diagonal = frustum.getCorner(core_common_1.Npc.LeftBottomRear).distance(frustum.getCorner(core_common_1.Npc.RightTopRear));
const focalLength = diagonal / (2 * Math.atan(pseudoCameraHalfAngle * core_geometry_1.Angle.radiansPerDegree));
let zScale = focalLength / delta.magnitude();
if (zScale < 1.000001)
zScale = 1.000001; // prevent worldEye front being on or inside the frustum front plane
camPos = core_geometry_1.Point3d.createAdd3Scaled(frustum.getCorner(core_common_1.Npc.LeftBottomRear), .5, frustum.getCorner(core_common_1.Npc.RightTopRear), .5, delta, zScale, scratchPoint3a);
}
// Compute the distance from the camera to the frustum center.
const camDist = camPos.distance(fCenter);
// Now use a fixed camera direction and compute a new frustum center.
const camDir = core_geometry_1.Vector3d.create(0.0, 1.0, 0.0, scratchVec3c);
fCenter.setFromPoint3d(camPos);
fCenter.addScaledInPlace(camDir, camDist);
// Create an up vector that mimics the projection of the globl up onto the real frustum.
upScreen.set(projRt, 0.0, projUp);
upScreen.normalizeInPlace();
// Compute a new right vector and then compute the 4 points for the sky.
rightScreen = upScreen.crossProduct(camDir, scratchVec3b);
upScreen.scaleInPlace(halfHeight);
rightScreen.scaleInPlace(halfWidth);
wp[0] = fCenter.x - rightScreen.x - upScreen.x; // left bottom
wp[1] = fCenter.y - rightScreen.y - upScreen.y;
wp[2] = fCenter.z - rightScreen.z - upScreen.z;
wp[3] = fCenter.x + rightScreen.x - upScreen.x; // right bottom
wp[4] = fCenter.y + rightScreen.y - upScreen.y;
wp[5] = fCenter.z + rightScreen.z - upScreen.z;
wp[6] = fCenter.x + rightScreen.x + upScreen.x; // right top
wp[7] = fCenter.y + rightScreen.y + upScreen.y;
wp[8] = fCenter.z + rightScreen.z + upScreen.z;
wp[9] = fCenter.x - rightScreen.x + upScreen.x; // left top
wp[10] = fCenter.y - rightScreen.y + upScreen.y;
wp[11] = fCenter.z - rightScreen.z + upScreen.z;
}
}
constructor(params, skybox, techniqueId) {
super(params, techniqueId);
this.worldPos = new Float32Array(4 * 3);
this._worldPosBuff = new AttributeBuffers_1.BufferHandle(GL_1.GL.Buffer.Target.ArrayBuffer);
this.typeAndExponents = new Float32Array(3);
this.zenithColor = new Float32Array(3);
this.skyColor = new Float32Array(3);
this.groundColor = new Float32Array(3);
this.nadirColor = new Float32Array(3);
this.zOffset = skybox.zOffset;
this.rotation = "sphere" === skybox.type ? skybox.rotation : 0;
if (skybox.type === "sphere") {
this.skyTexture = skybox.texture;
this.typeAndExponents[0] = 0.0;
this.typeAndExponents[1] = 1.0;
this.typeAndExponents[2] = 1.0;
this.zenithColor[0] = 0.0;
this.zenithColor[1] = 0.0;
this.zenithColor[2] = 0.0;
this.nadirColor[0] = 0.0;
this.nadirColor[1] = 0.0;
this.nadirColor[2] = 0.0;
this.skyColor[0] = 0.0;
this.skyColor[1] = 0.0;
this.skyColor[2] = 0.0;
this.groundColor[0] = 0.0;
this.groundColor[1] = 0.0;
this.groundColor[2] = 0.0;
}
else {
const gradient = skybox.gradient;
this.zenithColor[0] = gradient.zenithColor.colors.r / 255.0;
this.zenithColor[1] = gradient.zenithColor.colors.g / 255.0;
this.zenithColor[2] = gradient.zenithColor.colors.b / 255.0;
this.nadirColor[0] = gradient.nadirColor.colors.r / 255.0;
this.nadirColor[1] = gradient.nadirColor.colors.g / 255.0;
this.nadirColor[2] = gradient.nadirColor.colors.b / 255.0;
if (gradient.twoColor) {
this.typeAndExponents[0] = -1.0;
this.typeAndExponents[1] = 4.0;
this.typeAndExponents[2] = 4.0;
this.skyColor[0] = 0.0;
this.skyColor[1] = 0.0;
this.skyColor[2] = 0.0;
this.groundColor[0] = 0.0;
this.groundColor[1] = 0.0;
this.groundColor[2] = 0.0;
}
else {
this.typeAndExponents[0] = 1.0;
this.typeAndExponents[1] = gradient.skyExponent;
this.typeAndExponents[2] = gradient.groundExponent;
this.skyColor[0] = gradient.skyColor.colors.r / 255.0;
this.skyColor[1] = gradient.skyColor.colors.g / 255.0;
this.skyColor[2] = gradient.skyColor.colors.b / 255.0;
this.groundColor[0] = gradient.groundColor.colors.r / 255.0;
this.groundColor[1] = gradient.groundColor.colors.g / 255.0;
this.groundColor[2] = gradient.groundColor.colors.b / 255.0;
}
}
}
static createGeometry(skybox) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params)
return undefined;
const technique = "sphere" === skybox.type ? 25 /* TechniqueId.SkySphereTexture */ : 24 /* TechniqueId.SkySphereGradient */;
return new SkySphereViewportQuadGeometry(params, skybox, technique);
}
get isDisposed() { return super.isDisposed && this._worldPosBuff.isDisposed; }
[Symbol.dispose]() {
super[Symbol.dispose]();
(0, core_bentley_1.dispose)(this._worldPosBuff);
}
}
exports.SkySphereViewportQuadGeometry = SkySphereViewportQuadGeometry;
/** Geometry used when rendering ambient occlusion information to an output texture
* @internal
*/
class AmbientOcclusionGeometry extends TexturedViewportQuadGeometry {
static createGeometry(depthAndOrder, depth) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params) {
return undefined;
}
// Will derive positions and normals from depthAndOrder.
return new AmbientOcclusionGeometry(params, [depth, depthAndOrder]);
}
get depthAndOrder() { return this._textures[1]; }
get depth() { return this._textures[0]; }
get noise() { return System_1.System.instance.noiseTexture.getHandle(); }
constructor(params, textures) {
super(params, 26 /* TechniqueId.AmbientOcclusion */, textures);
}
}
exports.AmbientOcclusionGeometry = AmbientOcclusionGeometry;
/** @internal */
var BlurType;
(function (BlurType) {
BlurType[BlurType["NoTest"] = 0] = "NoTest";
BlurType[BlurType["TestOrder"] = 1] = "TestOrder";
})(BlurType || (exports.BlurType = BlurType = {}));
/** @internal */
class BlurGeometry extends TexturedViewportQuadGeometry {
blurDir;
static createGeometry(texToBlur, depthAndOrder, depthAndOrderHidden, blurDir, blurType) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params) {
return undefined;
}
if (undefined === depthAndOrderHidden || BlurType.NoTest === blurType)
return new BlurGeometry(params, [texToBlur, depthAndOrder], blurDir, blurType);
else
return new BlurGeometry(params, [texToBlur, depthAndOrder, depthAndOrderHidden], blurDir, blurType);
}
get textureToBlur() { return this._textures[0]; }
get depthAndOrder() { return this._textures[1]; }
get depthAndOrderHidden() { return this._textures[2]; }
constructor(params, textures, blurDir, blurType) {
super(params, BlurType.NoTest === blurType ? 27 /* TechniqueId.Blur */ : 28 /* TechniqueId.BlurTestOrder */, textures);
this.blurDir = blurDir;
}
}
exports.BlurGeometry = BlurGeometry;
/** @internal */
class EDLCalcBasicGeometry extends TexturedViewportQuadGeometry {
texInfo = new Float32Array(3);
static createGeometry(colorBuffer, depthBuffer, width, height) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params)
return undefined;
return new EDLCalcBasicGeometry(params, [colorBuffer, depthBuffer], width, height);
}
get colorTexture() { return this._textures[0]; }
get depthTexture() { return this._textures[1]; }
constructor(params, textures, width, height) {
super(params, 34 /* TechniqueId.EDLCalcBasic */, textures);
this.texInfo[0] = 1.0 / width;
this.texInfo[1] = 1.0 / height;
this.texInfo[2] = 1.0;
}
}
exports.EDLCalcBasicGeometry = EDLCalcBasicGeometry;
/** @internal */
class EDLCalcFullGeometry extends TexturedViewportQuadGeometry {
texInfo = new Float32Array(3);
static createGeometry(colorBuffer, depthBuffer, scale, width, height) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params)
return undefined;
return new EDLCalcFullGeometry(params, [colorBuffer, depthBuffer], scale, width, height);
}
get colorTexture() { return this._textures[0]; }
get depthTexture() { return this._textures[1]; }
constructor(params, textures, scale, width, height) {
super(params, 35 /* TechniqueId.EDLCalcFull */, textures);
this.texInfo[0] = 1.0 / width;
this.texInfo[1] = 1.0 / height;
this.texInfo[2] = scale;
}
}
exports.EDLCalcFullGeometry = EDLCalcFullGeometry;
/** @internal */
class EDLFilterGeometry extends TexturedViewportQuadGeometry {
texInfo = new Float32Array(3);
static createGeometry(colorBuffer, depthBuffer, scale, width, height) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params)
return undefined;
return new EDLFilterGeometry(params, [colorBuffer, depthBuffer], scale, width, height);
}
get colorTexture() { return this._textures[0]; }
get depthTexture() { return this._textures[1]; }
constructor(params, textures, scale, width, height) {
super(params, 36 /* TechniqueId.EDLFilter */, textures);
this.texInfo[0] = 1.0 / width;
this.texInfo[1] = 1.0 / height;
this.texInfo[2] = scale;
}
}
exports.EDLFilterGeometry = EDLFilterGeometry;
/** @internal */
class EDLMixGeometry extends TexturedViewportQuadGeometry {
static createGeometry(colorTexture1, colorTexture2, colorTexture4) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params)
return undefined;
return new EDLMixGeometry(params, [colorTexture1, colorTexture2, colorTexture4]);
}
get colorTexture1() { return this._textures[0]; }
get colorTexture2() { return this._textures[1]; }
get colorTexture4() { return this._textures[2]; }
constructor(params, textures) {
super(params, 37 /* TechniqueId.EDLMix */, textures);
}
}
exports.EDLMixGeometry = EDLMixGeometry;
/** @internal */
class EVSMGeometry extends TexturedViewportQuadGeometry {
stepSize = new Float32Array(2);
static createGeometry(depthBuffer, width, height) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params)
return undefined;
return new EVSMGeometry(params, [depthBuffer], width, height);
}
get depthTexture() { return this._textures[0]; }
constructor(params, textures, width, height) {
super(params, 22 /* TechniqueId.EVSMFromDepth */, textures);
this.stepSize[0] = 1.0 / width;
this.stepSize[1] = 1.0 / height;
}
}
exports.EVSMGeometry = EVSMGeometry;
/** Geometry used during the 'composite' pass to apply transparency and/or hilite effects.
* @internal
*/
class CompositeGeometry extends TexturedViewportQuadGeometry {
static createGeometry(opaque, accum, reveal, hilite) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params)
return undefined;
const textures = [opaque, accum, reveal, hilite];
return new CompositeGeometry(params, textures);
}
get opaque() { return this._textures[0]; }
get accum() { return this._textures[1]; }
get reveal() { return this._textures[2]; }
get hilite() { return this._textures[3]; }
get occlusion() {
return this._textures.length > 4 ? this._textures[4] : undefined;
}
set occlusion(occlusion) {
(0, core_bentley_1.assert)((undefined === occlusion) === (undefined !== this.occlusion));
if (undefined !== occlusion)
this._textures[4] = occlusion;
else
this._textures.length = 4;
}
// Invoked each frame to determine the appropriate Technique to use.
update(flags) { this._techniqueId = this.determineTechnique(flags); }
determineTechnique(flags) {
return (0, TechniqueId_1.computeCompositeTechniqueId)(flags);
}
constructor(params, textures) {
super(params, 9 /* TechniqueId.CompositeHilite */, textures);
(0, core_bentley_1.assert)(4 <= this._textures.length);
}
}
exports.CompositeGeometry = CompositeGeometry;
/** Geometry used to ping-pong the pick buffer data in between opaque passes.
* @internal
*/
class CopyPickBufferGeometry extends TexturedViewportQuadGeometry {
static createGeometry(featureId, depthAndOrder) {
const params = ViewportQuad.getInstance().createParams();
if (undefined !== params) {
return new CopyPickBufferGeometry(params, [featureId, depthAndOrder]);
}
else {
return undefined;
}
}
get featureId() { return this._textures[0]; }
get depthAndOrder() { return this._textures[1]; }
constructor(params, textures) {
super(params, 17 /* TechniqueId.CopyPickBuffers */, textures);
}
}
exports.CopyPickBufferGeometry = CopyPickBufferGeometry;
class CombineTexturesGeometry extends TexturedViewportQuadGeometry {
static createGeometry(texture0, texture1) {
const params = ViewportQuad.getInstance().createParams();
if (undefined !== params) {
return new CombineTexturesGeometry(params, [texture0, texture1]);
}
else {
return undefined;
}
}
get texture0() { return this._textures[0]; }
get texture1() { return this._textures[1]; }
constructor(params, textures) {
super(params, 29 /* TechniqueId.CombineTextures */, textures);
}
}
exports.CombineTexturesGeometry = CombineTexturesGeometry;
class Combine3TexturesGeometry extends TexturedViewportQuadGeometry {
static createGeometry(texture0, texture1, texture2) {
const params = ViewportQuad.getInstance().createParams();
if (undefined !== params) {
return new Combine3TexturesGeometry(params, [texture0, texture1, texture2]);
}
else {
return undefined;
}
}
get texture0() { return this._textures[0]; }
get texture1() { return this._textures[1]; }
get texture2() { return this._textures[2]; }
constructor(params, textures) {
super(params, 30 /* TechniqueId.Combine3Textures */, textures);
}
}
exports.Combine3TexturesGeometry = Combine3TexturesGeometry;
/** @internal */
class SingleTexturedViewportQuadGeometry extends TexturedViewportQuadGeometry {
static createGeometry(texture, techId) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params) {
return undefined;
}
return new SingleTexturedViewportQuadGeometry(params, texture, techId);
}
get texture() { return this._textures[0]; }
set texture(texture) { this._textures[0] = texture; }
constructor(params, texture, techId) {
super(params, techId, [texture]);
}
}
exports.SingleTexturedViewportQuadGeometry = SingleTexturedViewportQuadGeometry;
/** @internal */
var BoundaryType;
(function (BoundaryType) {
BoundaryType[BoundaryType["Outside"] = 0] = "Outside";
BoundaryType[BoundaryType["Inside"] = 1] = "Inside";
BoundaryType[BoundaryType["Selected"] = 2] = "Selected";
})(BoundaryType || (exports.BoundaryType = BoundaryType = {}));
/** @internal */
class VolumeClassifierGeometry extends SingleTexturedViewportQuadGeometry {
boundaryType = BoundaryType.Inside;
static createVCGeometry(texture) {
const params = ViewportQuad.getInstance().createParams();
if (undefined === params)
return undefined;
return new VolumeClassifierGeometry(params, texture);
}
constructor(params, texture) {
super(params, texture, 32 /* TechniqueId.VolClassSetBlend */);
}
}
exports.VolumeClassifierGeometry = VolumeClassifierGeometry;
/** A geometric primitive which renders gl points using gl.drawArrays() with one vertex buffer.
* @internal
*/
class ScreenPointsGeometry extends CachedGeometry {
_numPoints;
_origin;
_scale;
_positions;
buffers;
zTexture;
constructor(vertices, zTexture) {
super();
this.zTexture = zTexture;
this._numPoints = vertices.length;
this._positions = AttributeBuffers_1.QBufferHandle2d.create(vertices.params, vertices.toTypedArray());
this._origin = new Float32Array(3);
this._origin[0] = this._positions.params[0];
this._origin[1] = this._positions.params[1];
this._origin[2] = 0.0;
this._scale = new Float32Array(3);
this._scale[0] = this._positions.params[2];
this._scale[1] = this._positions.params[3];
this._scale[2] = this._positions.params[3]; // just copy the scale from y
this.buffers = AttributeBuffers_1.BuffersContainer.create();
const attrPos = AttributeMap_1.AttributeMap.findAttribute("a_pos", 31 /* TechniqueId.VolClassCopyZ */, false);
(0, core_bentley_1.assert)(attrPos !== undefined);
this.buffers.addBuffer(this._positions, [AttributeBuffers_1.BufferParameters.create(attrPos.location, 2, GL_1.GL.DataType.UnsignedShort, false, 0, 0, false)]);
}
static createGeometry(width, height, depth) {
const pixWidth = 2.0 / width;
const pixHeight = 2.0 / height;
const startX = pixWidth * 0.5 - 1.0;
const startY = pixHeight * 0.5 - 1.0;
const pt = new core_geometry_1.Point2d(startX, startY);
const vertices = new core_common_1.QPoint2dList(core_common_1.QParams2d.fromNormalizedRange());
for (let y = 0; y < height; ++y) {
pt.x = startX;
for (let x = 0; x < width; ++x) {
vertices.add(pt);
pt.x += pixWidth;
}
pt.y += pixHeight;
}
return new ScreenPointsGeometry(vertices, depth);
}
draw() {
this.buffers.bind();
System_1.System.instance.context.drawArrays(GL_1.GL.PrimitiveType.Points, 0, this._numPoints);
this.buffers.unbind();
}
get isDisposed() { return this.buffers.isDisposed && this._positions.isDisposed; }
[Symbol.dispose]() {
(0, core_bentley_1.dispose)(this.buffers);
(0, core_bentley_1.dispose)(this._positions);
}
collectStatistics(stats) {
stats.addBuffer(RenderMemory_1.RenderMemory.BufferType.PointStrings, this._positions.bytesUsed);
}
_wantWoWReversal(_target) { return false; }
get techniqueId() { return 31 /* TechniqueId.VolClassCopyZ */; }
getPass() { return "classification"; }
get renderOrder() { return 0 /* RenderOrder.None */; }
get qOrigin() { return this._origin; }
get qScale() { return this._scale; }
}
exports.ScreenPointsGeometry = ScreenPointsGeometry;
/** @internal */
class PolylineBuffers {
buffers;
indices;
prevIndices;
nextIndicesAndParams;
constructor(indices, prevIndices, nextIndicesAndParams) {
this.buffers = AttributeBuffers_1.BuffersContainer.create();
const attrPos = AttributeMap_1.AttributeMap.findAttribute("a_pos", 1 /* TechniqueId.Polyline */, false);
const attrPrevIndex = AttributeMap_1.AttributeMap.findAttribute("a_prevIndex", 1 /* TechniqueId.Polyline */, false);
const attrNextIndex = AttributeMap_1.AttributeMap.findAttribute("a_nextIndex", 1 /* TechniqueId.Polyline */, false);
const attrParam = AttributeMap_1.AttributeMap.findAttribute("a_param", 1 /* TechniqueId.Polyline */, false);
(0, core_bentley_1.assert)(attrPos !== undefined);
(0, core_bentley_1.assert)(attrPrevIndex !== undefined);
(0, core_bentley_1.assert)(attrNextIndex !== undefined);
(0, core_bentley_1.assert)(attrParam !== undefined);
this.buffers.addBuffer(indices, [AttributeBuffers_1.BufferParameters.create(attrPos.location, 3, GL_1.GL.DataType.UnsignedByte, false, 0, 0, false)]);
this.buffers.addBuffer(prevIndices, [AttributeBuffers_1.BufferParameters.create(attrPrevIndex.location, 3, GL_1.GL.DataType.UnsignedByte, false, 0, 0, false)]);
this.buffers.addBuffer(nextIndicesAndParams, [
AttributeBuffers_1.BufferParameters.create(attrNextIndex.location, 3, GL_1.GL.DataType.UnsignedByte, false, 4, 0, false),
AttributeBuffers_1.BufferParameters.create(attrParam.location, 1, GL_1.GL.DataType.UnsignedByte, false, 4, 3, false),
]);
this.indices = indices;
this.prevIndices = prevIndices;
this.nextIndicesAndParams = nextIndicesAndParams;
}
static create(polyline) {
const indices = AttributeBuffers_1.BufferHandle.createArrayBuffer(polyline.indices.data);
const prev = AttributeBuffers_1.BufferHandle.createArrayBuffer(polyline.prevIndices.data);
const next = AttributeBuffers_1.BufferHandle.createArrayBuffer(polyline.nextIndicesAndParams);
return undefined !== indices && undefined !== prev && undefined !== next ? new PolylineBuffers(indices, prev, next) : undefined;
}
collectStatistics(stats, type) {
stats.addBuffer(type, this.indices.bytesUsed + this.prevIndices.bytesUsed + this.nextIndicesAndParams.bytesUsed);
}
get isDisposed() {
return this.buffers.isDisposed
&& this.indices.isDisposed
&& this.prevIndices.isDisposed
&& this.nextIndicesAndParams.isDisposed;
}
[Symbol.dispose]() {
(0, core_bentley_1.dispose)(this.buffers);
(0, core_bentley_1.dispose)(this.indices);
(0, core_bentley_1.dispose)(this.prevIndices);
(0, core_bentley_1.dispose)(this.nextIndicesAndParams);
}
}
exports.PolylineBuffers = PolylineBuffers;
//# sourceMappingURL=CachedGeometry.js.map