Skip to main content
Up and Coming
April 22, 2013

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.
    This topic has been closed for replies.

    5 replies

    Inspiring
    April 22, 2013
    This is AMAZING news. Very educational too. Thank you so much for sharing your findings with everyone.

    You are my hero!
    Titans of Space PLUS for Quest is now available on DrashVR.com
    Up and Coming
    April 22, 2013
    Thanks Owenwp! This is great to hear.
    Inspiring
    April 22, 2013
    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.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 16GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i Gigabyte RX Vega 64 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
    April 23, 2013
    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.
    New Participant
    April 29, 2013
    This seems to be fixed in the 0.2.1 version