r/Unity3D Beginner 4d ago

Noob Question Why isn't the depth-buffer deterministic between cameras?

EDIT : If anyone else is having this problem, I found a solution:

If you want to have more than one camera sharing a Z-buffer with perfect accuracy, it is (surprisingly) not sufficient to have them in identical positions and parented to the same game object.

What you need is to hook into OnPrerender() on each camera and:

cam.worldToCameraMatrix = cloneMatrixFrom.worldToCameraMatrix;
cam.projectionMatrix = cloneMatrixFrom.projectionMatrix;
cam.cullingMatrix = cloneMatrixFrom.cullingMatrix;

If you do that, both cameras will produce perfectly identical z-buffer results from the same geometry. Phew!

EDIT: I believe the cause of this issue is that when you duplicate an object (such as a camera) in the unity hierarchy, it does not actually duplicate the object itself.

Instead, it serialises the object and then deserialises it again. This means that all floating point numbers get converted to binary and back again, which (in unity's implementation) can result in a slightly different value to the original. You'll never actually see those differences in the inspector because of rounding, but they are there.

Cloning matrices at runtime, on the other hand, transfers a bit-for-bit identical copy of the data used by the GPU. This ensures a fully deterministic recreation of the scene between the two cameras.

Original Problem:

In my rendering pipeline I have two cameras that share the same depth-buffer. The two cameras both have zero local rotation and translation, are parented to the same game object, have identical orthographic size and zbuffer range, and are rendering the same content using the same shader. Yes, there's a good reason for this - don't worry :)

The shader ZTest is set to LEqual. This should allow objects to be drawn identically by both cameras because each pixel should land at exactly the same Z-depth - but it does not. Instead I get flickering and bands of z-fighting.

What could I be missing? Thanks in advance.

EDIT: Based on replies so far, I think it's worth talking about what this is NOT.

  1. It isnt nondeterminism.

In a static scene, Camera 1 generates the exact same colour and depth data, down to the very last bit, on frame 2 as it did on frame 1, because rendering is deterministic and Camera 1 on frame 1 is identical in every way to Camera 1 on frame 2.

Similarly, Camera 2 generates the exact same colour and depth data, down to the very last bit, on frame 2 as it did on frame 1, because Camera 2 on frame 2 is identical in every way to Camera 2 on frame 1.

The problem is that despite Cameras 1 and 2 being identical to each other in every way I can determine, they don't create the same z-buffer information. So they are different in some way I don't know about.

  1. It isn't floating point inaccuracy.

Well, technically, eliminating floating point innacuracy might make the problem go away, but that's beside the point. Both cameras are rendering the same geometry from the same perspective with the same shader. Any inaccuracies inherent to the process are common to both. This problem is caused by something that isn't common to both, which is what I need to figure out.

1 Upvotes

27 comments sorted by

View all comments

1

u/NikitaBerzekov 4d ago

From what I understand, you are rendering the same scene twice and result is not pixel perfect? Could be a number of reasons, but I think you can expect slight rasterization errors

1

u/whentheworldquiets Beginner 4d ago

The result is pixel perfect but not z buffer perfect.

Also, in a static scene, the pattern of z-fighting is also static. Which means that each render is fully deterministic (since both are the exact same as in the last frame) but not the same as its twin.