PickDepth.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import Cartesian4 from '../Core/Cartesian4.js';
  2. import defined from '../Core/defined.js';
  3. import destroyObject from '../Core/destroyObject.js';
  4. import PixelFormat from '../Core/PixelFormat.js';
  5. import Framebuffer from '../Renderer/Framebuffer.js';
  6. import PixelDatatype from '../Renderer/PixelDatatype.js';
  7. import RenderState from '../Renderer/RenderState.js';
  8. import ShaderSource from '../Renderer/ShaderSource.js';
  9. import Texture from '../Renderer/Texture.js';
  10. /**
  11. * @private
  12. */
  13. function PickDepth() {
  14. this._framebuffer = undefined;
  15. this._depthTexture = undefined;
  16. this._textureToCopy = undefined;
  17. this._copyDepthCommand = undefined;
  18. this._useLogDepth = undefined;
  19. this._debugPickDepthViewportCommand = undefined;
  20. }
  21. function executeDebugPickDepth(pickDepth, context, passState, useLogDepth) {
  22. if (!defined(pickDepth._debugPickDepthViewportCommand) || useLogDepth !== pickDepth._useLogDepth) {
  23. var fsSource =
  24. 'uniform sampler2D u_texture;\n' +
  25. 'varying vec2 v_textureCoordinates;\n' +
  26. 'void main()\n' +
  27. '{\n' +
  28. ' float z_window = czm_unpackDepth(texture2D(u_texture, v_textureCoordinates));\n' +
  29. ' z_window = czm_reverseLogDepth(z_window); \n' +
  30. ' float n_range = czm_depthRange.near;\n' +
  31. ' float f_range = czm_depthRange.far;\n' +
  32. ' float z_ndc = (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n' +
  33. ' float scale = pow(z_ndc * 0.5 + 0.5, 8.0);\n' +
  34. ' gl_FragColor = vec4(mix(vec3(0.0), vec3(1.0), scale), 1.0);\n' +
  35. '}\n';
  36. var fs = new ShaderSource({
  37. defines : [useLogDepth ? 'LOG_DEPTH' : ''],
  38. sources : [fsSource]
  39. });
  40. pickDepth._debugPickDepthViewportCommand = context.createViewportQuadCommand(fs, {
  41. uniformMap : {
  42. u_texture : function() {
  43. return pickDepth._depthTexture;
  44. }
  45. },
  46. owner : pickDepth
  47. });
  48. pickDepth._useLogDepth = useLogDepth;
  49. }
  50. pickDepth._debugPickDepthViewportCommand.execute(context, passState);
  51. }
  52. function destroyTextures(pickDepth) {
  53. pickDepth._depthTexture = pickDepth._depthTexture && !pickDepth._depthTexture.isDestroyed() && pickDepth._depthTexture.destroy();
  54. }
  55. function destroyFramebuffers(pickDepth) {
  56. pickDepth._framebuffer = pickDepth._framebuffer && !pickDepth._framebuffer.isDestroyed() && pickDepth._framebuffer.destroy();
  57. }
  58. function createTextures(pickDepth, context, width, height) {
  59. pickDepth._depthTexture = new Texture({
  60. context : context,
  61. width : width,
  62. height : height,
  63. pixelFormat : PixelFormat.RGBA,
  64. pixelDatatype : PixelDatatype.UNSIGNED_BYTE
  65. });
  66. }
  67. function createFramebuffers(pickDepth, context, width, height) {
  68. destroyTextures(pickDepth);
  69. destroyFramebuffers(pickDepth);
  70. createTextures(pickDepth, context, width, height);
  71. pickDepth._framebuffer = new Framebuffer({
  72. context : context,
  73. colorTextures : [pickDepth._depthTexture],
  74. destroyAttachments : false
  75. });
  76. }
  77. function updateFramebuffers(pickDepth, context, depthTexture) {
  78. var width = depthTexture.width;
  79. var height = depthTexture.height;
  80. var texture = pickDepth._depthTexture;
  81. var textureChanged = !defined(texture) || texture.width !== width || texture.height !== height;
  82. if (!defined(pickDepth._framebuffer) || textureChanged) {
  83. createFramebuffers(pickDepth, context, width, height);
  84. }
  85. }
  86. function updateCopyCommands(pickDepth, context, depthTexture) {
  87. if (!defined(pickDepth._copyDepthCommand)) {
  88. var fs =
  89. 'uniform sampler2D u_texture;\n' +
  90. 'varying vec2 v_textureCoordinates;\n' +
  91. 'void main()\n' +
  92. '{\n' +
  93. ' gl_FragColor = czm_packDepth(texture2D(u_texture, v_textureCoordinates).r);\n' +
  94. '}\n';
  95. pickDepth._copyDepthCommand = context.createViewportQuadCommand(fs, {
  96. renderState : RenderState.fromCache(),
  97. uniformMap : {
  98. u_texture : function() {
  99. return pickDepth._textureToCopy;
  100. }
  101. },
  102. owner : pickDepth
  103. });
  104. }
  105. pickDepth._textureToCopy = depthTexture;
  106. pickDepth._copyDepthCommand.framebuffer = pickDepth._framebuffer;
  107. }
  108. PickDepth.prototype.executeDebugPickDepth = function(context, passState, useLogDepth) {
  109. executeDebugPickDepth(this, context, passState, useLogDepth);
  110. };
  111. PickDepth.prototype.update = function(context, depthTexture) {
  112. updateFramebuffers(this, context, depthTexture);
  113. updateCopyCommands(this, context, depthTexture);
  114. };
  115. var scratchPackedDepth = new Cartesian4();
  116. var packedDepthScale = new Cartesian4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 16581375.0);
  117. PickDepth.prototype.getDepth = function(context, x, y) {
  118. var pixels = context.readPixels({
  119. x : x,
  120. y : y,
  121. width : 1,
  122. height : 1,
  123. framebuffer : this._framebuffer
  124. });
  125. var packedDepth = Cartesian4.unpack(pixels, 0, scratchPackedDepth);
  126. Cartesian4.divideByScalar(packedDepth, 255.0, packedDepth);
  127. return Cartesian4.dot(packedDepth, packedDepthScale);
  128. };
  129. PickDepth.prototype.executeCopyDepth = function(context, passState) {
  130. this._copyDepthCommand.execute(context, passState);
  131. };
  132. PickDepth.prototype.isDestroyed = function() {
  133. return false;
  134. };
  135. PickDepth.prototype.destroy = function() {
  136. destroyTextures(this);
  137. destroyFramebuffers(this);
  138. this._copyDepthCommand.shaderProgram = defined(this._copyDepthCommand.shaderProgram) && this._copyDepthCommand.shaderProgram.destroy();
  139. return destroyObject(this);
  140. };
  141. export default PickDepth;