EllipsoidFS.glsl 4.1 KB

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