DepthPlane.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import BoundingSphere from '../Core/BoundingSphere.js';
  2. import Cartesian3 from '../Core/Cartesian3.js';
  3. import ComponentDatatype from '../Core/ComponentDatatype.js';
  4. import defined from '../Core/defined.js';
  5. import FeatureDetection from '../Core/FeatureDetection.js';
  6. import Geometry from '../Core/Geometry.js';
  7. import GeometryAttribute from '../Core/GeometryAttribute.js';
  8. import PrimitiveType from '../Core/PrimitiveType.js';
  9. import BufferUsage from '../Renderer/BufferUsage.js';
  10. import DrawCommand from '../Renderer/DrawCommand.js';
  11. import Pass from '../Renderer/Pass.js';
  12. import RenderState from '../Renderer/RenderState.js';
  13. import ShaderProgram from '../Renderer/ShaderProgram.js';
  14. import ShaderSource from '../Renderer/ShaderSource.js';
  15. import VertexArray from '../Renderer/VertexArray.js';
  16. import DepthPlaneFS from '../Shaders/DepthPlaneFS.js';
  17. import DepthPlaneVS from '../Shaders/DepthPlaneVS.js';
  18. import SceneMode from './SceneMode.js';
  19. /**
  20. * @private
  21. */
  22. function DepthPlane() {
  23. this._rs = undefined;
  24. this._sp = undefined;
  25. this._va = undefined;
  26. this._command = undefined;
  27. this._mode = undefined;
  28. this._useLogDepth = false;
  29. }
  30. var depthQuadScratch = FeatureDetection.supportsTypedArrays() ? new Float32Array(12) : [];
  31. var scratchCartesian1 = new Cartesian3();
  32. var scratchCartesian2 = new Cartesian3();
  33. var scratchCartesian3 = new Cartesian3();
  34. var scratchCartesian4 = new Cartesian3();
  35. function computeDepthQuad(ellipsoid, frameState) {
  36. var radii = ellipsoid.radii;
  37. var p = frameState.camera.positionWC;
  38. // Find the corresponding position in the scaled space of the ellipsoid.
  39. var q = Cartesian3.multiplyComponents(ellipsoid.oneOverRadii, p, scratchCartesian1);
  40. var qMagnitude = Cartesian3.magnitude(q);
  41. var qUnit = Cartesian3.normalize(q, scratchCartesian2);
  42. // Determine the east and north directions at q.
  43. var eUnit = Cartesian3.normalize(Cartesian3.cross(Cartesian3.UNIT_Z, q, scratchCartesian3), scratchCartesian3);
  44. var nUnit = Cartesian3.normalize(Cartesian3.cross(qUnit, eUnit, scratchCartesian4), scratchCartesian4);
  45. // Determine the radius of the 'limb' of the ellipsoid.
  46. var wMagnitude = Math.sqrt(Cartesian3.magnitudeSquared(q) - 1.0);
  47. // Compute the center and offsets.
  48. var center = Cartesian3.multiplyByScalar(qUnit, 1.0 / qMagnitude, scratchCartesian1);
  49. var scalar = wMagnitude / qMagnitude;
  50. var eastOffset = Cartesian3.multiplyByScalar(eUnit, scalar, scratchCartesian2);
  51. var northOffset = Cartesian3.multiplyByScalar(nUnit, scalar, scratchCartesian3);
  52. // A conservative measure for the longitudes would be to use the min/max longitudes of the bounding frustum.
  53. var upperLeft = Cartesian3.add(center, northOffset, scratchCartesian4);
  54. Cartesian3.subtract(upperLeft, eastOffset, upperLeft);
  55. Cartesian3.multiplyComponents(radii, upperLeft, upperLeft);
  56. Cartesian3.pack(upperLeft, depthQuadScratch, 0);
  57. var lowerLeft = Cartesian3.subtract(center, northOffset, scratchCartesian4);
  58. Cartesian3.subtract(lowerLeft, eastOffset, lowerLeft);
  59. Cartesian3.multiplyComponents(radii, lowerLeft, lowerLeft);
  60. Cartesian3.pack(lowerLeft, depthQuadScratch, 3);
  61. var upperRight = Cartesian3.add(center, northOffset, scratchCartesian4);
  62. Cartesian3.add(upperRight, eastOffset, upperRight);
  63. Cartesian3.multiplyComponents(radii, upperRight, upperRight);
  64. Cartesian3.pack(upperRight, depthQuadScratch, 6);
  65. var lowerRight = Cartesian3.subtract(center, northOffset, scratchCartesian4);
  66. Cartesian3.add(lowerRight, eastOffset, lowerRight);
  67. Cartesian3.multiplyComponents(radii, lowerRight, lowerRight);
  68. Cartesian3.pack(lowerRight, depthQuadScratch, 9);
  69. return depthQuadScratch;
  70. }
  71. DepthPlane.prototype.update = function(frameState) {
  72. this._mode = frameState.mode;
  73. if (frameState.mode !== SceneMode.SCENE3D) {
  74. return;
  75. }
  76. var context = frameState.context;
  77. var ellipsoid = frameState.mapProjection.ellipsoid;
  78. var useLogDepth = frameState.useLogDepth;
  79. if (!defined(this._command)) {
  80. this._rs = RenderState.fromCache({ // Write depth, not color
  81. cull : {
  82. enabled : true
  83. },
  84. depthTest : {
  85. enabled : true
  86. },
  87. colorMask : {
  88. red : false,
  89. green : false,
  90. blue : false,
  91. alpha : false
  92. }
  93. });
  94. this._command = new DrawCommand({
  95. renderState : this._rs,
  96. boundingVolume : new BoundingSphere(Cartesian3.ZERO, ellipsoid.maximumRadius),
  97. pass : Pass.OPAQUE,
  98. owner : this
  99. });
  100. }
  101. if (!defined(this._sp) || this._useLogDepth !== useLogDepth) {
  102. this._useLogDepth = useLogDepth;
  103. var vs = new ShaderSource({
  104. sources : [DepthPlaneVS]
  105. });
  106. var fs = new ShaderSource({
  107. sources : [DepthPlaneFS]
  108. });
  109. if (useLogDepth) {
  110. var extension =
  111. '#ifdef GL_EXT_frag_depth \n' +
  112. '#extension GL_EXT_frag_depth : enable \n' +
  113. '#endif \n\n';
  114. fs.sources.push(extension);
  115. fs.defines.push('LOG_DEPTH');
  116. vs.defines.push('LOG_DEPTH');
  117. vs.defines.push('DISABLE_GL_POSITION_LOG_DEPTH');
  118. }
  119. this._sp = ShaderProgram.replaceCache({
  120. shaderProgram : this._sp,
  121. context : context,
  122. vertexShaderSource : vs,
  123. fragmentShaderSource : fs,
  124. attributeLocations : {
  125. position : 0
  126. }
  127. });
  128. this._command.shaderProgram = this._sp;
  129. }
  130. // update depth plane
  131. var depthQuad = computeDepthQuad(ellipsoid, frameState);
  132. // depth plane
  133. if (!defined(this._va)) {
  134. var geometry = new Geometry({
  135. attributes : {
  136. position : new GeometryAttribute({
  137. componentDatatype : ComponentDatatype.FLOAT,
  138. componentsPerAttribute : 3,
  139. values : depthQuad
  140. })
  141. },
  142. indices : [0, 1, 2, 2, 1, 3],
  143. primitiveType : PrimitiveType.TRIANGLES
  144. });
  145. this._va = VertexArray.fromGeometry({
  146. context : context,
  147. geometry : geometry,
  148. attributeLocations : {
  149. position : 0
  150. },
  151. bufferUsage : BufferUsage.DYNAMIC_DRAW
  152. });
  153. this._command.vertexArray = this._va;
  154. } else {
  155. this._va.getAttribute(0).vertexBuffer.copyFromArrayView(depthQuad);
  156. }
  157. };
  158. DepthPlane.prototype.execute = function(context, passState) {
  159. if (this._mode === SceneMode.SCENE3D) {
  160. this._command.execute(context, passState);
  161. }
  162. };
  163. DepthPlane.prototype.isDestroyed = function() {
  164. return false;
  165. };
  166. DepthPlane.prototype.destroy = function() {
  167. this._sp = this._sp && this._sp.destroy();
  168. this._va = this._va && this._va.destroy();
  169. };
  170. export default DepthPlane;