Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
owenwp's avatar
owenwp
Expert Protege
12 years ago

Simple Deferred Lighting Fix

Now that I have my dev kit, I was able to do some real testing on the deferred lighting issue. As I mentioned in other threads, the problem is that constructing your own perspective matrix can prevent Unity from doing transforms back from screen space to world space. The reason this is an issue here is that the Oculus SDK uses Direct3D clip space conventions in its matrix construction, while Unity expects OpenGL conventions.

The fix is easy, just use Unity's built in perspective matrix. Find this method at the bottom of OVRCamera.cs:


public void SetPerspectiveOffset(ref Vector3 offset)
{
// NOTE: Unity skyboxes do not currently use the projection matrix, so
// if one wants to use a skybox with the Rift it must be implemented
// manually
gameObject.camera.ResetProjectionMatrix();
Matrix4x4 m = Matrix4x4.identity;// = gameObject.camera.projectionMatrix;
CreatePerspectiveMatrix(ref m);
Matrix4x4 tm = Matrix4x4.identity;
tm.SetColumn (3, new Vector4 (offset.x, offset.y, 0.0f, 1));
gameObject.camera.projectionMatrix = tm * m;
}


And replace it with this:


public void SetPerspectiveOffset(ref Vector3 offset)
{
// NOTE: Unity skyboxes do not currently use the projection matrix, so
// if one wants to use a skybox with the Rift it must be implemented
// manually
gameObject.camera.ResetProjectionMatrix();
Matrix4x4 tm = Matrix4x4.identity;
tm.SetColumn (3, new Vector4 (offset.x, offset.y, 0.0f, 1));
gameObject.camera.projectionMatrix = tm * gameObject.camera.projectionMatrix;
}


I have confirmed through testing (switching between those two functions quickly) that the projection is exactly the same visually. The absolute difference between the values in the matrices is also infinitesimal, except for the term where Direct3D and OpenGL differ:
m.m23 = (farClip * nearClip) / (nearClip - farClip);

The only thing this term affects is the Z position of vertices in clip space, so it has zero effect on the pixel position of a vertex, and therefore only influences the near and far clip plane distances.

Deferred lighting is also fixed if you simply change that line like so to match the OpenGL standard:

m.m23 = 2*(farClip * nearClip) / (nearClip - farClip);

But its still better to use Unity's projection, because there is the possibility that it might change on other platforms, and Unity may expect it to be a certain way. Other subtle bugs may be present in the current implementation, at least the near plane probably does not accurately reflect what you set in Unity.

5 Replies

Replies have been turned off for this discussion
  • drash's avatar
    drash
    Heroic Explorer
    This is AMAZING news. Very educational too. Thank you so much for sharing your findings with everyone.

    You are my hero!
  • Awesome fix, owenwp! I just tested it and it appears to work.

    We will do some more testing here at the office, but most likely we will roll this into the next release.

    Thanks a bunch.
  • Anonymous's avatar
    Anonymous
    This is HUGE news! Using Deferred lighting is so great, I was really worried that it wouldn't happen.
    Thank you VERY MUCH, can't stress how important this is for me.