GlobeDepth.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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 ClearCommand from "../Renderer/ClearCommand.js";
  6. import FramebufferManager from "../Renderer/FramebufferManager.js";
  7. import PixelDatatype from "../Renderer/PixelDatatype.js";
  8. import RenderState from "../Renderer/RenderState.js";
  9. import PassThrough from "../Shaders/PostProcessStages/PassThrough.js";
  10. import PassThroughDepth from "../Shaders/PostProcessStages/PassThroughDepth.js";
  11. import BlendingState from "./BlendingState.js";
  12. import StencilConstants from "./StencilConstants.js";
  13. import StencilFunction from "./StencilFunction.js";
  14. import StencilOperation from "./StencilOperation.js";
  15. /**
  16. * @private
  17. */
  18. function GlobeDepth() {
  19. this._picking = false;
  20. this._numSamples = 1;
  21. this._tempCopyDepthTexture = undefined;
  22. this._pickColorFramebuffer = new FramebufferManager({
  23. depthStencil: true,
  24. supportsDepthTexture: true,
  25. });
  26. this._outputFramebuffer = new FramebufferManager({
  27. depthStencil: true,
  28. supportsDepthTexture: true,
  29. });
  30. this._copyDepthFramebuffer = new FramebufferManager();
  31. this._tempCopyDepthFramebuffer = new FramebufferManager();
  32. this._updateDepthFramebuffer = new FramebufferManager({
  33. createColorAttachments: false,
  34. createDepthAttachments: false,
  35. depthStencil: true,
  36. });
  37. this._clearGlobeColorCommand = undefined;
  38. this._copyColorCommand = undefined;
  39. this._copyDepthCommand = undefined;
  40. this._tempCopyDepthCommand = undefined;
  41. this._updateDepthCommand = undefined;
  42. this._viewport = new BoundingRectangle();
  43. this._rs = undefined;
  44. this._rsBlend = undefined;
  45. this._rsUpdate = undefined;
  46. this._useScissorTest = false;
  47. this._scissorRectangle = undefined;
  48. this._useHdr = undefined;
  49. this._clearGlobeDepth = undefined;
  50. }
  51. Object.defineProperties(GlobeDepth.prototype, {
  52. colorFramebufferManager: {
  53. get: function () {
  54. return this._picking
  55. ? this._pickColorFramebuffer
  56. : this._outputFramebuffer;
  57. },
  58. },
  59. framebuffer: {
  60. get: function () {
  61. return this.colorFramebufferManager.framebuffer;
  62. },
  63. },
  64. depthStencilTexture: {
  65. get: function () {
  66. return this.colorFramebufferManager.getDepthStencilTexture();
  67. },
  68. },
  69. picking: {
  70. get: function () {
  71. return this._picking;
  72. },
  73. set: function (value) {
  74. this._picking = value;
  75. },
  76. },
  77. });
  78. function destroyFramebuffers(globeDepth) {
  79. globeDepth._pickColorFramebuffer.destroy();
  80. globeDepth._outputFramebuffer.destroy();
  81. globeDepth._copyDepthFramebuffer.destroy();
  82. globeDepth._tempCopyDepthFramebuffer.destroy();
  83. globeDepth._updateDepthFramebuffer.destroy();
  84. }
  85. function updateCopyCommands(globeDepth, context, width, height, passState) {
  86. globeDepth._viewport.width = width;
  87. globeDepth._viewport.height = height;
  88. const useScissorTest = !BoundingRectangle.equals(
  89. globeDepth._viewport,
  90. passState.viewport
  91. );
  92. let updateScissor = useScissorTest !== globeDepth._useScissorTest;
  93. globeDepth._useScissorTest = useScissorTest;
  94. if (
  95. !BoundingRectangle.equals(globeDepth._scissorRectangle, passState.viewport)
  96. ) {
  97. globeDepth._scissorRectangle = BoundingRectangle.clone(
  98. passState.viewport,
  99. globeDepth._scissorRectangle
  100. );
  101. updateScissor = true;
  102. }
  103. if (
  104. !defined(globeDepth._rs) ||
  105. !BoundingRectangle.equals(globeDepth._viewport, globeDepth._rs.viewport) ||
  106. updateScissor
  107. ) {
  108. globeDepth._rs = RenderState.fromCache({
  109. viewport: globeDepth._viewport,
  110. scissorTest: {
  111. enabled: globeDepth._useScissorTest,
  112. rectangle: globeDepth._scissorRectangle,
  113. },
  114. });
  115. globeDepth._rsBlend = RenderState.fromCache({
  116. viewport: globeDepth._viewport,
  117. scissorTest: {
  118. enabled: globeDepth._useScissorTest,
  119. rectangle: globeDepth._scissorRectangle,
  120. },
  121. blending: BlendingState.ALPHA_BLEND,
  122. });
  123. // Copy packed depth only if the 3D Tiles bit is set
  124. globeDepth._rsUpdate = RenderState.fromCache({
  125. viewport: globeDepth._viewport,
  126. scissorTest: {
  127. enabled: globeDepth._useScissorTest,
  128. rectangle: globeDepth._scissorRectangle,
  129. },
  130. stencilTest: {
  131. enabled: true,
  132. frontFunction: StencilFunction.EQUAL,
  133. frontOperation: {
  134. fail: StencilOperation.KEEP,
  135. zFail: StencilOperation.KEEP,
  136. zPass: StencilOperation.KEEP,
  137. },
  138. backFunction: StencilFunction.NEVER,
  139. reference: StencilConstants.CESIUM_3D_TILE_MASK,
  140. mask: StencilConstants.CESIUM_3D_TILE_MASK,
  141. },
  142. });
  143. }
  144. if (!defined(globeDepth._copyDepthCommand)) {
  145. globeDepth._copyDepthCommand = context.createViewportQuadCommand(
  146. PassThroughDepth,
  147. {
  148. uniformMap: {
  149. u_depthTexture: function () {
  150. return globeDepth.colorFramebufferManager.getDepthStencilTexture();
  151. },
  152. },
  153. owner: globeDepth,
  154. }
  155. );
  156. }
  157. globeDepth._copyDepthCommand.framebuffer =
  158. globeDepth._copyDepthFramebuffer.framebuffer;
  159. globeDepth._copyDepthCommand.renderState = globeDepth._rs;
  160. if (!defined(globeDepth._copyColorCommand)) {
  161. globeDepth._copyColorCommand = context.createViewportQuadCommand(
  162. PassThrough,
  163. {
  164. uniformMap: {
  165. colorTexture: function () {
  166. return globeDepth.colorFramebufferManager.getColorTexture();
  167. },
  168. },
  169. owner: globeDepth,
  170. }
  171. );
  172. }
  173. globeDepth._copyColorCommand.renderState = globeDepth._rs;
  174. if (!defined(globeDepth._tempCopyDepthCommand)) {
  175. globeDepth._tempCopyDepthCommand = context.createViewportQuadCommand(
  176. PassThroughDepth,
  177. {
  178. uniformMap: {
  179. u_depthTexture: function () {
  180. return globeDepth._tempCopyDepthTexture;
  181. },
  182. },
  183. owner: globeDepth,
  184. }
  185. );
  186. }
  187. globeDepth._tempCopyDepthCommand.framebuffer =
  188. globeDepth._tempCopyDepthFramebuffer.framebuffer;
  189. globeDepth._tempCopyDepthCommand.renderState = globeDepth._rs;
  190. if (!defined(globeDepth._updateDepthCommand)) {
  191. globeDepth._updateDepthCommand = context.createViewportQuadCommand(
  192. PassThrough,
  193. {
  194. uniformMap: {
  195. colorTexture: function () {
  196. return globeDepth._tempCopyDepthFramebuffer.getColorTexture();
  197. },
  198. },
  199. owner: globeDepth,
  200. }
  201. );
  202. }
  203. globeDepth._updateDepthCommand.framebuffer =
  204. globeDepth._updateDepthFramebuffer.framebuffer;
  205. globeDepth._updateDepthCommand.renderState = globeDepth._rsUpdate;
  206. if (!defined(globeDepth._clearGlobeColorCommand)) {
  207. globeDepth._clearGlobeColorCommand = new ClearCommand({
  208. color: new Color(0.0, 0.0, 0.0, 0.0),
  209. stencil: 0.0,
  210. owner: globeDepth,
  211. });
  212. }
  213. globeDepth._clearGlobeColorCommand.framebuffer = globeDepth.framebuffer;
  214. }
  215. GlobeDepth.prototype.update = function (
  216. context,
  217. passState,
  218. viewport,
  219. numSamples,
  220. hdr,
  221. clearGlobeDepth
  222. ) {
  223. const width = viewport.width;
  224. const height = viewport.height;
  225. const pixelDatatype = hdr
  226. ? context.halfFloatingPointTexture
  227. ? PixelDatatype.HALF_FLOAT
  228. : PixelDatatype.FLOAT
  229. : PixelDatatype.UNSIGNED_BYTE;
  230. this._numSamples = numSamples;
  231. if (this.picking) {
  232. this._pickColorFramebuffer.update(context, width, height);
  233. } else {
  234. this._outputFramebuffer.update(
  235. context,
  236. width,
  237. height,
  238. numSamples,
  239. pixelDatatype
  240. );
  241. }
  242. this._copyDepthFramebuffer.update(context, width, height);
  243. updateCopyCommands(this, context, width, height, passState);
  244. context.uniformState.globeDepthTexture = undefined;
  245. this._useHdr = hdr;
  246. this._clearGlobeDepth = clearGlobeDepth;
  247. };
  248. GlobeDepth.prototype.prepareColorTextures = function (context, blitStencil) {
  249. if (!this.picking && this._numSamples > 1) {
  250. this._outputFramebuffer.prepareTextures(context, blitStencil);
  251. }
  252. };
  253. GlobeDepth.prototype.executeCopyDepth = function (context, passState) {
  254. if (defined(this._copyDepthCommand)) {
  255. this.prepareColorTextures(context);
  256. this._copyDepthCommand.execute(context, passState);
  257. context.uniformState.globeDepthTexture = this._copyDepthFramebuffer.getColorTexture();
  258. }
  259. };
  260. GlobeDepth.prototype.executeUpdateDepth = function (
  261. context,
  262. passState,
  263. clearGlobeDepth,
  264. depthTexture
  265. ) {
  266. const depthTextureToCopy = defined(depthTexture)
  267. ? depthTexture
  268. : passState.framebuffer.depthStencilTexture;
  269. if (
  270. clearGlobeDepth ||
  271. depthTextureToCopy !== this.colorFramebufferManager.getDepthStencilTexture()
  272. ) {
  273. // First copy the depth to a temporary globe depth texture, then update the
  274. // main globe depth texture where the stencil bit for 3D Tiles is set.
  275. // This preserves the original globe depth except where 3D Tiles is rendered.
  276. // The additional texture and framebuffer resources are created on demand.
  277. if (defined(this._updateDepthCommand)) {
  278. if (
  279. !defined(this._updateDepthFramebuffer.framebuffer) ||
  280. this._updateDepthFramebuffer.getDepthStencilTexture() !==
  281. depthTextureToCopy ||
  282. this._updateDepthFramebuffer.getColorTexture() !==
  283. this._copyDepthFramebuffer.getColorTexture()
  284. ) {
  285. const width = this._copyDepthFramebuffer.getColorTexture().width;
  286. const height = this._copyDepthFramebuffer.getColorTexture().height;
  287. this._tempCopyDepthFramebuffer.destroy();
  288. this._tempCopyDepthFramebuffer.update(context, width, height);
  289. const colorTexture = this._copyDepthFramebuffer.getColorTexture();
  290. this._updateDepthFramebuffer.setColorTexture(colorTexture, 0);
  291. this._updateDepthFramebuffer.setDepthStencilTexture(depthTextureToCopy);
  292. this._updateDepthFramebuffer.update(context, width, height);
  293. updateCopyCommands(this, context, width, height, passState);
  294. }
  295. this._tempCopyDepthTexture = depthTextureToCopy;
  296. this._tempCopyDepthCommand.execute(context, passState);
  297. this._updateDepthCommand.execute(context, passState);
  298. }
  299. return;
  300. }
  301. // Fast path - the depth texture can be copied normally.
  302. if (defined(this._copyDepthCommand)) {
  303. this._copyDepthCommand.execute(context, passState);
  304. }
  305. };
  306. GlobeDepth.prototype.executeCopyColor = function (context, passState) {
  307. if (defined(this._copyColorCommand)) {
  308. this._copyColorCommand.execute(context, passState);
  309. }
  310. };
  311. GlobeDepth.prototype.clear = function (context, passState, clearColor) {
  312. const clear = this._clearGlobeColorCommand;
  313. if (defined(clear)) {
  314. Color.clone(clearColor, clear.color);
  315. this.colorFramebufferManager.clear(context, clear, passState);
  316. }
  317. };
  318. GlobeDepth.prototype.isDestroyed = function () {
  319. return false;
  320. };
  321. GlobeDepth.prototype.destroy = function () {
  322. destroyFramebuffers(this);
  323. if (defined(this._copyColorCommand)) {
  324. this._copyColorCommand.shaderProgram = this._copyColorCommand.shaderProgram.destroy();
  325. }
  326. if (defined(this._copyDepthCommand)) {
  327. this._copyDepthCommand.shaderProgram = this._copyDepthCommand.shaderProgram.destroy();
  328. }
  329. if (defined(this._tempCopyDepthCommand)) {
  330. this._tempCopyDepthCommand.shaderProgram = this._tempCopyDepthCommand.shaderProgram.destroy();
  331. }
  332. if (defined(this._updateDepthCommand)) {
  333. this._updateDepthCommand.shaderProgram = this._updateDepthCommand.shaderProgram.destroy();
  334. }
  335. return destroyObject(this);
  336. };
  337. export default GlobeDepth;