It’s depth, not distance, from camera origin to vertex, assuming a perspective projection matrix that’s focused on the camera’s origin, which most perspective projection matrices are calculated to be. And certainly the Unity camera’s perspective projection matrix is unless manually overridden.

LinearEyeDepth takes the depth from the non-linear depth buffer and converts it to linear eye depth, which is roughly identical to the clip space w in precision. It’s also the same value you get from the COMPUTE_EYEDEPTH macro when in the vertex function, though that’s calculated by applying the world and view matrices to the object space vertex position.

So why all of the different versions of this?

When using anything but the usual projection matrix, w component of the clip space position is not the view/eye depth. In fact when it’s an orthographic camera it’s a constant value. So if you need the linear depth for something and want to make sure your shader supports all projection matrix types, you can’t rely on the w being the depth. Plus, you often want to know the depth of a vertex in the fragment shader prior to calculating the clip space position. So that’s where COMPUTE_EYEDEPTH comes in.

What about LinearEyeDepth? That’s taking the value from the non-linear depth buffer and converting it into linear depth as I mentioned above. This is often the depth from the camera depth texture rather than some value interpolated from the current shader’s vertex stage. But you could get it the depth buffer value for a mesh from the input.pos.z value in the above shader, as that”s what that value holds in the fragment shader. But that’s extra math, including a divide that can be costly on some hardware. So it’s often better passed separately. Plus the conversion from non-linear depth buffer to linear depth buffer is actually broken in Unity if you’re using something other than a default perspective projection matrix since that function assumes some stuff (mainly that you are using a default projection matrix) so it can simplify the math.

But wait, I said you can access the input.pos, which is the same as the output.pos from the vertex function, which means the input.pos.w holds the linear depth! Right? Nope. Even assuming a perspective matrix this isn’t the case. The value you output from the vertex function is in clip space, but that same variable input into the fragment shader has been transformed into window space by the GPU. The x and y are now the screen pixel position, z is the non-linear depth buffer (which has a 0.0 to 1.0 range for all graphics APIs, remember I said clip space is 0.0 to w on some, and -w to w on otheres), and the w is 1.0. Yes, just 1.0, always. That’s because it’s the w component after the GPU applied the perspective divide, which is dividing the whole float4 value by the w, and any non zero number divided by itself is 1.0.

Now let’s look at why specifically the ComputeScreenPos passes the w value. This is so it can apply the perspective divide to the interpolated position. When using a non-orthographic projection, a screen space interpolated float3 position won’t interpolate the way you’d expect in 3D space. You’ll get odd warping and stretching of the value between the vertices as they’re being interpolated linearly in 2D screen space, not in 3D view space. Remember all that weird texture warping from old PS1 games? It’s that. Using a perspective divide let’s you interpolate a float4 value and correct the “2D” linear interpolation to take into account the perspective making they work as you would expect them to. So really that’s all it’s there for.

So, the shader example above is making use of the w component as an optimization, by assuming the use of a perspective matrix, they know that value used to correct for perspective interpolation is also the view depth.