cylinders.frag.ts 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /**
  2. * Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. export const cylinders_frag = `
  7. precision highp float;
  8. precision highp int;
  9. #define bumpEnabled
  10. uniform mat4 uView;
  11. varying mat4 vTransform;
  12. varying vec3 vStart;
  13. varying vec3 vEnd;
  14. varying float vSize;
  15. varying float vCap;
  16. varying float vColorMode;
  17. uniform vec3 uCameraDir;
  18. uniform vec3 uCameraPosition;
  19. uniform mat4 uInvView;
  20. #include common
  21. #include common_frag_params
  22. #include color_frag_params
  23. #include light_frag_params
  24. #include common_clip
  25. #ifdef dSolidInterior
  26. const bool solidInterior = true;
  27. #else
  28. const bool solidInterior = false;
  29. #endif
  30. // adapted from https://www.shadertoy.com/view/4lcSRn
  31. // The MIT License, Copyright 2016 Inigo Quilez
  32. bool CylinderImpostor(
  33. in vec3 rayOrigin, in vec3 rayDir,
  34. in vec3 start, in vec3 end, in float radius,
  35. out vec3 cameraNormal, out bool interior,
  36. out vec3 modelPosition, out vec3 viewPosition, out float fragmentDepth
  37. ){
  38. vec3 ba = end - start;
  39. vec3 oc = rayOrigin - start;
  40. float baba = dot(ba, ba);
  41. float bard = dot(ba, rayDir);
  42. float baoc = dot(ba, oc);
  43. float k2 = baba - bard * bard;
  44. float k1 = baba * dot(oc, rayDir) - baoc * bard;
  45. float k0 = baba * dot(oc, oc) - baoc * baoc - radius * radius * baba;
  46. float h = k1 * k1 - k2 * k0;
  47. if (h < 0.0) return false;
  48. bool topCap = (vCap > 0.9 && vCap < 1.1) || vCap >= 2.9;
  49. bool bottomCap = (vCap > 1.9 && vCap < 2.1) || vCap >= 2.9;
  50. #ifdef dSolidInterior
  51. bool topInterior = !topCap;
  52. bool bottomInterior = !bottomCap;
  53. topCap = true;
  54. bottomCap = true;
  55. #else
  56. bool topInterior = false;
  57. bool bottomInterior = false;
  58. #endif
  59. bool clipped = false;
  60. bool objectClipped = false;
  61. // body outside
  62. h = sqrt(h);
  63. float t = (-k1 - h) / k2;
  64. float y = baoc + t * bard;
  65. if (y > 0.0 && y < baba) {
  66. interior = false;
  67. cameraNormal = (oc + t * rayDir - ba * y / baba) / radius;
  68. modelPosition = rayOrigin + t * rayDir;
  69. viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
  70. fragmentDepth = calcDepth(viewPosition);
  71. #if defined(dClipVariant_pixel) && dClipObjectCount != 0
  72. if (clipTest(vec4(modelPosition, 0.0))) {
  73. objectClipped = true;
  74. fragmentDepth = -1.0;
  75. #ifdef dSolidInterior
  76. topCap = !topInterior;
  77. bottomCap = !bottomInterior;
  78. #endif
  79. }
  80. #endif
  81. if (fragmentDepth > 0.0) return true;
  82. clipped = true;
  83. }
  84. if (!clipped) {
  85. if (topCap && y < 0.0) {
  86. // top cap
  87. t = -baoc / bard;
  88. if (abs(k1 + k2 * t) < h) {
  89. interior = topInterior;
  90. cameraNormal = -ba / baba;
  91. modelPosition = rayOrigin + t * rayDir;
  92. viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
  93. fragmentDepth = calcDepth(viewPosition);
  94. #if defined(dClipVariant_pixel) && dClipObjectCount != 0
  95. if (clipTest(vec4(modelPosition, 0.0))) {
  96. objectClipped = true;
  97. fragmentDepth = -1.0;
  98. #ifdef dSolidInterior
  99. topCap = !topInterior;
  100. bottomCap = !bottomInterior;
  101. #endif
  102. }
  103. #endif
  104. if (fragmentDepth > 0.0) {
  105. #ifdef dSolidInterior
  106. if (interior) cameraNormal = -rayDir;
  107. #endif
  108. return true;
  109. }
  110. }
  111. } else if (bottomCap && y >= 0.0) {
  112. // bottom cap
  113. t = (baba - baoc) / bard;
  114. if (abs(k1 + k2 * t) < h) {
  115. interior = bottomInterior;
  116. cameraNormal = ba / baba;
  117. modelPosition = rayOrigin + t * rayDir;
  118. viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
  119. fragmentDepth = calcDepth(viewPosition);
  120. #if defined(dClipVariant_pixel) && dClipObjectCount != 0
  121. if (clipTest(vec4(modelPosition, 0.0))) {
  122. objectClipped = true;
  123. fragmentDepth = -1.0;
  124. #ifdef dSolidInterior
  125. topCap = !topInterior;
  126. bottomCap = !bottomInterior;
  127. #endif
  128. }
  129. #endif
  130. if (fragmentDepth > 0.0) {
  131. #ifdef dSolidInterior
  132. if (interior) cameraNormal = -rayDir;
  133. #endif
  134. return true;
  135. }
  136. }
  137. }
  138. }
  139. if (uDoubleSided || solidInterior) {
  140. // body inside
  141. h = -h;
  142. t = (-k1 - h) / k2;
  143. y = baoc + t * bard;
  144. if (y > 0.0 && y < baba) {
  145. interior = true;
  146. cameraNormal = -(oc + t * rayDir - ba * y / baba) / radius;
  147. modelPosition = rayOrigin + t * rayDir;
  148. viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
  149. fragmentDepth = calcDepth(viewPosition);
  150. if (fragmentDepth > 0.0) {
  151. #ifdef dSolidInterior
  152. if (!objectClipped) {
  153. fragmentDepth = 0.0 + (0.0000002 / vSize);
  154. cameraNormal = -rayDir;
  155. }
  156. #endif
  157. return true;
  158. }
  159. }
  160. if (topCap && y < 0.0) {
  161. // top cap
  162. t = -baoc / bard;
  163. if (abs(k1 + k2 * t) < -h) {
  164. interior = true;
  165. cameraNormal = ba / baba;
  166. modelPosition = rayOrigin + t * rayDir;
  167. viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
  168. fragmentDepth = calcDepth(viewPosition);
  169. if (fragmentDepth > 0.0) {
  170. #ifdef dSolidInterior
  171. if (!objectClipped) {
  172. fragmentDepth = 0.0 + (0.0000002 / vSize);
  173. cameraNormal = -rayDir;
  174. }
  175. #endif
  176. return true;
  177. }
  178. }
  179. } else if (bottomCap && y >= 0.0) {
  180. // bottom cap
  181. t = (baba - baoc) / bard;
  182. if (abs(k1 + k2 * t) < -h) {
  183. interior = true;
  184. cameraNormal = -ba / baba;
  185. modelPosition = rayOrigin + t * rayDir;
  186. viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
  187. fragmentDepth = calcDepth(viewPosition);
  188. if (fragmentDepth > 0.0) {
  189. #ifdef dSolidInterior
  190. if (!objectClipped) {
  191. fragmentDepth = 0.0 + (0.0000002 / vSize);
  192. cameraNormal = -rayDir;
  193. }
  194. #endif
  195. return true;
  196. }
  197. }
  198. }
  199. }
  200. return false;
  201. }
  202. void main() {
  203. vec3 rayOrigin = vModelPosition;
  204. vec3 rayDir = mix(normalize(vModelPosition - uCameraPosition), uCameraDir, uIsOrtho);
  205. vec3 cameraNormal;
  206. vec3 modelPosition;
  207. vec3 viewPosition;
  208. float fragmentDepth;
  209. bool hit = CylinderImpostor(rayOrigin, rayDir, vStart, vEnd, vSize, cameraNormal, interior, modelPosition, viewPosition, fragmentDepth);
  210. if (!hit) discard;
  211. if (fragmentDepth < 0.0) discard;
  212. if (fragmentDepth > 1.0) discard;
  213. gl_FragDepthEXT = fragmentDepth;
  214. vec3 vViewPosition = viewPosition;
  215. vec3 vModelPosition = modelPosition;
  216. #include clip_pixel
  217. #include assign_material_color
  218. #if defined(dRenderVariant_pick)
  219. #include check_picking_alpha
  220. #ifdef requiredDrawBuffers
  221. gl_FragColor = vObject;
  222. gl_FragData[1] = vInstance;
  223. gl_FragData[2] = vGroup;
  224. gl_FragData[3] = packDepthToRGBA(fragmentDepth);
  225. #else
  226. gl_FragColor = vColor;
  227. #endif
  228. #elif defined(dRenderVariant_depth)
  229. gl_FragColor = material;
  230. #elif defined(dRenderVariant_marking)
  231. gl_FragColor = material;
  232. #elif defined(dRenderVariant_color)
  233. mat3 normalMatrix = transpose3(inverse3(mat3(uView)));
  234. vec3 normal = normalize(normalMatrix * -normalize(cameraNormal));
  235. #include apply_light_color
  236. #include apply_interior_color
  237. #include apply_marker_color
  238. #include apply_fog
  239. #include wboit_write
  240. #include dpoit_write
  241. #endif
  242. }
  243. `;