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 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';
|
|
/**
|
* @private
|
*/
|
function DepthPlane() {
|
this._rs = undefined;
|
this._sp = undefined;
|
this._va = undefined;
|
this._command = undefined;
|
this._mode = undefined;
|
this._useLogDepth = false;
|
}
|
|
var depthQuadScratch = FeatureDetection.supportsTypedArrays() ? new Float32Array(12) : [];
|
var scratchCartesian1 = new Cartesian3();
|
var scratchCartesian2 = new Cartesian3();
|
var scratchCartesian3 = new Cartesian3();
|
var scratchCartesian4 = new Cartesian3();
|
|
function computeDepthQuad(ellipsoid, frameState) {
|
var radii = ellipsoid.radii;
|
var p = frameState.camera.positionWC;
|
|
// Find the corresponding position in the scaled space of the ellipsoid.
|
var q = Cartesian3.multiplyComponents(ellipsoid.oneOverRadii, p, scratchCartesian1);
|
|
var qMagnitude = Cartesian3.magnitude(q);
|
var qUnit = Cartesian3.normalize(q, scratchCartesian2);
|
|
// Determine the east and north directions at q.
|
var eUnit = Cartesian3.normalize(Cartesian3.cross(Cartesian3.UNIT_Z, q, scratchCartesian3), scratchCartesian3);
|
var nUnit = Cartesian3.normalize(Cartesian3.cross(qUnit, eUnit, scratchCartesian4), scratchCartesian4);
|
|
// Determine the radius of the 'limb' of the ellipsoid.
|
var wMagnitude = Math.sqrt(Cartesian3.magnitudeSquared(q) - 1.0);
|
|
// Compute the center and offsets.
|
var center = Cartesian3.multiplyByScalar(qUnit, 1.0 / qMagnitude, scratchCartesian1);
|
var scalar = wMagnitude / qMagnitude;
|
var eastOffset = Cartesian3.multiplyByScalar(eUnit, scalar, scratchCartesian2);
|
var northOffset = Cartesian3.multiplyByScalar(nUnit, scalar, scratchCartesian3);
|
|
// A conservative measure for the longitudes would be to use the min/max longitudes of the bounding frustum.
|
var upperLeft = Cartesian3.add(center, northOffset, scratchCartesian4);
|
Cartesian3.subtract(upperLeft, eastOffset, upperLeft);
|
Cartesian3.multiplyComponents(radii, upperLeft, upperLeft);
|
Cartesian3.pack(upperLeft, depthQuadScratch, 0);
|
|
var lowerLeft = Cartesian3.subtract(center, northOffset, scratchCartesian4);
|
Cartesian3.subtract(lowerLeft, eastOffset, lowerLeft);
|
Cartesian3.multiplyComponents(radii, lowerLeft, lowerLeft);
|
Cartesian3.pack(lowerLeft, depthQuadScratch, 3);
|
|
var upperRight = Cartesian3.add(center, northOffset, scratchCartesian4);
|
Cartesian3.add(upperRight, eastOffset, upperRight);
|
Cartesian3.multiplyComponents(radii, upperRight, upperRight);
|
Cartesian3.pack(upperRight, depthQuadScratch, 6);
|
|
var lowerRight = Cartesian3.subtract(center, northOffset, scratchCartesian4);
|
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;
|
}
|
|
var context = frameState.context;
|
var ellipsoid = frameState.mapProjection.ellipsoid;
|
var 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;
|
|
var vs = new ShaderSource({
|
sources : [DepthPlaneVS]
|
});
|
var fs = new ShaderSource({
|
sources : [DepthPlaneFS]
|
});
|
if (useLogDepth) {
|
var 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
|
var depthQuad = computeDepthQuad(ellipsoid, frameState);
|
|
// depth plane
|
if (!defined(this._va)) {
|
var 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;
|