PolylineShadowVolumeMorphVS.glsl 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. in vec3 position3DHigh;
  2. in vec3 position3DLow;
  3. in vec4 startHiAndForwardOffsetX;
  4. in vec4 startLoAndForwardOffsetY;
  5. in vec4 startNormalAndForwardOffsetZ;
  6. in vec4 endNormalAndTextureCoordinateNormalizationX;
  7. in vec4 rightNormalAndTextureCoordinateNormalizationY;
  8. in vec4 startHiLo2D;
  9. in vec4 offsetAndRight2D;
  10. in vec4 startEndNormals2D;
  11. in vec2 texcoordNormalization2D;
  12. in float batchId;
  13. out vec3 v_forwardDirectionEC;
  14. out vec3 v_texcoordNormalizationAndHalfWidth;
  15. out float v_batchId;
  16. // For materials
  17. #ifdef WIDTH_VARYING
  18. out float v_width;
  19. #endif
  20. #ifdef ANGLE_VARYING
  21. out float v_polylineAngle;
  22. #endif
  23. #ifdef PER_INSTANCE_COLOR
  24. out vec4 v_color;
  25. #else
  26. out vec2 v_alignedPlaneDistances;
  27. out float v_texcoordT;
  28. #endif
  29. // Morphing planes using SLERP or NLERP doesn't seem to work, so instead draw the material directly on the shadow volume.
  30. // Morph views are from very far away and aren't meant to be used precisely, so this should be sufficient.
  31. void main()
  32. {
  33. v_batchId = batchId;
  34. // Start position
  35. vec4 posRelativeToEye2D = czm_translateRelativeToEye(vec3(0.0, startHiLo2D.xy), vec3(0.0, startHiLo2D.zw));
  36. vec4 posRelativeToEye3D = czm_translateRelativeToEye(startHiAndForwardOffsetX.xyz, startLoAndForwardOffsetY.xyz);
  37. vec4 posRelativeToEye = czm_columbusViewMorph(posRelativeToEye2D, posRelativeToEye3D, czm_morphTime);
  38. vec3 posEc2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz;
  39. vec3 posEc3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz;
  40. vec3 startEC = (czm_modelViewRelativeToEye * posRelativeToEye).xyz;
  41. // Start plane
  42. vec4 startPlane2D;
  43. vec4 startPlane3D;
  44. startPlane2D.xyz = czm_normal * vec3(0.0, startEndNormals2D.xy);
  45. startPlane3D.xyz = czm_normal * startNormalAndForwardOffsetZ.xyz;
  46. startPlane2D.w = -dot(startPlane2D.xyz, posEc2D);
  47. startPlane3D.w = -dot(startPlane3D.xyz, posEc3D);
  48. // Right plane
  49. vec4 rightPlane2D;
  50. vec4 rightPlane3D;
  51. rightPlane2D.xyz = czm_normal * vec3(0.0, offsetAndRight2D.zw);
  52. rightPlane3D.xyz = czm_normal * rightNormalAndTextureCoordinateNormalizationY.xyz;
  53. rightPlane2D.w = -dot(rightPlane2D.xyz, posEc2D);
  54. rightPlane3D.w = -dot(rightPlane3D.xyz, posEc3D);
  55. // End position
  56. posRelativeToEye2D = posRelativeToEye2D + vec4(0.0, offsetAndRight2D.xy, 0.0);
  57. posRelativeToEye3D = posRelativeToEye3D + vec4(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w, 0.0);
  58. posRelativeToEye = czm_columbusViewMorph(posRelativeToEye2D, posRelativeToEye3D, czm_morphTime);
  59. posEc2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz;
  60. posEc3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz;
  61. vec3 endEC = (czm_modelViewRelativeToEye * posRelativeToEye).xyz;
  62. vec3 forwardEc3D = czm_normal * normalize(vec3(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w));
  63. vec3 forwardEc2D = czm_normal * normalize(vec3(0.0, offsetAndRight2D.xy));
  64. // End plane
  65. vec4 endPlane2D;
  66. vec4 endPlane3D;
  67. endPlane2D.xyz = czm_normal * vec3(0.0, startEndNormals2D.zw);
  68. endPlane3D.xyz = czm_normal * endNormalAndTextureCoordinateNormalizationX.xyz;
  69. endPlane2D.w = -dot(endPlane2D.xyz, posEc2D);
  70. endPlane3D.w = -dot(endPlane3D.xyz, posEc3D);
  71. // Forward direction
  72. v_forwardDirectionEC = normalize(endEC - startEC);
  73. vec2 cleanTexcoordNormalization2D;
  74. cleanTexcoordNormalization2D.x = abs(texcoordNormalization2D.x);
  75. cleanTexcoordNormalization2D.y = czm_branchFreeTernary(texcoordNormalization2D.y > 1.0, 0.0, abs(texcoordNormalization2D.y));
  76. vec2 cleanTexcoordNormalization3D;
  77. cleanTexcoordNormalization3D.x = abs(endNormalAndTextureCoordinateNormalizationX.w);
  78. cleanTexcoordNormalization3D.y = rightNormalAndTextureCoordinateNormalizationY.w;
  79. cleanTexcoordNormalization3D.y = czm_branchFreeTernary(cleanTexcoordNormalization3D.y > 1.0, 0.0, abs(cleanTexcoordNormalization3D.y));
  80. v_texcoordNormalizationAndHalfWidth.xy = mix(cleanTexcoordNormalization2D, cleanTexcoordNormalization3D, czm_morphTime);
  81. #ifdef PER_INSTANCE_COLOR
  82. v_color = czm_batchTable_color(batchId);
  83. #else // PER_INSTANCE_COLOR
  84. // For computing texture coordinates
  85. v_alignedPlaneDistances.x = -dot(v_forwardDirectionEC, startEC);
  86. v_alignedPlaneDistances.y = -dot(-v_forwardDirectionEC, endEC);
  87. #endif // PER_INSTANCE_COLOR
  88. #ifdef WIDTH_VARYING
  89. float width = czm_batchTable_width(batchId);
  90. float halfWidth = width * 0.5;
  91. v_width = width;
  92. v_texcoordNormalizationAndHalfWidth.z = halfWidth;
  93. #else
  94. float halfWidth = 0.5 * czm_batchTable_width(batchId);
  95. v_texcoordNormalizationAndHalfWidth.z = halfWidth;
  96. #endif
  97. // Compute a normal along which to "push" the position out, extending the miter depending on view distance.
  98. // Position has already been "pushed" by unit length along miter normal, and miter normals are encoded in the planes.
  99. // Decode the normal to use at this specific vertex, push the position back, and then push to where it needs to be.
  100. // Since this is morphing, compute both 3D and 2D positions and then blend.
  101. // ****** 3D ******
  102. // Check distance to the end plane and start plane, pick the plane that is closer
  103. vec4 positionEc3D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position3DHigh, position3DLow); // w = 1.0, see czm_computePosition
  104. float absStartPlaneDistance = abs(czm_planeDistance(startPlane3D, positionEc3D.xyz));
  105. float absEndPlaneDistance = abs(czm_planeDistance(endPlane3D, positionEc3D.xyz));
  106. vec3 planeDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlane3D.xyz, endPlane3D.xyz);
  107. vec3 upOrDown = normalize(cross(rightPlane3D.xyz, planeDirection)); // Points "up" for start plane, "down" at end plane.
  108. vec3 normalEC = normalize(cross(planeDirection, upOrDown)); // In practice, the opposite seems to work too.
  109. // Nudge the top vertex upwards to prevent flickering
  110. vec3 geodeticSurfaceNormal = normalize(cross(normalEC, forwardEc3D));
  111. geodeticSurfaceNormal *= float(0.0 <= rightNormalAndTextureCoordinateNormalizationY.w && rightNormalAndTextureCoordinateNormalizationY.w <= 1.0);
  112. geodeticSurfaceNormal *= MAX_TERRAIN_HEIGHT;
  113. positionEc3D.xyz += geodeticSurfaceNormal;
  114. // Determine if this vertex is on the "left" or "right"
  115. normalEC *= sign(endNormalAndTextureCoordinateNormalizationX.w);
  116. // A "perfect" implementation would push along normals according to the angle against forward.
  117. // In practice, just pushing the normal out by halfWidth is sufficient for morph views.
  118. positionEc3D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEc3D)) * normalEC; // prevent artifacts when czm_metersPerPixel is negative (behind camera)
  119. // ****** 2D ******
  120. // Check distance to the end plane and start plane, pick the plane that is closer
  121. vec4 positionEc2D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy); // w = 1.0, see czm_computePosition
  122. absStartPlaneDistance = abs(czm_planeDistance(startPlane2D, positionEc2D.xyz));
  123. absEndPlaneDistance = abs(czm_planeDistance(endPlane2D, positionEc2D.xyz));
  124. planeDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlane2D.xyz, endPlane2D.xyz);
  125. upOrDown = normalize(cross(rightPlane2D.xyz, planeDirection)); // Points "up" for start plane, "down" at end plane.
  126. normalEC = normalize(cross(planeDirection, upOrDown)); // In practice, the opposite seems to work too.
  127. // Nudge the top vertex upwards to prevent flickering
  128. geodeticSurfaceNormal = normalize(cross(normalEC, forwardEc2D));
  129. geodeticSurfaceNormal *= float(0.0 <= texcoordNormalization2D.y && texcoordNormalization2D.y <= 1.0);
  130. geodeticSurfaceNormal *= MAX_TERRAIN_HEIGHT;
  131. positionEc2D.xyz += geodeticSurfaceNormal;
  132. // Determine if this vertex is on the "left" or "right"
  133. normalEC *= sign(texcoordNormalization2D.x);
  134. #ifndef PER_INSTANCE_COLOR
  135. // Use vertex's sidedness to compute its texture coordinate.
  136. v_texcoordT = clamp(sign(texcoordNormalization2D.x), 0.0, 1.0);
  137. #endif
  138. // A "perfect" implementation would push along normals according to the angle against forward.
  139. // In practice, just pushing the normal out by halfWidth is sufficient for morph views.
  140. positionEc2D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEc2D)) * normalEC; // prevent artifacts when czm_metersPerPixel is negative (behind camera)
  141. // Blend for actual position
  142. gl_Position = czm_projection * mix(positionEc2D, positionEc3D, czm_morphTime);
  143. #ifdef ANGLE_VARYING
  144. // Approximate relative screen space direction of the line.
  145. vec2 approxLineDirection = normalize(vec2(v_forwardDirectionEC.x, -v_forwardDirectionEC.y));
  146. approxLineDirection.y = czm_branchFreeTernary(approxLineDirection.x == 0.0 && approxLineDirection.y == 0.0, -1.0, approxLineDirection.y);
  147. v_polylineAngle = czm_fastApproximateAtan(approxLineDirection.x, approxLineDirection.y);
  148. #endif
  149. }