windowToEyeCoordinates.glsl 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /**
  2. * Transforms a position from window to eye coordinates.
  3. * The transform from window to normalized device coordinates is done using components
  4. * of (@link czm_viewport} and {@link czm_viewportTransformation} instead of calculating
  5. * the inverse of <code>czm_viewportTransformation</code>. The transformation from
  6. * normalized device coordinates to clip coordinates is done using <code>fragmentCoordinate.w</code>,
  7. * which is expected to be the scalar used in the perspective divide. The transformation
  8. * from clip to eye coordinates is done using {@link czm_inverseProjection}.
  9. *
  10. * @name czm_windowToEyeCoordinates
  11. * @glslFunction
  12. *
  13. * @param {vec4} fragmentCoordinate The position in window coordinates to transform.
  14. *
  15. * @returns {vec4} The transformed position in eye coordinates.
  16. *
  17. * @see czm_modelToWindowCoordinates
  18. * @see czm_eyeToWindowCoordinates
  19. * @see czm_inverseProjection
  20. * @see czm_viewport
  21. * @see czm_viewportTransformation
  22. *
  23. * @example
  24. * vec4 positionEC = czm_windowToEyeCoordinates(gl_FragCoord);
  25. */
  26. vec4 czm_windowToEyeCoordinates(vec4 fragmentCoordinate)
  27. {
  28. // Reconstruct NDC coordinates
  29. float x = 2.0 * (fragmentCoordinate.x - czm_viewport.x) / czm_viewport.z - 1.0;
  30. float y = 2.0 * (fragmentCoordinate.y - czm_viewport.y) / czm_viewport.w - 1.0;
  31. float z = (fragmentCoordinate.z - czm_viewportTransformation[3][2]) / czm_viewportTransformation[2][2];
  32. vec4 q = vec4(x, y, z, 1.0);
  33. // Reverse the perspective division to obtain clip coordinates.
  34. q /= fragmentCoordinate.w;
  35. // Reverse the projection transformation to obtain eye coordinates.
  36. if (!(czm_inverseProjection == mat4(0.0))) // IE and Edge sometimes do something weird with != between mat4s
  37. {
  38. q = czm_inverseProjection * q;
  39. }
  40. else
  41. {
  42. float top = czm_frustumPlanes.x;
  43. float bottom = czm_frustumPlanes.y;
  44. float left = czm_frustumPlanes.z;
  45. float right = czm_frustumPlanes.w;
  46. float near = czm_currentFrustum.x;
  47. float far = czm_currentFrustum.y;
  48. q.x = (q.x * (right - left) + left + right) * 0.5;
  49. q.y = (q.y * (top - bottom) + bottom + top) * 0.5;
  50. q.z = (q.z * (near - far) - near - far) * 0.5;
  51. q.w = 1.0;
  52. }
  53. return q;
  54. }
  55. /**
  56. * Transforms a position given as window x/y and a depth or a log depth from window to eye coordinates.
  57. * This function produces more accurate results for window positions with log depth than
  58. * conventionally unpacking the log depth using czm_reverseLogDepth and using the standard version
  59. * of czm_windowToEyeCoordinates.
  60. *
  61. * @name czm_windowToEyeCoordinates
  62. * @glslFunction
  63. *
  64. * @param {vec2} fragmentCoordinateXY The XY position in window coordinates to transform.
  65. * @param {float} depthOrLogDepth A depth or log depth for the fragment.
  66. *
  67. * @see czm_modelToWindowCoordinates
  68. * @see czm_eyeToWindowCoordinates
  69. * @see czm_inverseProjection
  70. * @see czm_viewport
  71. * @see czm_viewportTransformation
  72. *
  73. * @returns {vec4} The transformed position in eye coordinates.
  74. */
  75. vec4 czm_windowToEyeCoordinates(vec2 fragmentCoordinateXY, float depthOrLogDepth)
  76. {
  77. // See reverseLogDepth.glsl. This is separate to re-use the pow.
  78. #ifdef LOG_DEPTH
  79. float near = czm_currentFrustum.x;
  80. float far = czm_currentFrustum.y;
  81. float log2Depth = depthOrLogDepth * czm_log2FarDepthFromNearPlusOne;
  82. float depthFromNear = pow(2.0, log2Depth) - 1.0;
  83. float depthFromCamera = depthFromNear + near;
  84. vec4 windowCoord = vec4(fragmentCoordinateXY, far * (1.0 - near / depthFromCamera) / (far - near), 1.0);
  85. vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);
  86. eyeCoordinate.w = 1.0 / depthFromCamera; // Better precision
  87. return eyeCoordinate;
  88. #else
  89. vec4 windowCoord = vec4(fragmentCoordinateXY, depthOrLogDepth, 1.0);
  90. vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);
  91. #endif
  92. return eyeCoordinate;
  93. }