Projection Matrix "m23" is changed before it gets passed to shader?

I have created a custom projection matrix I use with a native plugin. I want to match Unity3D’s projection matrix perfectly.
Problem is Unity is changing the projection matrix “m23” value BEFORE it gets set to UNITY_MATRIX_P but idk what that change is.

If I multiply using the built in values everything is fine:

However if I pass in the matrix values as constant values it doesn’t work.

Here is the code for a custom projection matrix but what do I need to change on “m23” to make it match Unity’s shaders modification?

Matrix4x4 CreateProjection(float near, float far, float fov, float width, float height)
    {
        float depth = far - near;
        float top = 1.0f / Mathf.Tan(MathUtilities.DegToRad(fov) * .5f);
        float aspect = (width / height);
        float right = top / aspect;

        var result = new Matrix4x4();
        result.m00 = right;
        result.m01 = 0;
        result.m02 = 0;
        result.m03 = 0;

        result.m10 = 0;
        result.m11 = top;
        result.m12 = 0;
        result.m13 = 0;

        result.m20 = 0;
        result.m21 = 0;
        result.m22 = -(far+near) / depth;
        result.m23 = -(2*near*far) / depth;// Unity changes this value BEFORE UNITY_MATRIX_P is set

        result.m30 = 0;
        result.m31 = 0;
        result.m32 = -1;
        result.m33 = 0;
        return result;
    }

NOTE: This thread is to illustrate an issue with Unity not giving access to the actual projection matrix being used.

I know this is the issue because if I do the following in the shader it also works correctly:

projMatrix[2][3] = UNITY_MATRIX_P[2][3];
float4x4 camera = mul(projMatrix, viewMatrix);
o.vertex = mul(camera, v.vertex);

Unity changes the projection matrix because it depends on the underlying graphics API. For instance, the projection matrices to be passed in openGL and direct3d are not the same. Hence, hardcoding a projection matrix in a script would result in inconsistent results on different plateforms. This is why Unity has to modify them to ensure the consistency.

There are more information here: projection matrix in unity - Questions & Answers - Unity Discussions
and perhaps the GL.GetGPUProjectionMatrix method will help you out.

IDK of any differences in OGL2-3 vs D3D9-11 in the clipping planes that would need this to be different? The only difference Iv’e run into in native GLSL/HLSL is row vs column majors and this is simply fixed by reverse multiply or transposing the matrix. The zbuffer should function the same with the same matrix and bit (unless I’m forgetting something else about GL).

In either case thats probably the solution I wanted, tnx!

It’s a bit old, but I thought it might have something to do with my problem . Do you have any ideas? I haven’t found a solution yet.

https://discussions.unity.com/t/749349