getClippingFunction.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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(
  22. clippingPlaneCollection,
  23. context,
  24. textureResolutionScratch
  25. );
  26. var width = textureResolution.x;
  27. var height = textureResolution.y;
  28. var functions = usingFloatTexture
  29. ? getClippingPlaneFloat(width, height)
  30. : getClippingPlaneUint8(width, height);
  31. functions += "\n";
  32. functions += unionClippingRegions
  33. ? clippingFunctionUnion(clippingPlanesLength)
  34. : clippingFunctionIntersect(clippingPlanesLength);
  35. return functions;
  36. }
  37. function clippingFunctionUnion(clippingPlanesLength) {
  38. var functionString =
  39. "float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n" +
  40. "{\n" +
  41. " vec4 position = czm_windowToEyeCoordinates(fragCoord);\n" +
  42. " vec3 clipNormal = vec3(0.0);\n" +
  43. " vec3 clipPosition = vec3(0.0);\n" +
  44. " 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.
  45. " float pixelWidth = czm_metersPerPixel(position);\n" +
  46. " bool breakAndDiscard = false;\n" +
  47. " for (int i = 0; i < " +
  48. clippingPlanesLength +
  49. "; ++i)\n" +
  50. " {\n" +
  51. " vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\n" +
  52. " clipNormal = clippingPlane.xyz;\n" +
  53. " clipPosition = -clippingPlane.w * clipNormal;\n" +
  54. " float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\n" +
  55. " clipAmount = czm_branchFreeTernary(i == 0, amount, min(amount, clipAmount));\n" +
  56. " if (amount <= 0.0)\n" +
  57. " {\n" +
  58. " breakAndDiscard = true;\n" +
  59. " break;\n" + // HLSL compiler bug if we discard here: https://bugs.chromium.org/p/angleproject/issues/detail?id=1945#c6
  60. " }\n" +
  61. " }\n" +
  62. " if (breakAndDiscard) {\n" +
  63. " discard;\n" +
  64. " }\n" +
  65. " return clipAmount;\n" +
  66. "}\n";
  67. return functionString;
  68. }
  69. function clippingFunctionIntersect(clippingPlanesLength) {
  70. var functionString =
  71. "float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n" +
  72. "{\n" +
  73. " bool clipped = true;\n" +
  74. " vec4 position = czm_windowToEyeCoordinates(fragCoord);\n" +
  75. " vec3 clipNormal = vec3(0.0);\n" +
  76. " vec3 clipPosition = vec3(0.0);\n" +
  77. " float clipAmount = 0.0;\n" +
  78. " float pixelWidth = czm_metersPerPixel(position);\n" +
  79. " for (int i = 0; i < " +
  80. clippingPlanesLength +
  81. "; ++i)\n" +
  82. " {\n" +
  83. " vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\n" +
  84. " clipNormal = clippingPlane.xyz;\n" +
  85. " clipPosition = -clippingPlane.w * clipNormal;\n" +
  86. " float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\n" +
  87. " clipAmount = max(amount, clipAmount);\n" +
  88. " clipped = clipped && (amount <= 0.0);\n" +
  89. " }\n" +
  90. " if (clipped)\n" +
  91. " {\n" +
  92. " discard;\n" +
  93. " }\n" +
  94. " return clipAmount;\n" +
  95. "}\n";
  96. return functionString;
  97. }
  98. function getClippingPlaneFloat(width, height) {
  99. var pixelWidth = 1.0 / width;
  100. var pixelHeight = 1.0 / height;
  101. var pixelWidthString = pixelWidth + "";
  102. if (pixelWidthString.indexOf(".") === -1) {
  103. pixelWidthString += ".0";
  104. }
  105. var pixelHeightString = pixelHeight + "";
  106. if (pixelHeightString.indexOf(".") === -1) {
  107. pixelHeightString += ".0";
  108. }
  109. var functionString =
  110. "vec4 getClippingPlane(highp sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\n" +
  111. "{\n" +
  112. " int pixY = clippingPlaneNumber / " +
  113. width +
  114. ";\n" +
  115. " int pixX = clippingPlaneNumber - (pixY * " +
  116. width +
  117. ");\n" +
  118. " float u = (float(pixX) + 0.5) * " +
  119. pixelWidthString +
  120. ";\n" + // sample from center of pixel
  121. " float v = (float(pixY) + 0.5) * " +
  122. pixelHeightString +
  123. ";\n" +
  124. " vec4 plane = texture2D(packedClippingPlanes, vec2(u, v));\n" +
  125. " return czm_transformPlane(plane, transform);\n" +
  126. "}\n";
  127. return functionString;
  128. }
  129. function getClippingPlaneUint8(width, height) {
  130. var pixelWidth = 1.0 / width;
  131. var pixelHeight = 1.0 / height;
  132. var pixelWidthString = pixelWidth + "";
  133. if (pixelWidthString.indexOf(".") === -1) {
  134. pixelWidthString += ".0";
  135. }
  136. var pixelHeightString = pixelHeight + "";
  137. if (pixelHeightString.indexOf(".") === -1) {
  138. pixelHeightString += ".0";
  139. }
  140. var functionString =
  141. "vec4 getClippingPlane(highp sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\n" +
  142. "{\n" +
  143. " int clippingPlaneStartIndex = clippingPlaneNumber * 2;\n" + // clipping planes are two pixels each
  144. " int pixY = clippingPlaneStartIndex / " +
  145. width +
  146. ";\n" +
  147. " int pixX = clippingPlaneStartIndex - (pixY * " +
  148. width +
  149. ");\n" +
  150. " float u = (float(pixX) + 0.5) * " +
  151. pixelWidthString +
  152. ";\n" + // sample from center of pixel
  153. " float v = (float(pixY) + 0.5) * " +
  154. pixelHeightString +
  155. ";\n" +
  156. " vec4 oct32 = texture2D(packedClippingPlanes, vec2(u, v)) * 255.0;\n" +
  157. " vec2 oct = vec2(oct32.x * 256.0 + oct32.y, oct32.z * 256.0 + oct32.w);\n" +
  158. " vec4 plane;\n" +
  159. " plane.xyz = czm_octDecode(oct, 65535.0);\n" +
  160. " plane.w = czm_unpackFloat(texture2D(packedClippingPlanes, vec2(u + " +
  161. pixelWidthString +
  162. ", v)));\n" +
  163. " return czm_transformPlane(plane, transform);\n" +
  164. "}\n";
  165. return functionString;
  166. }
  167. export default getClippingFunction;