Forum Discussion

Sir_Danielo's avatar
Sir_Danielo
Honored Guest
25 days ago

OVRCameraRig per-eye camera mode appears to double effective IPD (world scale distortion)

I found what appears to be a stereo geometry bug in Unity when using OVRCameraRig in per-eye camera mode. Sharing this with the community so others can reproduce and verify.

Summary

With OVRCameraRig per-eye cameras, behavior suggests effective IOD/IPD is being applied twice:

  • Left/right eye transforms are already separated, which is expected for per-eye mode.
  • But the final rendered behavior still looks like additional eye separation is being applied elsewhere.

In practice this causes:

  • world appearing too small
  • compressed perceived distances
  • movement gain mismatch versus real-world motion

This can persist even when Camera.stereoSeparation = 0, which suggests the extra separation is not only coming from that property.

When both per-eye cameras are forced to the center-eye position, with zero horizontal separation, scale and distance perception return to normal while stereopsis remains visible.

Testing Environment

  • Unity 6000.3.2f1 LTS
  • Meta XR SDK 85.0
  • Meta Quest 3
  • Meta Horizon Link

Reproduce

Project repo:
https://github.com/Danial-Kord/meta-quest-sdk-stereo-ipd-bug

Contains:

  • minimal OVRCameraRig setup
  • two behavior-based validation scenes
  • world-space UI and controller tools
  • workaround script: CustomIPDOverride

Test A: Dual Iron-Sight Alignment (SampleScene)

Two iron sights, one per eye.

Adjust horizontal offsets until both sights perceptually align.

Measured separation at alignment:

  • Per-eye default: about 12 cm
  • Non-per-eye: about 6 cm
  • Per-eye plus override, cameras centered: about 6 cm

This suggests per-eye default behaves like about 2x effective IOD.

Test B: Monocular Head-Center Alignment (HeadCenterExperiment)

This is a second test independent from dual-sight balancing.

Procedure:

  1. Align a single iron sight while only one eye is active.
  2. Switch to the other eye only.
  3. Physically move to align the same sight again.
  4. Compare the two saved headset poses.

The difference between the two saved headset poses is used as a measure of effective IOD.

Compared modes:

  • per-eye mode: about 12 cm after test
  • per-eye plus centered-camera override: about 6 cm after test

This provides another alignment-based check of geometry consistency.

Interpretation

Results suggest per-eye mode in OVRCameraRig may be composing eye separation from more than one source, such as transform offset plus another pipeline stage, yielding doubled effective IOD in default behavior.

Possible Fix Direction

For per-eye mode, use only one baseline source:

Option A
Keep per-eye transforms centered and let the internal or native stereo path apply IPD.

Option B
Use transform offsets of plus or minus IPD/2 and ensure no additional separation is applied downstream.

But not both simultaneously.

Workaround

CustomIPDOverride, my custom camera placement override, hooks into:

  • OVRCameraRig.UpdatedAnchors
  • LateUpdate
  • Application.onBeforeRender

It forces anchors from center with a configurable proportion, including zero.

In my tests, this restores expected alignment and perceived scale.

Request for Reproduction

If anyone can reproduce this on other versions or devices, please share results.

I can also provide:

  • in-headset videos
  • runtime logs for OVRPlugin.ipd, eye anchor transforms, and camera separation values
  • stripped-down package

Links

Project repo: https://github.com/Danial-Kord/meta-quest-sdk-stereo-ipd-bug

GitHub: https://github.com/Danial-Kord/

Email: danielkordm@gmail.com

Our lab: BioMotionLab - Nikolaus Troje | York University

Thanks for reading! Let me know your comments on it.
Best,
Danial Kordmodanlou

 

1 Reply

  • Degly's avatar
    Degly
    Start Partner

    You’re likely seeing double transforms because:

    • OVRCameraRig already applies IPD via tracking (OVRPlugin)
    • Then Unity/Link pipeline applies stereo again at render level

    So your per-eye transforms + runtime stereo = apparent 2x separation

    That’s why:

    • Centering cameras “fixes” it → you remove one layer
    • stereoSeparation = 0 doesn’t help → it’s not the main source

    Recommended approach:

    • Don’t override eye transforms in per-eye mode
    • Let OVRPlugin handle IPD entirely
    • Use center-eye setup (single camera rig) unless you have a very specific need

→ Find helpful resources to begin your development journey in Getting Started

→ Get the latest information about HorizonOS development in News & Announcements.

→ Access Start program mentor videos and share knowledge, tutorials, and videos in Community Resources.

→ Get support or provide help in Questions & Discussions.

→ Show off your work in What I’m Building to get feedback and find playtesters.

→ Looking for documentation?  Developer Docs

→ Looking for account support?  Support Center

→ Looking for the previous forum?  Forum Archive

→ Looking to join the Start program? Apply here.

 

Recent Discussions