EllipsoidFS.glsl 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #ifdef WRITE_DEPTH
  2. #ifdef GL_EXT_frag_depth
  3. #extension GL_EXT_frag_depth : enable
  4. #endif
  5. #endif
  6. uniform vec3 u_radii;
  7. uniform vec3 u_oneOverEllipsoidRadiiSquared;
  8. varying vec3 v_positionEC;
  9. vec4 computeEllipsoidColor(czm_ray ray, float intersection, float side)
  10. {
  11. vec3 positionEC = czm_pointAlongRay(ray, intersection);
  12. vec3 positionMC = (czm_inverseModelView * vec4(positionEC, 1.0)).xyz;
  13. vec3 geodeticNormal = normalize(czm_geodeticSurfaceNormal(positionMC, vec3(0.0), u_oneOverEllipsoidRadiiSquared));
  14. vec3 sphericalNormal = normalize(positionMC / u_radii);
  15. vec3 normalMC = geodeticNormal * side; // normalized surface normal (always facing the viewer) in model coordinates
  16. vec3 normalEC = normalize(czm_normal * normalMC); // normalized surface normal in eye coordiantes
  17. vec2 st = czm_ellipsoidWgs84TextureCoordinates(sphericalNormal);
  18. vec3 positionToEyeEC = -positionEC;
  19. czm_materialInput materialInput;
  20. materialInput.s = st.s;
  21. materialInput.st = st;
  22. materialInput.str = (positionMC + u_radii) / u_radii;
  23. materialInput.normalEC = normalEC;
  24. materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(positionMC, normalEC);
  25. materialInput.positionToEyeEC = positionToEyeEC;
  26. czm_material material = czm_getMaterial(materialInput);
  27. #ifdef ONLY_SUN_LIGHTING
  28. return czm_private_phong(normalize(positionToEyeEC), material);
  29. #else
  30. return czm_phong(normalize(positionToEyeEC), material);
  31. #endif
  32. }
  33. void main()
  34. {
  35. // PERFORMANCE_TODO: When dynamic branching is available, compute ratio of maximum and minimum radii
  36. // in the vertex shader. Only when it is larger than some constant, march along the ray.
  37. // Otherwise perform one intersection test which will be the common case.
  38. // Test if the ray intersects a sphere with the ellipsoid's maximum radius.
  39. // For very oblate ellipsoids, using the ellipsoid's radii for an intersection test
  40. // may cause false negatives. This will discard fragments before marching the ray forward.
  41. float maxRadius = max(u_radii.x, max(u_radii.y, u_radii.z)) * 1.5;
  42. vec3 direction = normalize(v_positionEC);
  43. vec3 ellipsoidCenter = czm_modelView[3].xyz;
  44. float t1 = -1.0;
  45. float t2 = -1.0;
  46. float b = -2.0 * dot(direction, ellipsoidCenter);
  47. float c = dot(ellipsoidCenter, ellipsoidCenter) - maxRadius * maxRadius;
  48. float discriminant = b * b - 4.0 * c;
  49. if (discriminant >= 0.0) {
  50. t1 = (-b - sqrt(discriminant)) * 0.5;
  51. t2 = (-b + sqrt(discriminant)) * 0.5;
  52. }
  53. if (t1 < 0.0 && t2 < 0.0) {
  54. discard;
  55. }
  56. float t = min(t1, t2);
  57. if (t < 0.0) {
  58. t = 0.0;
  59. }
  60. // March ray forward to intersection with larger sphere and find
  61. // actual intersection point with ellipsoid.
  62. czm_ellipsoid ellipsoid = czm_ellipsoidNew(ellipsoidCenter, u_radii);
  63. czm_ray ray = czm_ray(t * direction, direction);
  64. czm_raySegment intersection = czm_rayEllipsoidIntersectionInterval(ray, ellipsoid);
  65. if (czm_isEmpty(intersection))
  66. {
  67. discard;
  68. }
  69. // If the viewer is outside, compute outsideFaceColor, with normals facing outward.
  70. vec4 outsideFaceColor = (intersection.start != 0.0) ? computeEllipsoidColor(ray, intersection.start, 1.0) : vec4(0.0);
  71. // If the viewer either is inside or can see inside, compute insideFaceColor, with normals facing inward.
  72. vec4 insideFaceColor = (outsideFaceColor.a < 1.0) ? computeEllipsoidColor(ray, intersection.stop, -1.0) : vec4(0.0);
  73. gl_FragColor = mix(insideFaceColor, outsideFaceColor, outsideFaceColor.a);
  74. gl_FragColor.a = 1.0 - (1.0 - insideFaceColor.a) * (1.0 - outsideFaceColor.a);
  75. #ifdef WRITE_DEPTH
  76. #ifdef GL_EXT_frag_depth
  77. t = (intersection.start != 0.0) ? intersection.start : intersection.stop;
  78. vec3 positionEC = czm_pointAlongRay(ray, t);
  79. vec4 positionCC = czm_projection * vec4(positionEC, 1.0);
  80. float z = positionCC.z / positionCC.w;
  81. float n = czm_depthRange.near;
  82. float f = czm_depthRange.far;
  83. gl_FragDepthEXT = (z * (f - n) + f + n) * 0.5;
  84. #endif
  85. #endif
  86. }