| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 | import BoundingSphere from "../Core/BoundingSphere.js";import Cartesian3 from "../Core/Cartesian3.js";import ComponentDatatype from "../Core/ComponentDatatype.js";import defined from "../Core/defined.js";import FeatureDetection from "../Core/FeatureDetection.js";import Geometry from "../Core/Geometry.js";import GeometryAttribute from "../Core/GeometryAttribute.js";import OrthographicFrustum from "../Core/OrthographicFrustum.js";import PrimitiveType from "../Core/PrimitiveType.js";import BufferUsage from "../Renderer/BufferUsage.js";import DrawCommand from "../Renderer/DrawCommand.js";import Pass from "../Renderer/Pass.js";import RenderState from "../Renderer/RenderState.js";import ShaderProgram from "../Renderer/ShaderProgram.js";import ShaderSource from "../Renderer/ShaderSource.js";import VertexArray from "../Renderer/VertexArray.js";import DepthPlaneFS from "../Shaders/DepthPlaneFS.js";import DepthPlaneVS from "../Shaders/DepthPlaneVS.js";import SceneMode from "./SceneMode.js";import defaultValue from "../Core/defaultValue.js";import Ellipsoid from "../Core/Ellipsoid.js";/** * @private */function DepthPlane(depthPlaneEllipsoidOffset) {  this._rs = undefined;  this._sp = undefined;  this._va = undefined;  this._command = undefined;  this._mode = undefined;  this._useLogDepth = false;  this._ellipsoidOffset = defaultValue(depthPlaneEllipsoidOffset, 0);}const depthQuadScratch = FeatureDetection.supportsTypedArrays()  ? new Float32Array(12)  : [];const scratchCartesian1 = new Cartesian3();const scratchCartesian2 = new Cartesian3();const scratchCartesian3 = new Cartesian3();const scratchCartesian4 = new Cartesian3();const scratchCartesian5 = new Cartesian3();function computeDepthQuad(ellipsoid, frameState) {  const radii = ellipsoid.radii;  const camera = frameState.camera;  let center, eastOffset, northOffset;  if (camera.frustum instanceof OrthographicFrustum) {    center = Cartesian3.ZERO;    eastOffset = camera.rightWC;    northOffset = camera.upWC;  } else {    const p = camera.positionWC;    // Find the corresponding position in the scaled space of the ellipsoid.    const q = Cartesian3.multiplyComponents(      ellipsoid.oneOverRadii,      p,      scratchCartesian1    );    const qUnit = Cartesian3.normalize(q, scratchCartesian2);    // Determine the east and north directions at q.    const eUnit = Cartesian3.normalize(      Cartesian3.cross(Cartesian3.UNIT_Z, q, scratchCartesian3),      scratchCartesian3    );    const nUnit = Cartesian3.normalize(      Cartesian3.cross(qUnit, eUnit, scratchCartesian4),      scratchCartesian4    );    const qMagnitude = Cartesian3.magnitude(q);    // Determine the radius of the 'limb' of the ellipsoid.    const wMagnitude = Math.sqrt(qMagnitude * qMagnitude - 1.0);    // Compute the center and offsets.    center = Cartesian3.multiplyByScalar(      qUnit,      1.0 / qMagnitude,      scratchCartesian1    );    const scalar = wMagnitude / qMagnitude;    eastOffset = Cartesian3.multiplyByScalar(eUnit, scalar, scratchCartesian2);    northOffset = Cartesian3.multiplyByScalar(nUnit, scalar, scratchCartesian3);  }  // A conservative measure for the longitudes would be to use the min/max longitudes of the bounding frustum.  const upperLeft = Cartesian3.add(center, northOffset, scratchCartesian5);  Cartesian3.subtract(upperLeft, eastOffset, upperLeft);  Cartesian3.multiplyComponents(radii, upperLeft, upperLeft);  Cartesian3.pack(upperLeft, depthQuadScratch, 0);  const lowerLeft = Cartesian3.subtract(center, northOffset, scratchCartesian5);  Cartesian3.subtract(lowerLeft, eastOffset, lowerLeft);  Cartesian3.multiplyComponents(radii, lowerLeft, lowerLeft);  Cartesian3.pack(lowerLeft, depthQuadScratch, 3);  const upperRight = Cartesian3.add(center, northOffset, scratchCartesian5);  Cartesian3.add(upperRight, eastOffset, upperRight);  Cartesian3.multiplyComponents(radii, upperRight, upperRight);  Cartesian3.pack(upperRight, depthQuadScratch, 6);  const lowerRight = Cartesian3.subtract(    center,    northOffset,    scratchCartesian5  );  Cartesian3.add(lowerRight, eastOffset, lowerRight);  Cartesian3.multiplyComponents(radii, lowerRight, lowerRight);  Cartesian3.pack(lowerRight, depthQuadScratch, 9);  return depthQuadScratch;}DepthPlane.prototype.update = function (frameState) {  this._mode = frameState.mode;  if (frameState.mode !== SceneMode.SCENE3D) {    return;  }  const context = frameState.context;  // Allow offsetting the ellipsoid radius to address rendering artefacts below ellipsoid zero elevation.  const radii = frameState.mapProjection.ellipsoid.radii;  const ellipsoid = new Ellipsoid(    radii.x + this._ellipsoidOffset,    radii.y + this._ellipsoidOffset,    radii.z + this._ellipsoidOffset  );  const useLogDepth = frameState.useLogDepth;  if (!defined(this._command)) {    this._rs = RenderState.fromCache({      // Write depth, not color      cull: {        enabled: true,      },      depthTest: {        enabled: true,      },      colorMask: {        red: false,        green: false,        blue: false,        alpha: false,      },    });    this._command = new DrawCommand({      renderState: this._rs,      boundingVolume: new BoundingSphere(        Cartesian3.ZERO,        ellipsoid.maximumRadius      ),      pass: Pass.OPAQUE,      owner: this,    });  }  if (!defined(this._sp) || this._useLogDepth !== useLogDepth) {    this._useLogDepth = useLogDepth;    const vs = new ShaderSource({      sources: [DepthPlaneVS],    });    const fs = new ShaderSource({      sources: [DepthPlaneFS],    });    if (useLogDepth) {      const extension =        "#ifdef GL_EXT_frag_depth \n" +        "#extension GL_EXT_frag_depth : enable \n" +        "#endif \n\n";      fs.sources.push(extension);      fs.defines.push("LOG_DEPTH");      vs.defines.push("LOG_DEPTH");    }    this._sp = ShaderProgram.replaceCache({      shaderProgram: this._sp,      context: context,      vertexShaderSource: vs,      fragmentShaderSource: fs,      attributeLocations: {        position: 0,      },    });    this._command.shaderProgram = this._sp;  }  // update depth plane  const depthQuad = computeDepthQuad(ellipsoid, frameState);  // depth plane  if (!defined(this._va)) {    const geometry = new Geometry({      attributes: {        position: new GeometryAttribute({          componentDatatype: ComponentDatatype.FLOAT,          componentsPerAttribute: 3,          values: depthQuad,        }),      },      indices: [0, 1, 2, 2, 1, 3],      primitiveType: PrimitiveType.TRIANGLES,    });    this._va = VertexArray.fromGeometry({      context: context,      geometry: geometry,      attributeLocations: {        position: 0,      },      bufferUsage: BufferUsage.DYNAMIC_DRAW,    });    this._command.vertexArray = this._va;  } else {    this._va.getAttribute(0).vertexBuffer.copyFromArrayView(depthQuad);  }};DepthPlane.prototype.execute = function (context, passState) {  if (this._mode === SceneMode.SCENE3D) {    this._command.execute(context, passState);  }};DepthPlane.prototype.isDestroyed = function () {  return false;};DepthPlane.prototype.destroy = function () {  this._sp = this._sp && this._sp.destroy();  this._va = this._va && this._va.destroy();};export default DepthPlane;
 |