cylinders.frag.ts 8.7 KB

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