GlobeDepth.js 22 KB

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