getClippingFunction.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import Cartesian2 from '../Core/Cartesian2.js';
  2. import Check from '../Core/Check.js';
  3. import ClippingPlaneCollection from './ClippingPlaneCollection.js';
  4. var textureResolutionScratch = new Cartesian2();
  5. /**
  6. * Gets the GLSL functions needed to retrieve clipping planes from a ClippingPlaneCollection's texture.
  7. *
  8. * @param {ClippingPlaneCollection} clippingPlaneCollection ClippingPlaneCollection with a defined texture.
  9. * @param {Context} context The current rendering context.
  10. * @returns {String} A string containing GLSL functions for retrieving clipping planes.
  11. * @private
  12. */
  13. function getClippingFunction(clippingPlaneCollection, context) {
  14. //>>includeStart('debug', pragmas.debug);
  15. Check.typeOf.object('clippingPlaneCollection', clippingPlaneCollection);
  16. Check.typeOf.object('context', context);
  17. //>>includeEnd('debug');
  18. var unionClippingRegions = clippingPlaneCollection.unionClippingRegions;
  19. var clippingPlanesLength = clippingPlaneCollection.length;
  20. var usingFloatTexture = ClippingPlaneCollection.useFloatTexture(context);
  21. var textureResolution = ClippingPlaneCollection.getTextureResolution(clippingPlaneCollection, context, textureResolutionScratch);
  22. var width = textureResolution.x;
  23. var height = textureResolution.y;
  24. var functions = usingFloatTexture ? getClippingPlaneFloat(width, height) : getClippingPlaneUint8(width, height);
  25. functions += '\n';
  26. functions += unionClippingRegions ? clippingFunctionUnion(clippingPlanesLength) : clippingFunctionIntersect(clippingPlanesLength);
  27. return functions;
  28. }
  29. function clippingFunctionUnion(clippingPlanesLength) {
  30. var functionString =
  31. 'float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n' +
  32. '{\n' +
  33. ' vec4 position = czm_windowToEyeCoordinates(fragCoord);\n' +
  34. ' vec3 clipNormal = vec3(0.0);\n' +
  35. ' vec3 clipPosition = vec3(0.0);\n' +
  36. ' float clipAmount;\n' + // For union planes, we want to get the min distance. So we set the initial value to the first plane distance in the loop below.
  37. ' float pixelWidth = czm_metersPerPixel(position);\n' +
  38. ' bool breakAndDiscard = false;\n' +
  39. ' for (int i = 0; i < ' + clippingPlanesLength + '; ++i)\n' +
  40. ' {\n' +
  41. ' vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\n' +
  42. ' clipNormal = clippingPlane.xyz;\n' +
  43. ' clipPosition = -clippingPlane.w * clipNormal;\n' +
  44. ' float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\n' +
  45. ' clipAmount = czm_branchFreeTernary(i == 0, amount, min(amount, clipAmount));\n' +
  46. ' if (amount <= 0.0)\n' +
  47. ' {\n' +
  48. ' breakAndDiscard = true;\n' +
  49. ' break;\n' + // HLSL compiler bug if we discard here: https://bugs.chromium.org/p/angleproject/issues/detail?id=1945#c6
  50. ' }\n' +
  51. ' }\n' +
  52. ' if (breakAndDiscard) {\n' +
  53. ' discard;\n' +
  54. ' }\n' +
  55. ' return clipAmount;\n' +
  56. '}\n';
  57. return functionString;
  58. }
  59. function clippingFunctionIntersect(clippingPlanesLength) {
  60. var functionString =
  61. 'float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n' +
  62. '{\n' +
  63. ' bool clipped = true;\n' +
  64. ' vec4 position = czm_windowToEyeCoordinates(fragCoord);\n' +
  65. ' vec3 clipNormal = vec3(0.0);\n' +
  66. ' vec3 clipPosition = vec3(0.0);\n' +
  67. ' float clipAmount = 0.0;\n' +
  68. ' float pixelWidth = czm_metersPerPixel(position);\n' +
  69. ' for (int i = 0; i < ' + clippingPlanesLength + '; ++i)\n' +
  70. ' {\n' +
  71. ' vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\n' +
  72. ' clipNormal = clippingPlane.xyz;\n' +
  73. ' clipPosition = -clippingPlane.w * clipNormal;\n' +
  74. ' float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\n' +
  75. ' clipAmount = max(amount, clipAmount);\n' +
  76. ' clipped = clipped && (amount <= 0.0);\n' +
  77. ' }\n' +
  78. ' if (clipped)\n' +
  79. ' {\n' +
  80. ' discard;\n' +
  81. ' }\n' +
  82. ' return clipAmount;\n' +
  83. '}\n';
  84. return functionString;
  85. }
  86. function getClippingPlaneFloat(width, height) {
  87. var pixelWidth = 1.0 / width;
  88. var pixelHeight = 1.0 / height;
  89. var pixelWidthString = pixelWidth + '';
  90. if (pixelWidthString.indexOf('.') === -1) {
  91. pixelWidthString += '.0';
  92. }
  93. var pixelHeightString = pixelHeight + '';
  94. if (pixelHeightString.indexOf('.') === -1) {
  95. pixelHeightString += '.0';
  96. }
  97. var functionString =
  98. 'vec4 getClippingPlane(sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\n' +
  99. '{\n' +
  100. ' int pixY = clippingPlaneNumber / ' + width + ';\n' +
  101. ' int pixX = clippingPlaneNumber - (pixY * ' + width + ');\n' +
  102. ' float u = (float(pixX) + 0.5) * ' + pixelWidthString + ';\n' + // sample from center of pixel
  103. ' float v = (float(pixY) + 0.5) * ' + pixelHeightString + ';\n' +
  104. ' vec4 plane = texture2D(packedClippingPlanes, vec2(u, v));\n' +
  105. ' return czm_transformPlane(plane, transform);\n' +
  106. '}\n';
  107. return functionString;
  108. }
  109. function getClippingPlaneUint8(width, height) {
  110. var pixelWidth = 1.0 / width;
  111. var pixelHeight = 1.0 / height;
  112. var pixelWidthString = pixelWidth + '';
  113. if (pixelWidthString.indexOf('.') === -1) {
  114. pixelWidthString += '.0';
  115. }
  116. var pixelHeightString = pixelHeight + '';
  117. if (pixelHeightString.indexOf('.') === -1) {
  118. pixelHeightString += '.0';
  119. }
  120. var functionString =
  121. 'vec4 getClippingPlane(sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\n' +
  122. '{\n' +
  123. ' int clippingPlaneStartIndex = clippingPlaneNumber * 2;\n' + // clipping planes are two pixels each
  124. ' int pixY = clippingPlaneStartIndex / ' + width + ';\n' +
  125. ' int pixX = clippingPlaneStartIndex - (pixY * ' + width + ');\n' +
  126. ' float u = (float(pixX) + 0.5) * ' + pixelWidthString + ';\n' + // sample from center of pixel
  127. ' float v = (float(pixY) + 0.5) * ' + pixelHeightString + ';\n' +
  128. ' vec4 oct32 = texture2D(packedClippingPlanes, vec2(u, v)) * 255.0;\n' +
  129. ' vec2 oct = vec2(oct32.x * 256.0 + oct32.y, oct32.z * 256.0 + oct32.w);\n' +
  130. ' vec4 plane;\n' +
  131. ' plane.xyz = czm_octDecode(oct, 65535.0);\n' +
  132. ' plane.w = czm_unpackFloat(texture2D(packedClippingPlanes, vec2(u + ' + pixelWidthString + ', v)));\n' +
  133. ' return czm_transformPlane(plane, transform);\n' +
  134. '}\n';
  135. return functionString;
  136. }
  137. export default getClippingFunction;