GlobeDepth.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. import BoundingRectangle from "../Core/BoundingRectangle.js";
  2. import Color from "../Core/Color.js";
  3. import defined from "../Core/defined.js";
  4. import destroyObject from "../Core/destroyObject.js";
  5. import PixelFormat from "../Core/PixelFormat.js";
  6. import ClearCommand from "../Renderer/ClearCommand.js";
  7. import Framebuffer from "../Renderer/Framebuffer.js";
  8. import PixelDatatype from "../Renderer/PixelDatatype.js";
  9. import RenderState from "../Renderer/RenderState.js";
  10. import Sampler from "../Renderer/Sampler.js";
  11. import ShaderSource from "../Renderer/ShaderSource.js";
  12. import Texture from "../Renderer/Texture.js";
  13. import PassThrough from "../Shaders/PostProcessStages/PassThrough.js";
  14. import PassThroughDepth from "../Shaders/PostProcessStages/PassThroughDepth.js";
  15. import BlendingState from "./BlendingState.js";
  16. import StencilConstants from "./StencilConstants.js";
  17. import StencilFunction from "./StencilFunction.js";
  18. import StencilOperation from "./StencilOperation.js";
  19. /**
  20. * @private
  21. */
  22. function GlobeDepth() {
  23. this._globeColorTexture = undefined;
  24. this._primitiveColorTexture = undefined;
  25. this._depthStencilTexture = undefined;
  26. this._globeDepthTexture = undefined;
  27. this._tempGlobeDepthTexture = undefined;
  28. this._tempCopyDepthTexture = undefined;
  29. this._globeColorFramebuffer = undefined;
  30. this._primitiveColorFramebuffer = undefined;
  31. this._copyDepthFramebuffer = undefined;
  32. this._tempCopyDepthFramebuffer = undefined;
  33. this._updateDepthFramebuffer = undefined;
  34. this._clearGlobeColorCommand = undefined;
  35. this._clearPrimitiveColorCommand = undefined;
  36. this._copyColorCommand = undefined;
  37. this._copyDepthCommand = undefined;
  38. this._tempCopyDepthCommand = undefined;
  39. this._updateDepthCommand = undefined;
  40. this._mergeColorCommand = undefined;
  41. this._viewport = new BoundingRectangle();
  42. this._rs = undefined;
  43. this._rsBlend = undefined;
  44. this._rsUpdate = undefined;
  45. this._useScissorTest = false;
  46. this._scissorRectangle = undefined;
  47. this._useLogDepth = undefined;
  48. this._useHdr = undefined;
  49. this._clearGlobeDepth = undefined;
  50. this._debugGlobeDepthViewportCommand = undefined;
  51. }
  52. Object.defineProperties(GlobeDepth.prototype, {
  53. framebuffer: {
  54. get: function () {
  55. return this._globeColorFramebuffer;
  56. },
  57. },
  58. primitiveFramebuffer: {
  59. get: function () {
  60. return this._primitiveColorFramebuffer;
  61. },
  62. },
  63. });
  64. function executeDebugGlobeDepth(globeDepth, context, passState, useLogDepth) {
  65. if (
  66. !defined(globeDepth._debugGlobeDepthViewportCommand) ||
  67. useLogDepth !== globeDepth._useLogDepth
  68. ) {
  69. var fsSource =
  70. "uniform sampler2D u_depthTexture;\n" +
  71. "varying vec2 v_textureCoordinates;\n" +
  72. "void main()\n" +
  73. "{\n" +
  74. " float z_window = czm_unpackDepth(texture2D(u_depthTexture, v_textureCoordinates));\n" +
  75. " z_window = czm_reverseLogDepth(z_window); \n" +
  76. " float n_range = czm_depthRange.near;\n" +
  77. " float f_range = czm_depthRange.far;\n" +
  78. " float z_ndc = (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n" +
  79. " float scale = pow(z_ndc * 0.5 + 0.5, 8.0);\n" +
  80. " gl_FragColor = vec4(mix(vec3(0.0), vec3(1.0), scale), 1.0);\n" +
  81. "}\n";
  82. var fs = new ShaderSource({
  83. defines: [useLogDepth ? "LOG_DEPTH" : ""],
  84. sources: [fsSource],
  85. });
  86. globeDepth._debugGlobeDepthViewportCommand = context.createViewportQuadCommand(
  87. fs,
  88. {
  89. uniformMap: {
  90. u_depthTexture: function () {
  91. return globeDepth._globeDepthTexture;
  92. },
  93. },
  94. owner: globeDepth,
  95. }
  96. );
  97. globeDepth._useLogDepth = useLogDepth;
  98. }
  99. globeDepth._debugGlobeDepthViewportCommand.execute(context, passState);
  100. }
  101. function destroyTextures(globeDepth) {
  102. globeDepth._globeColorTexture =
  103. globeDepth._globeColorTexture &&
  104. !globeDepth._globeColorTexture.isDestroyed() &&
  105. globeDepth._globeColorTexture.destroy();
  106. globeDepth._depthStencilTexture =
  107. globeDepth._depthStencilTexture &&
  108. !globeDepth._depthStencilTexture.isDestroyed() &&
  109. globeDepth._depthStencilTexture.destroy();
  110. globeDepth._globeDepthTexture =
  111. globeDepth._globeDepthTexture &&
  112. !globeDepth._globeDepthTexture.isDestroyed() &&
  113. globeDepth._globeDepthTexture.destroy();
  114. }
  115. function destroyFramebuffers(globeDepth) {
  116. globeDepth._globeColorFramebuffer =
  117. globeDepth._globeColorFramebuffer &&
  118. !globeDepth._globeColorFramebuffer.isDestroyed() &&
  119. globeDepth._globeColorFramebuffer.destroy();
  120. globeDepth._copyDepthFramebuffer =
  121. globeDepth._copyDepthFramebuffer &&
  122. !globeDepth._copyDepthFramebuffer.isDestroyed() &&
  123. globeDepth._copyDepthFramebuffer.destroy();
  124. }
  125. function destroyUpdateDepthResources(globeDepth) {
  126. globeDepth._tempCopyDepthFramebuffer =
  127. globeDepth._tempCopyDepthFramebuffer &&
  128. !globeDepth._tempCopyDepthFramebuffer.isDestroyed() &&
  129. globeDepth._tempCopyDepthFramebuffer.destroy();
  130. globeDepth._updateDepthFramebuffer =
  131. globeDepth._updateDepthFramebuffer &&
  132. !globeDepth._updateDepthFramebuffer.isDestroyed() &&
  133. globeDepth._updateDepthFramebuffer.destroy();
  134. globeDepth._tempGlobeDepthTexture =
  135. globeDepth._tempGlobeDepthTexture &&
  136. !globeDepth._tempGlobeDepthTexture.isDestroyed() &&
  137. globeDepth._tempGlobeDepthTexture.destroy();
  138. }
  139. function createUpdateDepthResources(
  140. globeDepth,
  141. context,
  142. width,
  143. height,
  144. passState
  145. ) {
  146. globeDepth._tempGlobeDepthTexture = new Texture({
  147. context: context,
  148. width: width,
  149. height: height,
  150. pixelFormat: PixelFormat.RGBA,
  151. pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
  152. sampler: Sampler.NEAREST,
  153. });
  154. globeDepth._tempCopyDepthFramebuffer = new Framebuffer({
  155. context: context,
  156. colorTextures: [globeDepth._tempGlobeDepthTexture],
  157. destroyAttachments: false,
  158. });
  159. globeDepth._updateDepthFramebuffer = new Framebuffer({
  160. context: context,
  161. colorTextures: [globeDepth._globeDepthTexture],
  162. depthStencilTexture: passState.framebuffer.depthStencilTexture,
  163. destroyAttachments: false,
  164. });
  165. }
  166. function createTextures(globeDepth, context, width, height, hdr) {
  167. var pixelDatatype = hdr
  168. ? context.halfFloatingPointTexture
  169. ? PixelDatatype.HALF_FLOAT
  170. : PixelDatatype.FLOAT
  171. : PixelDatatype.UNSIGNED_BYTE;
  172. globeDepth._globeColorTexture = new Texture({
  173. context: context,
  174. width: width,
  175. height: height,
  176. pixelFormat: PixelFormat.RGBA,
  177. pixelDatatype: pixelDatatype,
  178. sampler: Sampler.NEAREST,
  179. });
  180. globeDepth._depthStencilTexture = new Texture({
  181. context: context,
  182. width: width,
  183. height: height,
  184. pixelFormat: PixelFormat.DEPTH_STENCIL,
  185. pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8,
  186. });
  187. globeDepth._globeDepthTexture = new Texture({
  188. context: context,
  189. width: width,
  190. height: height,
  191. pixelFormat: PixelFormat.RGBA,
  192. pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
  193. sampler: Sampler.NEAREST,
  194. });
  195. }
  196. function createFramebuffers(globeDepth, context) {
  197. globeDepth._globeColorFramebuffer = new Framebuffer({
  198. context: context,
  199. colorTextures: [globeDepth._globeColorTexture],
  200. depthStencilTexture: globeDepth._depthStencilTexture,
  201. destroyAttachments: false,
  202. });
  203. globeDepth._copyDepthFramebuffer = new Framebuffer({
  204. context: context,
  205. colorTextures: [globeDepth._globeDepthTexture],
  206. destroyAttachments: false,
  207. });
  208. }
  209. function createPrimitiveFramebuffer(globeDepth, context, width, height, hdr) {
  210. var pixelDatatype = hdr
  211. ? context.halfFloatingPointTexture
  212. ? PixelDatatype.HALF_FLOAT
  213. : PixelDatatype.FLOAT
  214. : PixelDatatype.UNSIGNED_BYTE;
  215. globeDepth._primitiveColorTexture = new Texture({
  216. context: context,
  217. width: width,
  218. height: height,
  219. pixelFormat: PixelFormat.RGBA,
  220. pixelDatatype: pixelDatatype,
  221. sampler: Sampler.NEAREST,
  222. });
  223. globeDepth._primitiveColorFramebuffer = new Framebuffer({
  224. context: context,
  225. colorTextures: [globeDepth._primitiveColorTexture],
  226. depthStencilTexture: globeDepth._depthStencilTexture,
  227. destroyAttachments: false,
  228. });
  229. }
  230. function destroyPrimitiveFramebuffer(globeDepth) {
  231. globeDepth._primitiveColorTexture =
  232. globeDepth._primitiveColorTexture &&
  233. !globeDepth._primitiveColorTexture.isDestroyed() &&
  234. globeDepth._primitiveColorTexture.destroy();
  235. globeDepth._primitiveColorFramebuffer =
  236. globeDepth._primitiveColorFramebuffer &&
  237. !globeDepth._primitiveColorFramebuffer.isDestroyed() &&
  238. globeDepth._primitiveColorFramebuffer.destroy();
  239. }
  240. function updateFramebuffers(
  241. globeDepth,
  242. context,
  243. width,
  244. height,
  245. hdr,
  246. clearGlobeDepth
  247. ) {
  248. var colorTexture = globeDepth._globeColorTexture;
  249. var textureChanged =
  250. !defined(colorTexture) ||
  251. colorTexture.width !== width ||
  252. colorTexture.height !== height ||
  253. hdr !== globeDepth._useHdr;
  254. if (textureChanged) {
  255. destroyTextures(globeDepth);
  256. destroyFramebuffers(globeDepth);
  257. createTextures(globeDepth, context, width, height, hdr, clearGlobeDepth);
  258. createFramebuffers(globeDepth, context, clearGlobeDepth);
  259. }
  260. if (textureChanged || clearGlobeDepth !== globeDepth._clearGlobeDepth) {
  261. destroyPrimitiveFramebuffer(globeDepth);
  262. if (clearGlobeDepth) {
  263. createPrimitiveFramebuffer(globeDepth, context, width, height, hdr);
  264. }
  265. }
  266. }
  267. function updateCopyCommands(globeDepth, context, width, height, passState) {
  268. globeDepth._viewport.width = width;
  269. globeDepth._viewport.height = height;
  270. var useScissorTest = !BoundingRectangle.equals(
  271. globeDepth._viewport,
  272. passState.viewport
  273. );
  274. var updateScissor = useScissorTest !== globeDepth._useScissorTest;
  275. globeDepth._useScissorTest = useScissorTest;
  276. if (
  277. !BoundingRectangle.equals(globeDepth._scissorRectangle, passState.viewport)
  278. ) {
  279. globeDepth._scissorRectangle = BoundingRectangle.clone(
  280. passState.viewport,
  281. globeDepth._scissorRectangle
  282. );
  283. updateScissor = true;
  284. }
  285. if (
  286. !defined(globeDepth._rs) ||
  287. !BoundingRectangle.equals(globeDepth._viewport, globeDepth._rs.viewport) ||
  288. updateScissor
  289. ) {
  290. globeDepth._rs = RenderState.fromCache({
  291. viewport: globeDepth._viewport,
  292. scissorTest: {
  293. enabled: globeDepth._useScissorTest,
  294. rectangle: globeDepth._scissorRectangle,
  295. },
  296. });
  297. globeDepth._rsBlend = RenderState.fromCache({
  298. viewport: globeDepth._viewport,
  299. scissorTest: {
  300. enabled: globeDepth._useScissorTest,
  301. rectangle: globeDepth._scissorRectangle,
  302. },
  303. blending: BlendingState.ALPHA_BLEND,
  304. });
  305. // Copy packed depth only if the 3D Tiles bit is set
  306. globeDepth._rsUpdate = RenderState.fromCache({
  307. viewport: globeDepth._viewport,
  308. scissorTest: {
  309. enabled: globeDepth._useScissorTest,
  310. rectangle: globeDepth._scissorRectangle,
  311. },
  312. stencilTest: {
  313. enabled: true,
  314. frontFunction: StencilFunction.EQUAL,
  315. frontOperation: {
  316. fail: StencilOperation.KEEP,
  317. zFail: StencilOperation.KEEP,
  318. zPass: StencilOperation.KEEP,
  319. },
  320. backFunction: StencilFunction.NEVER,
  321. reference: StencilConstants.CESIUM_3D_TILE_MASK,
  322. mask: StencilConstants.CESIUM_3D_TILE_MASK,
  323. },
  324. });
  325. }
  326. if (!defined(globeDepth._copyDepthCommand)) {
  327. globeDepth._copyDepthCommand = context.createViewportQuadCommand(
  328. PassThroughDepth,
  329. {
  330. uniformMap: {
  331. u_depthTexture: function () {
  332. return globeDepth._depthStencilTexture;
  333. },
  334. },
  335. owner: globeDepth,
  336. }
  337. );
  338. }
  339. globeDepth._copyDepthCommand.framebuffer = globeDepth._copyDepthFramebuffer;
  340. globeDepth._copyDepthCommand.renderState = globeDepth._rs;
  341. if (!defined(globeDepth._copyColorCommand)) {
  342. globeDepth._copyColorCommand = context.createViewportQuadCommand(
  343. PassThrough,
  344. {
  345. uniformMap: {
  346. colorTexture: function () {
  347. return globeDepth._globeColorTexture;
  348. },
  349. },
  350. owner: globeDepth,
  351. }
  352. );
  353. }
  354. globeDepth._copyColorCommand.renderState = globeDepth._rs;
  355. if (!defined(globeDepth._tempCopyDepthCommand)) {
  356. globeDepth._tempCopyDepthCommand = context.createViewportQuadCommand(
  357. PassThroughDepth,
  358. {
  359. uniformMap: {
  360. u_depthTexture: function () {
  361. return globeDepth._tempCopyDepthTexture;
  362. },
  363. },
  364. owner: globeDepth,
  365. }
  366. );
  367. }
  368. globeDepth._tempCopyDepthCommand.framebuffer =
  369. globeDepth._tempCopyDepthFramebuffer;
  370. globeDepth._tempCopyDepthCommand.renderState = globeDepth._rs;
  371. if (!defined(globeDepth._updateDepthCommand)) {
  372. globeDepth._updateDepthCommand = context.createViewportQuadCommand(
  373. PassThrough,
  374. {
  375. uniformMap: {
  376. colorTexture: function () {
  377. return globeDepth._tempGlobeDepthTexture;
  378. },
  379. },
  380. owner: globeDepth,
  381. }
  382. );
  383. }
  384. globeDepth._updateDepthCommand.framebuffer =
  385. globeDepth._updateDepthFramebuffer;
  386. globeDepth._updateDepthCommand.renderState = globeDepth._rsUpdate;
  387. if (!defined(globeDepth._clearGlobeColorCommand)) {
  388. globeDepth._clearGlobeColorCommand = new ClearCommand({
  389. color: new Color(0.0, 0.0, 0.0, 0.0),
  390. stencil: 0.0,
  391. owner: globeDepth,
  392. });
  393. }
  394. globeDepth._clearGlobeColorCommand.framebuffer =
  395. globeDepth._globeColorFramebuffer;
  396. if (!defined(globeDepth._clearPrimitiveColorCommand)) {
  397. globeDepth._clearPrimitiveColorCommand = new ClearCommand({
  398. color: new Color(0.0, 0.0, 0.0, 0.0),
  399. stencil: 0.0,
  400. owner: globeDepth,
  401. });
  402. }
  403. globeDepth._clearPrimitiveColorCommand.framebuffer =
  404. globeDepth._primitiveColorFramebuffer;
  405. if (!defined(globeDepth._mergeColorCommand)) {
  406. globeDepth._mergeColorCommand = context.createViewportQuadCommand(
  407. PassThrough,
  408. {
  409. uniformMap: {
  410. colorTexture: function () {
  411. return globeDepth._primitiveColorTexture;
  412. },
  413. },
  414. owner: globeDepth,
  415. }
  416. );
  417. }
  418. globeDepth._mergeColorCommand.framebuffer = globeDepth._globeColorFramebuffer;
  419. globeDepth._mergeColorCommand.renderState = globeDepth._rsBlend;
  420. }
  421. GlobeDepth.prototype.executeDebugGlobeDepth = function (
  422. context,
  423. passState,
  424. useLogDepth
  425. ) {
  426. executeDebugGlobeDepth(this, context, passState, useLogDepth);
  427. };
  428. GlobeDepth.prototype.update = function (
  429. context,
  430. passState,
  431. viewport,
  432. hdr,
  433. clearGlobeDepth
  434. ) {
  435. var width = viewport.width;
  436. var height = viewport.height;
  437. updateFramebuffers(this, context, width, height, hdr, clearGlobeDepth);
  438. updateCopyCommands(this, context, width, height, passState);
  439. context.uniformState.globeDepthTexture = undefined;
  440. this._useHdr = hdr;
  441. this._clearGlobeDepth = clearGlobeDepth;
  442. };
  443. GlobeDepth.prototype.executeCopyDepth = function (context, passState) {
  444. if (defined(this._copyDepthCommand)) {
  445. this._copyDepthCommand.execute(context, passState);
  446. context.uniformState.globeDepthTexture = this._globeDepthTexture;
  447. }
  448. };
  449. GlobeDepth.prototype.executeUpdateDepth = function (
  450. context,
  451. passState,
  452. clearGlobeDepth
  453. ) {
  454. var depthTextureToCopy = passState.framebuffer.depthStencilTexture;
  455. if (clearGlobeDepth || depthTextureToCopy !== this._depthStencilTexture) {
  456. // First copy the depth to a temporary globe depth texture, then update the
  457. // main globe depth texture where the stencil bit for 3D Tiles is set.
  458. // This preserves the original globe depth except where 3D Tiles is rendered.
  459. // The additional texture and framebuffer resources are created on demand.
  460. if (defined(this._updateDepthCommand)) {
  461. if (
  462. !defined(this._updateDepthFramebuffer) ||
  463. this._updateDepthFramebuffer.depthStencilTexture !==
  464. depthTextureToCopy ||
  465. this._updateDepthFramebuffer.getColorTexture(0) !==
  466. this._globeDepthTexture
  467. ) {
  468. var width = this._globeDepthTexture.width;
  469. var height = this._globeDepthTexture.height;
  470. destroyUpdateDepthResources(this);
  471. createUpdateDepthResources(this, context, width, height, passState);
  472. updateCopyCommands(this, context, width, height, passState);
  473. }
  474. this._tempCopyDepthTexture = depthTextureToCopy;
  475. this._tempCopyDepthCommand.execute(context, passState);
  476. this._updateDepthCommand.execute(context, passState);
  477. }
  478. return;
  479. }
  480. // Fast path - the depth texture can be copied normally.
  481. if (defined(this._copyDepthCommand)) {
  482. this._copyDepthCommand.execute(context, passState);
  483. }
  484. };
  485. GlobeDepth.prototype.executeCopyColor = function (context, passState) {
  486. if (defined(this._copyColorCommand)) {
  487. this._copyColorCommand.execute(context, passState);
  488. }
  489. };
  490. GlobeDepth.prototype.executeMergeColor = function (context, passState) {
  491. if (defined(this._mergeColorCommand)) {
  492. this._mergeColorCommand.execute(context, passState);
  493. }
  494. };
  495. GlobeDepth.prototype.clear = function (context, passState, clearColor) {
  496. var clear = this._clearGlobeColorCommand;
  497. if (defined(clear)) {
  498. Color.clone(clearColor, clear.color);
  499. clear.execute(context, passState);
  500. }
  501. clear = this._clearPrimitiveColorCommand;
  502. if (defined(clear) && defined(this._primitiveColorFramebuffer)) {
  503. clear.execute(context, passState);
  504. }
  505. };
  506. GlobeDepth.prototype.isDestroyed = function () {
  507. return false;
  508. };
  509. GlobeDepth.prototype.destroy = function () {
  510. destroyTextures(this);
  511. destroyFramebuffers(this);
  512. destroyPrimitiveFramebuffer(this);
  513. destroyUpdateDepthResources(this);
  514. if (defined(this._copyColorCommand)) {
  515. this._copyColorCommand.shaderProgram = this._copyColorCommand.shaderProgram.destroy();
  516. }
  517. if (defined(this._copyDepthCommand)) {
  518. this._copyDepthCommand.shaderProgram = this._copyDepthCommand.shaderProgram.destroy();
  519. }
  520. if (defined(this._tempCopyDepthCommand)) {
  521. this._tempCopyDepthCommand.shaderProgram = this._tempCopyDepthCommand.shaderProgram.destroy();
  522. }
  523. if (defined(this._updateDepthCommand)) {
  524. this._updateDepthCommand.shaderProgram = this._updateDepthCommand.shaderProgram.destroy();
  525. }
  526. if (defined(this._mergeColorCommand)) {
  527. this._mergeColorCommand.shaderProgram = this._mergeColorCommand.shaderProgram.destroy();
  528. }
  529. if (defined(this._debugGlobeDepthViewportCommand)) {
  530. this._debugGlobeDepthViewportCommand.shaderProgram = this._debugGlobeDepthViewportCommand.shaderProgram.destroy();
  531. }
  532. return destroyObject(this);
  533. };
  534. export default GlobeDepth;