On the issue of camera space chirality

I have consulted some information and done some experiments. When I get the depth map of nonlinear space from depthRenderer and convert it to linear space, I find that the camera space is not what I expected. By the way, the conversion function comes from unity. In unity, only the camera space is a right-handed coordinate system, and the rest are left-handed coordinate systems. I tried to modify it to conform to the left-handed coordinate system, but the final result was not as expected. When I did not make any changes, I found that the result was as expected. So can it be inferred that the camera space in babylon is right-handed like unity? Is there any corresponding literature or information to explain it?
here is conversion functions

float Linear01Depth(sampler2D depthTexture, vec2 coord) {
  float depth = texture2D(depthTexture, coord).x;
  float x = 1. - cameraFar / cameraNear;
  float y = cameraFar / cameraNear;
  float z = x / cameraFar;
  float w = y / cameraFar;
  return 1.0 / (x * depth + y);
}

in unity source code

// Z buffer to linear 0..1 depth
inline float Linear01Depth( float z )
{
    return 1.0 / (_ZBufferParams.x * z + _ZBufferParams.y);
}

about _ZBufferParams docs:
https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html

here is demo link
https://playground.babylonjs.com/#JCP5UC

here is the conversion function I modified to conform to the left-handed coordinate system,
you can uncomment the demo to see the result. The result is not as expected.

 float Linear01Depth(sampler2D depthTexture, vec2 coord) {
        loat depth = texture2D(depthTexture, coord).x;
        float x = (uCameraFar / uCameraNear) - 1.;
        float y = uCameraFar / uCameraNear;
        return 1.0 / (x * depth - y);
        }

Babylon is left-handed, unless you enabled the right handed flag on scene.
From seeing your shader (though I don’t 100% understand the question), depth must be positive. The data you are passing is not related to left handed or right handed. You are using camera near and camera far, which are always two positive floats - min being the minimum distance the camera will render, and max being the maximum.
Apologies if I didn’t understand the question, I hope this helps.

I added a demo to explain my confusion, what works and works is the conversion function in unity. In unity the camera space is in right-handed coordinate system which means looking in the -z direction so they added -1 to convert the derived formula, but in babylon this also works, I have provided a function to convert to left-handed coordinate system but it does not work properly. What am I doing wrong?

I don’t see anything you are going wrong. I also don’t see anything related to right-handed vs. left-handed space. you are defining a color, which needs to be positive, meaning, you depth variable needs to be positive. The uCameraFar is a large number, uCameraNear is a low number, but both are positive. The texture2D call on the depth texture also provides positive numbers.

Maybe it would be helpful to understand what you are trying to achieve.


This is the formula derivation. Unity’s observation space is a right-handed coordinate system. The Zview calculated here is a negative value, so it needs to be multiplied by -1 to get a positive value. The range of this formula is [near, far] and it needs to be divided by far to map to [near/far, 1]. In other words, the formula derived here is divided by far and then multiplied by -1, which works normally. However, as you said, babylon is a left-handed system, which means it does not need to be multiplied by -1. The function without multiplication by -1 should be applied. The function without multiplication by -1 has been commented out in my demo and it does not work properly.

cc @Evgeni_Popov

Here’s the derivation of Zndc from Zview in Babylon:

We need it in reverse, so Zview = d / (Zndc - c).

In the left-handed system of Babylon, c = (f + n) / (f - n) and d = -2nf / (f - n) (see Babylon.js/packages/dev/core/src/Maths/math.vector.ts at master · BabylonJS/Babylon.js · GitHub). c and d can also be retrieved from the projection matrix as shown in the first link above.

Here’s the PG with this implementation: https://playground.babylonjs.com/#JCP5UC#7

I set minZ = 8 and maxZ = 11 to better see what is happening and to make sure n is not too small in relation to f, in which case (f + n) and (f - n) are not very different from f, which could hide bugs in the implementation.

Your PG with these clip planes: https://playground.babylonjs.com/#JCP5UC#6

We can see that the output of your PG is wrong, because the color of the plane should change from black to white, since it is clipped by the near and far planes.

The output from the first PG:

1 Like

I understand what you mean but when I derive the formula starting from the projection matrix of dx, I get the same result as unity. This confuses me

Now I understand that when I start to derive the formula from Direct’s perspective projection matrix, I get this function encapsulated in the Unity source code. This function has near/far as the near plane is near/far, and the far plane is 1. In the PG you provided, the near plane is mapped to 0 and the far plane is 1. This is the reason for the difference. The underlying formulas of both are correct. Thanks!

I modified the value range of Unity’s function to be between 0 and 1(PG):https://playground.babylonjs.com/#JCP5UC#9

1 Like