koochyrat / SteamVRFrustumAdjust

For canted headsets like Pimax, calculate proper culling matrix to avoid objects being culled too early at far edges in Unity. Prevents objects popping in and out of view
Creative Commons Zero v1.0 Universal
19 stars 4 forks source link

Support Scriptable Render Pipeline (URP + HDRP)? #1

Closed mfoda-acer closed 4 years ago

mfoda-acer commented 4 years ago

Hi, Thanks for this life-saving script. It works great, but since camera rendering callbacks were removed in SRP there's no Camera.OnPreCull event in either URP or HDRP. It seems that this would instead need to be done in RenderPipeline.beginCameraRendering or RenderPipeline.beginFrameRendering as noted here. I'm not very familiar with Unity so any help would be appreciated!

koochyrat commented 4 years ago

I haven't implemented it on URP/HDRP yet. But it looks like the culling is now done in ScriptableRenderContext.Cull. If you manage to get it working share your code thanks :)

mfoda-acer commented 4 years ago

Ah, thanks for the tip! I'll give it a try and submit a PR if I get it to work :-) Cheers

mfoda-acer commented 4 years ago

@koochyrat I wasn't sure how to use ScriptableRenderContext.Cull (I think that needs implementing a custom render pass?). Anyway, I used RenderPipelineManager.beginCameraRendering and this works. If it looks good I can open a PR. Thanks again for your help!


using UnityEngine;
using UnityEngine.Rendering;
using Valve.VR;

public class SteamVRFrustumAdjustSRP : MonoBehaviour
{
    private bool isCantedFov = false;
    private float m00;
    private Camera m_Camera;

    private void OnEnable()
    {
        RenderPipelineManager.beginCameraRendering += RenderPipelineManager_beginCameraRendering;

        HmdMatrix34_t eyeToHeadL = SteamVR.instance.hmd.GetEyeToHeadTransform(EVREye.Eye_Left);
        if (eyeToHeadL.m0 < 1)
        {
            isCantedFov = true;
            float eyeYawAngle = Mathf.Acos(eyeToHeadL.m0);  //since there are no x or z rotations, this is y only. 10 deg on Pimax
            float eyeHalfFov = Mathf.Atan(SteamVR.instance.tanHalfFov.x);
            float tanCorrectedEyeHalfFov = Mathf.Tan(eyeYawAngle + eyeHalfFov);
            m00 = 1 / tanCorrectedEyeHalfFov;  //m00 = 0.1737 for Pimax
        }
        else
            isCantedFov = false;
    }

    private void RenderPipelineManager_beginCameraRendering(ScriptableRenderContext context, Camera camera)
    {
        m_Camera = camera;
        Matrix4x4 projectionMatrix = camera.projectionMatrix;
        projectionMatrix.m00 = m00;
        camera.cullingMatrix = projectionMatrix * camera.worldToCameraMatrix;
    }

    private void OnDisable()
    {
        RenderPipelineManager.beginCameraRendering -= RenderPipelineManager_beginCameraRendering;

        if (isCantedFov)
        {
            isCantedFov = false;
            m_Camera?.ResetCullingMatrix();
        }
    }
}
`
koochyrat commented 4 years ago

Ok thanks, if it is working then should be fine. I'm not too familiar with how the new rendering pipeline works. You can open a PR and I will merge it in. By the way, I've updated the original code to handle vertical culling too.

mfoda-acer commented 4 years ago

Awesome. I'll add the vertical culling code you updated and I'll submit then.