lines.vert 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. *
  6. * heavily based on code by WestLangley from https://github.com/WestLangley/three.js/blob/af28b2fb706ac109771ecad0a7447fad90ab3210/examples/js/lines/LineMaterial.js
  7. */
  8. precision highp float;
  9. precision highp int;
  10. #include common
  11. #include read_from_texture
  12. #include common_vert_params
  13. #include color_vert_params
  14. #include size_vert_params
  15. uniform float uPixelRatio;
  16. uniform float uViewportHeight;
  17. attribute vec3 aPosition;
  18. attribute mat4 aTransform;
  19. attribute float aInstance;
  20. attribute float aGroup;
  21. attribute vec2 aMapping;
  22. attribute vec3 aStart;
  23. attribute vec3 aEnd;
  24. void trimSegment(const in vec4 start, inout vec4 end) {
  25. // trim end segment so it terminates between the camera plane and the near plane
  26. // conservative estimate of the near plane
  27. float a = uProjection[2][2]; // 3nd entry in 3th column
  28. float b = uProjection[3][2]; // 3nd entry in 4th column
  29. float nearEstimate = -0.5 * b / a;
  30. float alpha = (nearEstimate - start.z) / (end.z - start.z);
  31. end.xyz = mix(start.xyz, end.xyz, alpha);
  32. }
  33. void main(){
  34. #include assign_group
  35. #include assign_color_varying
  36. #include assign_marker_varying
  37. #include assign_size
  38. mat4 modelView = uView * uModel * aTransform;
  39. // camera space
  40. vec4 start = modelView * vec4(aStart, 1.0);
  41. vec4 end = modelView * vec4(aEnd, 1.0);
  42. // special case for perspective projection, and segments that terminate either in, or behind, the camera plane
  43. // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space
  44. // but we need to perform ndc-space calculations in the shader, so we must address this issue directly
  45. // perhaps there is a more elegant solution -- WestLangley
  46. bool perspective = (uProjection[2][3] == -1.0); // 4th entry in the 3rd column
  47. if (perspective) {
  48. if (start.z < 0.0 && end.z >= 0.0) {
  49. trimSegment(start, end);
  50. } else if (end.z < 0.0 && start.z >= 0.0) {
  51. trimSegment(end, start);
  52. }
  53. }
  54. // clip space
  55. vec4 clipStart = uProjection * start;
  56. vec4 clipEnd = uProjection * end;
  57. // ndc space
  58. vec2 ndcStart = clipStart.xy / clipStart.w;
  59. vec2 ndcEnd = clipEnd.xy / clipEnd.w;
  60. // direction
  61. vec2 dir = ndcEnd - ndcStart;
  62. // account for clip-space aspect ratio
  63. dir.x *= uPixelRatio;
  64. dir = normalize(dir);
  65. // perpendicular to dir
  66. vec2 offset = vec2(dir.y, - dir.x);
  67. // undo aspect ratio adjustment
  68. dir.x /= uPixelRatio;
  69. offset.x /= uPixelRatio;
  70. // sign flip
  71. if (aMapping.x < 0.0) offset *= -1.0;
  72. // calculate linewidth
  73. float linewidth;
  74. #ifdef dLineSizeAttenuation
  75. linewidth = size * uPixelRatio * ((uViewportHeight / 2.0) / -start.z) * 5.0;
  76. #else
  77. linewidth = size * uPixelRatio;
  78. #endif
  79. // adjust for linewidth
  80. offset *= linewidth;
  81. // adjust for clip-space to screen-space conversion
  82. offset /= uViewportHeight;
  83. // select end
  84. vec4 clip = (aMapping.y < 0.5) ? clipStart : clipEnd;
  85. // back to clip space
  86. offset *= clip.w;
  87. clip.xy += offset;
  88. gl_Position = clip;
  89. }