Objects culled when using Oblique projection

Hi all,

I am trying to make portals using render textures from secondary cameras displayed onto a quad.
I’m using an oblique projection matrix to avoid rendering any objects in front of a plane (the secondary cameras are placed in positions relative to the main camera, so objects sometimes fall in between the output point of the portal and the camera)

When looking through the portals sometimes objects will suddenly disappear, as if they were culled. There is no in between, they are rendered normally, then they will disappear. Though their shadows remain.

This occurs with most objects, except for large objects like the floor. It occurs when the objects are on the sides of the screen and does not occur only when viewing nearly perpendicular to the quad displaying the render texture.


Looking slightly to the right, the object disappears:

I am using Unity 6.3LTS with URP. I first position the secondary camera, set their projection matrix, then manually render using SubmitRenderRequest. This is repeated for every secondary camera.

The code to set the oblique matrix:

    // Use custom projection matrix to align portal camera's near clip plane with the surface of the portal
    void SetNearClipPlane(Camera viewingCam)
    {
        portalCam.projectionMatrix = Camera.main.projectionMatrix;

        Transform clipPlane = transform;
        int dot = System.Math.Sign(Vector3.Dot(clipPlane.forward, transform.position - portalCam.transform.position));

        Vector3 camSpacePos = portalCam.worldToCameraMatrix.MultiplyPoint(clipPlane.position);
        Vector3 camSpaceNormal = portalCam.worldToCameraMatrix.MultiplyVector(clipPlane.forward) * dot;
        float camSpaceDst = -Vector3.Dot(camSpacePos, camSpaceNormal) + nearClipOffset;

        Vector4 clipPlaneCameraSpace = new Vector4(camSpaceNormal.x, camSpaceNormal.y, camSpaceNormal.z, camSpaceDst);

        portalCam.projectionMatrix = portalCam.CalculateObliqueMatrix(clipPlaneCameraSpace);
    }

I have tried the following:

  • Disabling all occlusion culling
  • Setting a custom culling matrix for the camera
  • Changing the bounds of the renderer that keeps disappearing
  • Using Camera.Render()
  • Enabling all renderers just before the camera renders

I am wondering the following:

  • Is culling causing this issue?
  • Is this to due with the object being culled from the main camera and thus it being culled in the secondary cams?
  • Is this due to how I create the oblique matrix, oblique matrices in general, or the URP pipeline?
  • How do I resolve this issue?

Right now my alternative seems to be to rewrite the URP lit shader but add in a clip plane in the fragment shader, then apply that shader to every object that might be infront of the plane, though I would prefer not to do this and I am also generally curious what the issue is.

A similar project that has helped me is Portals by SebLague (it won’t let me share the link)

I’d appreciate any help and if you need more details let me know.

You said you tried setting a custom culling mask. How did you calculate that culling mask? Did you use the normal projection matrix of the main camera? If you use the oblique matrix you would get the same result. I’m not 100% sure if the oblique projection matrix would cause this, but yes, it seems to be a culling problem. The engine usually discards any objects which bounding box is outside the view frustum. With an oblique projection matrix it may result in some edge cases. Using the original projection matrix.

I’ve never used a custom culling matrix, but in your case you probably want to do something like:

portalCam.cullingMatrix = Camera.main.projectionMatrix * Camera.main.worldToCameraMatrix;

This should make your portal camera cull objects like the main camera.

Hello,

With regards to culling masks, the only thing I’ve tried is setting the object that is disappearing to a mask which the main camera does not use, but the portal camera does.

I have tried setting the culling matrix to be some of the following:

  • The method you suggested Camera.main.projectionMatrix * Camera.main.worldToCameraMatrix;
  • The portal cameras standard projection matrix without oblique
  • The main cameras projection matrix & the main cams culling matrix
  • A large ortho Matrix4x4.Ortho(-99999f, 99999f, -99999f, 99999f, 0.01f, 99999f);
  • Matrix4x4.zero;

I have tried setting the culling matrix after I set the projection matrix and also in callbacks such as OnBeginCameraRendering.

I have also tried resetting the CullingMatrix and ProjectionMatrix before and after I render each frame.

Also as a note I call SubmitRenderRequest from LateUpdate.

Thank you for your time.