智慧水务管理系统 - 精河县供水工程综合管理平台

DepthPlane.js 7.0KB

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