In order to doing some researches, I aim to increase the fov for the HMDs.
The result what I want to achieve is like the result in this paper.
https://dl.acm.org/doi/abs/10.1145/2628257.2628273
Here is my current environment
Unity editor 2021.3.3f1
SteamVR plugin
HMD: HTC Vive Pro, Oculus Rift
Why I’ve done is, I get defined view frustum value from the hmd by using GetProjectionRaw(),
which return the left, right, top, bottom values for each eyes’ view frustum.
Then, I multiply a gain value to them and construct new projection matrices, then submit them through SetStereoProjectionMatrix().
BTW, I am using the built-in render pipeline.
Here are my main component that attach to the camera.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using Valve.VR;
public class FieldOfViewModify : MonoBehaviour
{
public CVRSystem system;
private void Awake()
{
//Get cvrsystem component
var error = EVRInitError.None;
system = OpenVR.Init(ref error, EVRApplicationType.VRApplication_Scene);
if (error != EVRInitError.None)
Debug.Log("Init Error");
}
private void OnEnable()
{
RenderPipelineManager.beginFrameRendering += ScenePreCull;
}
private void OnDisable()
{
RenderPipelineManager.beginFrameRendering -= ScenePreCull;
GetComponent<Camera>().ResetStereoProjectionMatrices();
}
private void ScenePreCull(ScriptableRenderContext context, Camera[] cam)
{
OnPreCull();
}
Camera cam;
//the matrices which is going to be customized
Matrix4x4 matR, matL;
float ll, rl, bl, tl;
float lr, rr, br, tr;
float n, f;
public float gain;
public float fov_ver, fov_hor;
float v, h;
public float imageScale;
// Start is called before the first frame update
void Start()
{
cam = GetComponent<Camera>();
n = cam.nearClipPlane;
f = cam.farClipPlane;
system.GetProjectionRaw(EVREye.Eye_Left, ref ll, ref rl, ref bl, ref tl);
system.GetProjectionRaw(EVREye.Eye_Right, ref lr, ref rr, ref br, ref tr);
gain = 1f;
fov_hor = Mathf.Atan(rr) * Mathf.Rad2Deg - Mathf.Atan(ll) * Mathf.Rad2Deg;
fov_ver = Mathf.Atan(tl) * Mathf.Rad2Deg - Mathf.Atan(bl) * Mathf.Rad2Deg;
h = fov_hor;
v = fov_ver;
matR = cam.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right);
matL = cam.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
gain += 0.1f;
if (Input.GetKeyDown(KeyCode.DownArrow))
gain -= 0.1f;
}
private void OnPreCull()
{
cam.ResetStereoProjectionMatrices();
newProjection(gain);
cam.SetStereoProjectionMatrix(Camera.StereoscopicEye.Right, matR);
cam.SetStereoProjectionMatrix(Camera.StereoscopicEye.Left, matL);
}
void newProjection(float gain)
{
float lR = Mathf.Tan(Mathf.Atan(lr) * gain);
float rR = Mathf.Tan(Mathf.Atan(rr) * gain);
float bR = Mathf.Tan(Mathf.Atan(br) * gain);
float tR = Mathf.Tan(Mathf.Atan(tr) * gain);
matR = Matrix4x4.Frustum(lR * n, rR * n, bR * n, tR * n, n, f);
float lL = Mathf.Tan(Mathf.Atan(ll) * gain);
float rL = Mathf.Tan(Mathf.Atan(rl) * gain);
float bL = Mathf.Tan(Mathf.Atan(bl) * gain);
float tL = Mathf.Tan(Mathf.Atan(tl) * gain);
matL = Matrix4x4.Frustum(lL * n, rL * n, bL * n, tL * n, n, f);
fov_hor = Mathf.Atan(rR) * Mathf.Rad2Deg - Mathf.Atan(lL) * Mathf.Rad2Deg;
fov_ver = Mathf.Atan(tL) * Mathf.Rad2Deg - Mathf.Atan(bL) * Mathf.Rad2Deg;
imageScale = rr / rR;
//imageScale = Mathf.Tan(v/2 * Mathf.Deg2Rad) / Mathf.Tan(fov_ver/2 * Mathf.Deg2Rad);
}
}
And here’s the outcome.
The origin vision:
Gain = 1.2
Gain = 1.3
So when the gain increase(fov increase), the object in the peripheral area of the lens are lengthened toward to the edge, and some of the shadows are gone?
So do anyone knows how to solve this issue?