UNPKG

@itwin/core-frontend

Version:
994 lines • 47.9 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module WebGL */ Object.defineProperty(exports, "__esModule", { value: true }); exports.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