智慧水务管理系统 - 精河县供水工程综合管理平台

PolygonSignedDistanceFS.glsl 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. in vec2 v_textureCoordinates;
  2. uniform int u_polygonsLength;
  3. uniform int u_extentsLength;
  4. uniform highp sampler2D u_polygonTexture;
  5. uniform highp sampler2D u_extentsTexture;
  6. int getPolygonIndex(float dimension, vec2 coord) {
  7. vec2 uv = coord.xy * dimension;
  8. return int(floor(uv.y) * dimension + floor(uv.x));
  9. }
  10. vec2 getLookupUv(ivec2 dimensions, int i) {
  11. int pixY = i / dimensions.x;
  12. int pixX = i - (pixY * dimensions.x);
  13. float pixelWidth = 1.0 / float(dimensions.x);
  14. float pixelHeight = 1.0 / float(dimensions.y);
  15. float u = (float(pixX) + 0.5) * pixelWidth; // sample from center of pixel
  16. float v = (float(pixY) + 0.5) * pixelHeight;
  17. return vec2(u, v);
  18. }
  19. vec4 getExtents(int i) {
  20. return texture(u_extentsTexture, getLookupUv(textureSize(u_extentsTexture, 0), i));
  21. }
  22. ivec2 getPositionsLengthAndExtentsIndex(int i) {
  23. vec2 uv = getLookupUv(textureSize(u_polygonTexture, 0), i);
  24. vec4 value = texture(u_polygonTexture, uv);
  25. return ivec2(int(value.x), int(value.y));
  26. }
  27. vec2 getPolygonPosition(int i) {
  28. vec2 uv = getLookupUv(textureSize(u_polygonTexture, 0), i);
  29. return texture(u_polygonTexture, uv).xy;
  30. }
  31. vec2 getCoordinates(vec2 textureCoordinates, vec4 extents) {
  32. float latitude = mix(extents.x, extents.x + 1.0 / extents.z, textureCoordinates.y);
  33. float longitude = mix(extents.y, extents.y + 1.0 / extents.w, textureCoordinates.x);
  34. return vec2(latitude, longitude);
  35. }
  36. void main() {
  37. int lastPolygonIndex = 0;
  38. out_FragColor = vec4(1.0);
  39. // Get the relevant region of the texture
  40. float dimension = float(u_extentsLength);
  41. if (u_extentsLength > 2) {
  42. dimension = ceil(log2(float(u_extentsLength)));
  43. }
  44. int regionIndex = getPolygonIndex(dimension, v_textureCoordinates);
  45. if (regionIndex >= u_extentsLength) {
  46. return; // done (no polygons in this region)
  47. }
  48. for (int polygonIndex = 0; polygonIndex < u_polygonsLength; polygonIndex++) {
  49. ivec2 positionsLengthAndExtents = getPositionsLengthAndExtentsIndex(lastPolygonIndex);
  50. int positionsLength = positionsLengthAndExtents.x;
  51. int polygonExtentsIndex = positionsLengthAndExtents.y;
  52. lastPolygonIndex += 1;
  53. // Read the individual polygon extent (2 pixels: south/west, latRange/lonRange)
  54. vec2 extentsSouthWest = getPolygonPosition(lastPolygonIndex);
  55. vec2 extentsRange = getPolygonPosition(lastPolygonIndex + 1);
  56. vec4 polygonExtent = vec4(extentsSouthWest, extentsRange);
  57. lastPolygonIndex += 2;
  58. if (polygonExtentsIndex < regionIndex) {
  59. lastPolygonIndex += positionsLength;
  60. continue; // skip to next (TODO: could optimize further if we knew how many polygons to skip)
  61. } else if (polygonExtentsIndex > regionIndex) {
  62. break; // done (we know polygons are sorted by regionIndex)
  63. }
  64. // Only compute signed distance for the relevant part of the atlas
  65. float clipAmount = czm_infinity;
  66. vec4 extents = getExtents(polygonExtentsIndex);
  67. vec2 textureOffset = vec2(mod(float(polygonExtentsIndex), dimension), floor(float(polygonExtentsIndex) / dimension)) / dimension;
  68. vec2 p = getCoordinates((v_textureCoordinates - textureOffset) * dimension, extents); // current pixel position
  69. // Only consider polygons whos boundingbox includes current pixel (with a slight padding)
  70. float padding = 0.05; // 5% of polygon extents
  71. float polygonNorth = polygonExtent.x + polygonExtent.z;
  72. float polygonEast = polygonExtent.y + polygonExtent.w;
  73. float latPadding = padding * polygonExtent.z; // padding as fraction of latitude range
  74. float lonPadding = padding * polygonExtent.w; // padding as fraction of longitude range
  75. if (p.x < polygonExtent.x - latPadding || p.x > polygonNorth + latPadding ||
  76. p.y < polygonExtent.y - lonPadding || p.y > polygonEast + lonPadding) {
  77. lastPolygonIndex += positionsLength;
  78. continue; // skip to next
  79. }
  80. float s = 1.0;
  81. // Check each edge for absolute distance.
  82. // Cache the previous vertex to halve the texture reads per iteration.
  83. vec2 prev = getPolygonPosition(lastPolygonIndex + positionsLength - 1);
  84. for (int i = 0; i < positionsLength; i++) {
  85. vec2 a = getPolygonPosition(lastPolygonIndex + i);
  86. vec2 b = prev;
  87. prev = a;
  88. vec2 ab = b - a;
  89. vec2 pa = p - a;
  90. float t = dot(pa, ab) / dot(ab, ab);
  91. t = clamp(t, 0.0, 1.0);
  92. vec2 pq = pa - t * ab;
  93. float d = length(pq);
  94. // Inside / outside computation to determine sign
  95. bvec3 cond = bvec3(p.y >= a.y,
  96. p.y < b.y,
  97. ab.x * pa.y > ab.y * pa.x);
  98. if (all(cond) || all(not(cond))) s = -s;
  99. if (abs(d) < abs(clipAmount)) {
  100. clipAmount = d;
  101. }
  102. }
  103. // Normalize the range to [0,1]
  104. vec4 result = (s * vec4(clipAmount * length(extents.zw))) / 2.0 + 0.5;
  105. // In the case where we've iterated through multiple polygons, take the minimum
  106. out_FragColor = min(out_FragColor, result);
  107. lastPolygonIndex += positionsLength;
  108. }
  109. }