How does Camera.ViewportToWorldPoint() work under the hood?

I get the part of “inverse of projection * view”, as well as the normalized viewport coords. But how are Z and W calculated? If I insert Z as depth in [0,1], my world points are mostly near the camera. How do I fix this?

From the documentation:

So likely it’s just dividing out the projection’s perspective from x and y, then transforming that point by the cameraToWorld matrix.

I found it out by myself, it goes like this:

Matrix4x4 projectionMatrix = GL.GetGPUProjectionMatrix(myCamera.projectionMatrix, false);
Matrix4x4 worldToView = projectionMatrix * currentCamera.worldToCameraMatrix;
Matrix4x4 viewToWorld = worldToView.inverse;

float viewport_z01 = myViewSpaceZCoord;
float zFull = viewport_z01 * myCamera.farClipPlane;
float zNearToFar = Mathf.Lerp(myCamera.nearClipPlane, myCamera.farClipPlane, viewport_z01);
float alpha = zFull / zNearToFar;
Vector4 position = viewToWorld * new Vector4(viewport_x, viewport_y, 1 - alpha, 1f);
position.x /= position.w;
position.y /= position.w;
position.z /= position.w;

Hope this helps someone! :slight_smile:

4 Likes