[UE3] 3D Vision issues

I’m part of a community that fixes stereoscopic rendering issues in games using nVidia 3D Vision by patching shader assembly using tools called Helix Mod and 3Dmigoto (you can check out our fixes here - http://helixmod.blogspot.com/ and forums here - https://forums.geforce.com/default/board/49/3d-vision).

The most recent game I’ve fixed is Life Is Strange, which uses Unreal Engine 3 (I can’t say exactly which version or release, or if the Life Is Strange developers had altered anything) - the fix is here: Helix Mod: Life Is Strange (All Episodes)

Normally Unreal Engine is regarded to be one of the better engines as it has native support for 3D Vision which can be enabled in BaseEngine.ini, and many (but not all) of the effects are already fixed for 3D. In this case, however, I found that AllowNvidiaStereo3d=True was actually causing more harm than good as it broke many effects that looked fine without it.

This was a typical pattern I saw in pixel shaders that were broken by enabling AllowNvidiaStereo3d (stripping out irrelevant instructions):



// Registers:
//
//   Name                    Reg   Size
//   ----------------------- ----- ----
//   NvStereoEnabled         c3       1
//   NvStereoFixTexture      s1       1
//   ...

    ps_3_0
...
    dcl vPos.xy
    dcl_2d s1
...
    mad r0.xy, vPos, c0, c0.zwzw
    mul r0.xy, r0, v2.w
...
    abs r1.w, c3.x
    if_ne c3.x, -c3.x
      texld r2, c4, s1
      add r2.y, -r2.y, v2.w
      mad r0.z, r2.x, r2.y, r0.x
      mov r0.w, v2.w
      mov r2.xyz, r0.zyww
    else
      mov r2.xyz, c4.y
    endif
    mov r0.z, v2.w
    cmp r0.xyz, -r1.w, r0, r2
...


Here the vPos semantic is being used to find the screen position on the pixel (which is already correct in stereo 3D), but then nVidia’s stereo correction formula is being applied to it if NvStereoEnabled is enabled, which will now break it since vPos was already correct.

In previous games I’ve fixed I don’t think I’ve seen vPos being used - the screen position was being copied from the output position of the vertex shader, and in that case the stereo correction was required. It seems that the method used to find the screen position must have changed at some point and the 3D Vision support was not regression tested?

For this particular game I scripted a fix that disabled NvStereoEnabled on any shader that also used vPos, which did this:

I did not observe any new issues resulting from running that script, which had altered over 3000 pixel shaders (likely far less in HLSL - at the level we apply these fixes we see any variations in assembly as being a different shader).

You should also consider studying some of the other community fixes for Unreal Engine games as well and integrating them back into the engine - here’s a few links to broken effects I’ve fixed in Unreal Engine games:

The big one is shadows since it affects many games - these seem to already use a stereo correction, but it is not accurate. This is the pattern we have been using to fix these (I did not develop this pattern, I’m merely following the pattern previous fixers have found):

Here’s one that I did develop - this fixes light shafts & sky glow in many games (Life Is Strange, Eleusis, The Vanishing of Ethan Carter, Betrayer, Mind: Path to Thalamus, probably others). It works by adjusting TextureSpaceBlurOrigin in any shader that uses it by separation/2:

For glow/bloom around lights I adjusted them to infinity (simplifies to X += separation * convergence) which looked fine in Life Is Strange:

However I’m not sure if that was accurate (none of the lights were close enough to the camera to tell), and eqzitara, one of our great fixers shared a different technique:
https://forums.geforce.com/default/topic/807717/3d-vision/life-is-strange-3d-vision-surround-support/post/4443791/#4443791
Really these should be positioned such that either their output W coordinate matches the light source (and XYZ scaled appropriately), or if that is not possible a stereo correction can be applied to the X coordinate to make the output position match up.

This is the pattern I used to approximately fix reflections on the ground in Life Is Strange (not mirror reflections, which were already 100% perfect in 3D - this applies to surfaces using DNEReflectionTexture):

Here’s my fixes to the water reflection & refraction in Betrayer - this was my first non-trivial fix while learning how to fix 3D, and this solution was mostly found through experimentation. The Ocean shader looks like it might be an Unreal Engine one since it already includes a stereo correction, while the lake shader might be something custom they did for Betrayer as it doesn’t have a stereo correction. Also, keep in mind this is a slightly older game now so for all I know this may not apply anymore:
Ocean: 3d-fixes/8D1914C3.txt at master · DarkStarSword/3d-fixes · GitHub
Lake refraction: Betrayer: Fix lake water refraction · DarkStarSword/3d-fixes@1a32780 · GitHub
Lake reflection: Betrayer: Fix reflections on lake · DarkStarSword/3d-fixes@efd7bc6 · GitHub

Finally, decals in Life is Strange and point lights in Eleusis were being incorrectly clipped in stereo 3D, which is easily fixed by disabling the call to SetScissorRect() - nVidia recommends this call be disabled whenever 3D is used as the rectangle it defines is inherently 2D.