/**
|
* Transforms a position from window to eye coordinates.
|
* The transform from window to normalized device coordinates is done using components
|
* of (@link czm_viewport} and {@link czm_viewportTransformation} instead of calculating
|
* the inverse of <code>czm_viewportTransformation</code>. The transformation from
|
* normalized device coordinates to clip coordinates is done using <code>fragmentCoordinate.w</code>,
|
* which is expected to be the scalar used in the perspective divide. The transformation
|
* from clip to eye coordinates is done using {@link czm_inverseProjection}.
|
*
|
* @name czm_windowToEyeCoordinates
|
* @glslFunction
|
*
|
* @param {vec4} fragmentCoordinate The position in window coordinates to transform.
|
*
|
* @returns {vec4} The transformed position in eye coordinates.
|
*
|
* @see czm_modelToWindowCoordinates
|
* @see czm_eyeToWindowCoordinates
|
* @see czm_inverseProjection
|
* @see czm_viewport
|
* @see czm_viewportTransformation
|
*
|
* @example
|
* vec4 positionEC = czm_windowToEyeCoordinates(gl_FragCoord);
|
*/
|
vec4 czm_windowToEyeCoordinates(vec4 fragmentCoordinate)
|
{
|
// Reconstruct NDC coordinates
|
float x = 2.0 * (fragmentCoordinate.x - czm_viewport.x) / czm_viewport.z - 1.0;
|
float y = 2.0 * (fragmentCoordinate.y - czm_viewport.y) / czm_viewport.w - 1.0;
|
float z = (fragmentCoordinate.z - czm_viewportTransformation[3][2]) / czm_viewportTransformation[2][2];
|
vec4 q = vec4(x, y, z, 1.0);
|
|
// Reverse the perspective division to obtain clip coordinates.
|
q /= fragmentCoordinate.w;
|
|
// Reverse the projection transformation to obtain eye coordinates.
|
if (!(czm_inverseProjection == mat4(0.0))) // IE and Edge sometimes do something weird with != between mat4s
|
{
|
q = czm_inverseProjection * q;
|
}
|
else
|
{
|
float top = czm_frustumPlanes.x;
|
float bottom = czm_frustumPlanes.y;
|
float left = czm_frustumPlanes.z;
|
float right = czm_frustumPlanes.w;
|
|
float near = czm_currentFrustum.x;
|
float far = czm_currentFrustum.y;
|
|
q.x = (q.x * (right - left) + left + right) * 0.5;
|
q.y = (q.y * (top - bottom) + bottom + top) * 0.5;
|
q.z = (q.z * (near - far) - near - far) * 0.5;
|
q.w = 1.0;
|
}
|
|
return q;
|
}
|
|
/**
|
* Transforms a position given as window x/y and a depth or a log depth from window to eye coordinates.
|
* This function produces more accurate results for window positions with log depth than
|
* conventionally unpacking the log depth using czm_reverseLogDepth and using the standard version
|
* of czm_windowToEyeCoordinates.
|
*
|
* @name czm_windowToEyeCoordinates
|
* @glslFunction
|
*
|
* @param {vec2} fragmentCoordinateXY The XY position in window coordinates to transform.
|
* @param {float} depthOrLogDepth A depth or log depth for the fragment.
|
*
|
* @see czm_modelToWindowCoordinates
|
* @see czm_eyeToWindowCoordinates
|
* @see czm_inverseProjection
|
* @see czm_viewport
|
* @see czm_viewportTransformation
|
*
|
* @returns {vec4} The transformed position in eye coordinates.
|
*/
|
vec4 czm_windowToEyeCoordinates(vec2 fragmentCoordinateXY, float depthOrLogDepth)
|
{
|
// See reverseLogDepth.glsl. This is separate to re-use the pow.
|
#ifdef LOG_DEPTH
|
float near = czm_currentFrustum.x;
|
float far = czm_currentFrustum.y;
|
float log2Depth = depthOrLogDepth * czm_log2FarDepthFromNearPlusOne;
|
float depthFromNear = pow(2.0, log2Depth) - 1.0;
|
float depthFromCamera = depthFromNear + near;
|
vec4 windowCoord = vec4(fragmentCoordinateXY, far * (1.0 - near / depthFromCamera) / (far - near), 1.0);
|
vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);
|
eyeCoordinate.w = 1.0 / depthFromCamera; // Better precision
|
return eyeCoordinate;
|
#else
|
vec4 windowCoord = vec4(fragmentCoordinateXY, depthOrLogDepth, 1.0);
|
vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);
|
#endif
|
return eyeCoordinate;
|
}
|