VRto3D renders one canonical 2W x H side-by-side frame internally and the active Output Mode repacks it for your display. Pick the matching output_mode either in default_config.json or from the OSD System tab (Ctrl + Home). Most modes only need the Regular Installation; the few that need extra software or display setup are called out below.
Find your display type and use the listed Output Mode(s):
SbS, TaB, or one of the FramePacked* modesSbS or TaB based on what your TV / projector accepts as a stereo inputFramePacked* modes target HDMI 1.4 frame-packed 3D - VRto3D will attempt to engage the custom resolution, but it still relies on your display accepting it and allowing you to engage 3D:
FramePacked720p60 - 1280x1470 @60Hz, 30px gapFramePacked1080p24 - 1920x2205 @24Hz, 45px gap (most universal)FramePacked1080p60 - 1920x2205 @60Hz, 45px gap, 371.25 MHz pixel clock (HDMI 2.0+)FramePacked1080p60CVT - 1920x2205 @60Hz with CVT reduced blanking, 45px gap, 280.8 MHz pixel clock (HDMI 2.0)SbS, TaB, and the FramePacked* modes all work. Frame-packed timing is applied differently than on Windows:
ModeValidation overrides in xorg.conf)tools/make_fp_edid.py and load it via drm.edid_firmware=<connector>:edid/<file>.bin on the kernel cmdlineRowInterlaced, ColInterlaced, or CheckerboardRowInterlaced covers the vast majority of passive 3D TVs and monitorsColInterlaced is for column-interlaced passive panelsCheckerboard is for DLP-link 3D projectors and the older Mitsubishi / Samsung DLP 3D TVs ((x+y)%2 eye selection)SbS (switch the glasses to Full-SbS mode first)Game Mode, place the glasses on a flat surface looking straight ahead, and click Start Calibrate. Calibration may need to be redone if misalignment occursOpenTrack Configuration and disable Enable Roll if neededStart the OpenTrack VertoXR pluginCtrl + Home) and on the Tracking tab tick Enable OpenTrack under OpenTrack, then set UDP Port to match VertoXR’s OpenTrack port (restart SteamVR after a port change)System tab, set Launch Script to start vertoxr://steamvr so VertoXR auto-starts with OpenTrack active every time you start SteamVRSave Default Cfg in the OSD footer to persist the changesRecenter button in VertoXR as neededSbS output is supported; the optional VertoXR head-tracking app is Windows-only, so use another OpenTrack source for head tracking on LinuxSbSLeiaSR (SR Display Weaver)Fix LeiaSR library loading (requires restart) option in the VRto3D installer
Win + R, Paste this command: cmd /k setx PATH "C:\Program Files\LeiaSR\Platform\bin;%PATH%" Exit the terminal and rebootTracking tab. Tune the LeiaSR head-tracking and track filter sliders on the same tabWibbleWobble (preferred) or NvidiaDX9 (legacy / unstable)WibbleWobble requires the WibbleWobbleClient - select Install WibbleWobble for Frame Sequential 3D in the VRto3D Installer. Follow the WibbleWobble SteamVR Setup Instructions (skip the VR Config step, but do the rest). When framerate is low, you will have eye flickeringNvidiaDX9 requires the 3DVision driver installed and 3D Enabled. May freeze or crash, requiring a hard reset. Should be more stable on single-display setups. If it crashes, just try againSwap Eyes to be set depending on how your display initializesNvidiaDX9 has no Linux driver stack, and WibbleWobble is a Windows-only client (a port may come later)VirtualDesktopVirtualDesktop output mode worksDualDisplay or DualDisplayFlipDualDisplay puts the left eye on the display_index and the right eye on the display to the right of itDualDisplayFlip is the same as DualDisplay but the left eye is flipped vertically - useful for mirror-based dual-monitor 3D rigsAnaglyph* modes - works on any 2D displayAnaglyphRedCyan (simple R | GB split), AnaglyphRedCyanDubois (Dubois - best general-purpose), AnaglyphRedCyanDeghosted, AnaglyphRedCyanCompromiseAnaglyphGreenMagenta (simple G | RB split), AnaglyphGreenMagentaDubois, AnaglyphGreenMagentaDeghostedAnaglyphBlueAmberMonoeye_swap to render the right eye instead of the leftCheckout the Compatibility List to see if a game has been tested
Most adjustments now happen in the On-Screen Menu — open it with Ctrl + Home (or Start + D-Pad Down on a connected XInput controller). The remaining global hotkeys are intentionally minimal:
Ctrl + Home or the Start + D-Pad Down gamepad chord
A to activate, B to cancel the current widget, LB/RB to page through tabs, right stick to scroll)X (Xbox) / Square (PS) to jump nav up to the title bar (where the X close button lives — press A to dismiss); hold the same button to enter ImGui’s windowing mode (left stick moves the window, D-pad resizes it, LB/RB cycle windows)Ctrl + F3 and Ctrl + F4 - re-syncs the projection so the change is visible immediately (some VR mods otherwise need a reload to pick it up)
Shift to skip the projection re-sync (bare depth nudge)Ctrl + F5 and Ctrl + F6 - this often has issues in VR mods"+" under Configuration) to the running game’s Game.exe_config.json with Ctrl + F7 - a beep indicates successGame.exe_config.json with Ctrl + F10, or reload default_config.json with Ctrl + Shift + F10 - a beep indicates successCtrl + F11Ctrl + F8Ctrl + F12Ctrl + Home) can be disabled with disable_hotkeys if they conflict with another 3D mod - the OSD menu remains accessibleUser-defined preset hotkeys (configured under User Presets) work alongside the built-in keys above.
VRto3D-Installer.exe from the latest release and run it. The installer auto-detects your Steam library, installs/updates the VRto3D driver, and offers optional cleanup of legacy ReShade and third-party SteamVR drivers. It can also install WibbleWobble and launch SteamVR for you.
vrto3d folder from inside the VRto3D.zip to your Steam\steamapps\common\SteamVR\drivers folderdefault_config.json and you should see a 1080p SbS VRto3D window upscaled to fullscreenCtrl + Home and use the System tab to pick Display Index, Output Mode, and render resolution for your display - see the Output Modes table for which mode to choose
Steam\config\vrto3d\default_config.json manually - see what each setting doesSteam\config\vrto3d\ folder (or click Download Latest Profiles on the OSD’s System tab)display_index displayLock Cursor to Game (lock_cursor) in the OSD’s System tab to confine the mouse to the game window, and Hide Cursor (hide_cursor) to fully hide the OS cursor while the game is focusedStereo Cursor (stereo_cursor) to replace the flat OS cursor with a per-eye 3D cursor drawn at an adjustable depth — recommended for SbS/TaB displays where the OS cursor only lines up with one eyeAlt + Enter This will alleviate controller input and fullscreen issues. (Borderless fullscreen/windowed sometimes also work)Ctrl + F8 to lock the 3D window to the foreground and focus the game window
auto_focus settingAlt + Tab to switch to the game windowAlt + Tab out
Ctrl + F8 to toggle the foregrounding off, and then Alt + Tab outNative Linux SteamVR driver — same direct-mode architecture as Windows, no virtual display or capture chain. The SteamVR compositor renders games into driver-allocated Vulkan images (shared via dmabuf), VRto3D repacks them into your chosen 3D format and presents fullscreen on the selected display. Configuration, profiles, the OSD, and hotkeys all work the same as on Windows; everything below is Linux-specific.
input group:
sudo usermod -aG input $USER # then log out/in
vrto3d-linux64.tar.gz from the latest release, extract it, and run the installer:
tar xzf vrto3d-linux64.tar.gz
cd vrto3d-linux64
./install.sh
The script finds your Steam installation (pass --steam <path> if it’s somewhere unusual), copies the driver into SteamVR/drivers/, registers it in steamvr.vrsettings, and warns if your user is missing the input group. Run ./install.sh --uninstall to remove it again.
drivers/vrto3d folder from the tarball into <steam>/steamapps/common/SteamVR/drivers/, then in ~/.local/share/Steam/config/steamvr.vrsettings set:
"steamvr": { "requireHmd": true, "forcedDriver": "vrto3d", "activateMultipleDrivers": true }
Config lives in <steam>/config/vrto3d/default_config.json, same schema as Windows. Keybind names use the portable vocabulary (Key_A, Numpad7, Pad_A, Pad_Start+Pad_DPadDown); legacy VK_*/XINPUT_* names still load and are rewritten on the next profile save.
display_index picks the output (0 = primary, 1..N = connected order). The presenter is chosen by session: Wayland (layer-shell overlay surface — always on top on KDE/Hyprland/Sway, plain fullscreen on GNOME) or X11 (borderless _NET_WM_STATE_ABOVE window). Override with env VRTO3D_PRESENTER=x11|wayland (e.g. force X11/XWayland when you need runtime frame-packed modelines).
Per-output-mode Linux compatibility (including the LeiaSR / 3D Vision / WibbleWobble modes that are compiled out, and the runtime vs. EDID handling for frame-packed HDMI) is noted inline in the Output Modes table.
hide_cursor/lock_cursor/stereo_cursor) and focus stealing — no cross-client mechanism on Wayland; X11 cursor grab may come laterdefault_config.json to be createdCtrl + Home); changes take effect immediately and the footer’s Save Default Cfg / Save Game Cfg buttons persist themSteam\config\vrto3d\default_config.json - some changes require a SteamVR restart (display index, output mode, render size, OpenTrack port)"+" next to them are saved to a game’s profile when you press Ctrl + F7 (or use the OSD Save Game Cfg footer button), and can be reloaded from the game’s profile (Ctrl + F10) or default_config.json (Ctrl + Shift + F10)| Field Name | Type | Description | Default Value |
|---|---|---|---|
display_index |
int |
3D display selection by display order (0 = auto primary, 1 = first display, 2 = second, etc.) |
0 |
output_mode |
string |
Stereo output format. See the Output Modes table for valid values | "SbS" |
eye_swap |
bool |
Swap left and right eyes | false |
render_width |
int |
The width to render per eye | 1920 |
render_height |
int |
The height to render per eye | 1080 |
display_frequency |
float |
Per-eye refresh rate in Hz. 0.0 auto-detects from the target monitor at activation |
0.0 |
hmd_height + |
float |
The height/Z position origin of the simulated HMD | 1.0 |
hmd_x |
float |
The X position origin of the simulated HMD | 0.0 |
hmd_y |
float |
The y position origin of the simulated HMD | 0.0 |
hmd_yaw |
float |
The yaw attitude of the simulated HMD | 0.0 |
aspect_ratio |
float |
The aspect ratio used to calculate vertical FoV | 1.77778 |
fov + |
float |
The horizontal field of view (FoV) for the VR rendering | 90.0 |
depth + |
float |
The max separation. Overrides VR’s IPD field | 0.1 |
convergence + |
float |
Where the left and right images converge. Adjusts frustum | 1.0 |
async_enable + |
bool |
Whether or not to use Asynchronous Reprojection. May improve or worsen smoothness | false |
auto_depth_enabled + |
bool |
Enable Auto-Depth (GPU disparity analysis caps depth so the closest object stays comfortable) | false |
auto_depth_target_disparity + |
float |
Target max on-screen disparity, as a fraction of one eye’s width | 0.005 |
auto_depth_smoothing + |
float |
Auto-Depth smoothing (higher = snappier; lower = smoother) | 0.08 |
shader_enabled + |
bool |
Enable the display-correction shader pass (Lift/Gamma/Gain + S-Curve) - see Display Correction | false |
shader_lift + |
[float] |
RGB Lift (shadows), 3-element array, each 0..2 |
[1.0, 1.0, 1.0] |
shader_gamma + |
[float] |
RGB Gamma (midtones), 3-element array, each 0..2 |
[1.0, 1.0, 1.0] |
shader_gain + |
[float] |
RGB Gain (highlights), 3-element array, each 0..2 |
[1.0, 1.0, 1.0] |
shader_curve + |
float |
Extended S-Curve strength (0.33..3.0; 1.0 = pass-through; <1 reduces midtone contrast) |
1.0 |
shader_curve_offset_low + |
float |
S-Curve low-color offset (-1..1) |
0.0 |
shader_curve_offset_high + |
float |
S-Curve high-color offset (-1..1) |
0.0 |
shader_curve_offset_both + |
float |
S-Curve both-color blend-point offset (-1..1) |
0.0 |
disable_hotkeys |
bool |
Disable the global hotkeys (Depth/Convergence/profile/save) to avoid conflict with other 3D mods. Ctrl + Home and Start + D-Pad Down (OSD toggles) are unaffected |
false |
dash_enable |
bool |
Enable or disable SteamVR Dashboard and Home | false |
auto_focus |
bool |
Enable or disable automatic focusing/bringing VRto3D to foreground | true |
hide_cursor + |
bool |
Fully hide the OS cursor while the game is focused (blanks the system cursor set; restored on focus loss) | false |
lock_cursor + |
bool |
Confine the OS cursor to the focused game window’s client area (re-asserted continuously) | false |
stereo_cursor + |
bool |
Hide the OS cursor and draw a per-eye 3D cursor in both eye views instead (also used for the OSD menu) | false |
cursor_depth + |
float |
Stereo cursor per-eye shift in pixels: 0 = screen plane, positive = into the screen, negative = pop-out |
0.0 |
cursor_size + |
int |
Stereo cursor arrow height in per-eye pixels | 32 |
pitch_enable + |
bool |
Enables or disables Controller right stick y-axis mapped to HMD Pitch | false |
yaw_enable + |
bool |
Enables or disables Controller right stick x-axis mapped to HMD Yaw | false |
use_open_track |
bool |
Enables or disables OpenTrack 6DoF HMD Control | false |
open_track_port |
int |
UDP Port for OpenTrack | 4242 |
use_track_filter |
bool |
Enables or disables Accela-Hamilton style pose filtering for tracking rotation and position | false |
trk_flt_rot_sens |
float |
Rotation smoothing threshold for track filter (lower = more smoothing) | 0.5 |
trk_flt_pos_sens |
float |
Position smoothing threshold for track filter (lower = more smoothing) | 0.25 |
trk_flt_rot_dz |
float |
Rotation deadzone used by track filter | 0.03 |
trk_flt_pos_dz |
float |
Position deadzone used by track filter | 0.02 |
trk_flt_zoom_smooth |
float |
Additional rotation smoothing when moving toward the display | 0.0 |
trk_flt_max_zoom |
float |
Max Z distance used for scaling zoom smoothing | 10.0 |
sr_tracking_enabled |
bool |
Enable the LeiaSR built-in head-tracking sender. Disable to feed OpenTrack from another source (e.g. the OpenTrack app) while in LeiaSR mode | true |
sr_filter_pos_mincutoff |
float |
LeiaSR built-in head tracking: One-Euro position min cutoff | 0.08 |
sr_filter_pos_beta |
float |
LeiaSR built-in head tracking: One-Euro position beta | 0.08 |
sr_filter_rot_mincutoff |
float |
LeiaSR built-in head tracking: One-Euro rotation min cutoff | 0.12 |
sr_filter_rot_beta |
float |
LeiaSR built-in head tracking: One-Euro rotation beta | 0.01 |
sr_angle_deadzone_deg |
float |
LeiaSR built-in head tracking: angular deadzone in degrees | 0.2 |
sr_sens_yaw |
float |
LeiaSR built-in head tracking: yaw sensitivity | 1.0 |
sr_sens_pitch |
float |
LeiaSR built-in head tracking: pitch sensitivity | 1.0 |
sr_sens_roll |
float |
LeiaSR built-in head tracking: roll sensitivity | 1.0 |
sr_max_yaw |
float |
LeiaSR built-in head tracking: max yaw clamp (deg) | 70.0 |
sr_max_pitch |
float |
LeiaSR built-in head tracking: max pitch clamp (deg) | 70.0 |
sr_max_roll |
float |
LeiaSR built-in head tracking: max roll clamp (deg) | 70.0 |
sr_track_mode |
string |
LeiaSR built-in head tracking mode ("XYZ_YawPitch", "XYZ", "YawPitch", "Full6DOF", "YawPitchRoll") |
"XYZ_YawPitch" |
launch_script |
string |
Command executed once when VRto3D driver activates (e.g. "start vertoxr://steamvr") |
"" |
pose_reset_key + |
string |
The Virtual-Key Code to reset the HMD position and orientation | "VK_NUMPAD7" |
ctrl_toggle_key + |
string |
The Virtual-Key Code to toggle Pitch and Yaw emulation on/off when they are enabled | "VK_NUMPAD8" |
ctrl_toggle_type + |
string |
The ctrl_toggle_key’s behavior ("toggle", "hold") |
"toggle" |
pitch_radius + |
float |
Radius of curvature for the HMD to pitch along. Useful in 3rd person VR games | 0.0 |
ctrl_deadzone + |
float |
Controller Deadzone when using pitch or yaw emulation | 0.05 |
ctrl_sensitivity + |
float |
Controller Sensitivity when using pitch or yaw emulation | 1.0 |
user_settings[].user_load_key + |
string |
The Virtual-Key Code (or XInput chord) to load a user preset | "VK_NUMPAD1" |
user_settings[].user_key_type + |
string |
The load key’s behavior. Only "toggle" supports multi-preset cycles; "switch" and "hold" keep just the first value |
"switch" |
user_settings[].user_depth + |
float or [float] |
The separation value(s) for a user preset (array = cycle on each press, toggle mode only) |
0.1 |
user_settings[].user_convergence + |
float or [float] |
The convergence value(s) for a user preset (array = cycle on each press, toggle mode only) |
1.0 |
user_settings[].user_fov + |
float or [float] |
The fov value(s) for a user preset; 0 falls back to the global FoV (array = cycle on each press, toggle mode only) |
90.0 |
Alt + Tab to the gameShader tab runs a configurable post-process pass on the final stereo image that trades some brightness/contrast for sharply less visible crosstalk - toggle it on/off instantly when neededShader tab:
Enable Display Correction Shader - master on/off (defaults off, no perf cost when off)0..2, default 1.0): RGB Lift raises/lowers shadows, RGB Gamma adjusts midtone gamma, RGB Gain scales highlightsCurve (range 0.33..3.0, default 1.0 = pass-through); below 1.0 reduces midtone contrast (the crosstalk-fix direction), above 1.0 increases it. Curve Offset (Low / High / Both) fine-tune the curve’s low-end, high-end, and overall blend point (-1..1, default 0)Reset to Defaults - snap everything back to pass-throughExample starting point for a LeiaSR 3D monitor with heavy crosstalk (Acer/Samsung 27”):
| Control | Value |
|---|---|
Enable Display Correction Shader |
on |
RGB Gamma |
0.6, 0.6, 0.6 |
Curve |
0.33 |
Curve Offset (Both) |
-1.0 |
Curve upward toward 1.0 until you find the smallest correction that hides the crosstalk in your worst-case scene - every step toward 1.0 recovers contrastSave Game Cfg (per-game) or Save Default Cfg (global) in the OSD footer to persist the settingsEnable Steam Input for Xbox ControllersEdit on the Desktop Layout and then select Disable Steam InputController Icon and select Disable Steam InputTracking tab (Ctrl + Home -> XInput (Xbox) Controller)
Pitch (right stick) and / or Yaw (right stick) to map themSensitivity, Stick Deadzone, and Pitch Radius (curves the view along a semicircle - useful in 3rd-person games) all live in the same panelToggle Key (default VK_NUMPAD8) toggles pitch/yaw on/off in-game; the Mode combo next to it switches between toggle and hold behavior. Reset Key (default VK_NUMPAD7) recenters. Both bindings accept any keyboard/mouse key or XInput button/chord - click Set to capture a single key/button or Combo to capture an XInput chord, or type a string from key_names.h directlyEnable OpenTrack on the OSD Tracking tab (OpenTrack panel) and set the UDP port to match your sender (default 4242; port changes need a SteamVR restart)
output_mode: "LeiaSR" and tune the One-Euro filter / sensitivities / clamps in the OSD Tracking tab’s LeiaSR Head Tracking panelLaunch Script field on the OSD System tab to start vertoxr://steamvr to auto-start it with SteamVRuse_track_filter
Tracking tabCtrl + Home (or Start + D-Pad Down on a gamepad) to open the OSD menu and select the User Hotkeys tab(Depth, Convergence, FoV) preset. Only toggle mode supports multi-preset cycles - switch and hold rows are trimmed to the first value on edit and on profile load
Set to capture a single key, mouse button, or XInput buttonCombo to capture an XInput chord (e.g. XINPUT_GAMEPAD_LEFT_SHOULDER+XINPUT_GAMEPAD_RIGHT_SHOULDER); the chord commits when you release everythingMode:
switch - jump to the preset and stay theretoggle - bounce between the preset and the previous setting every 1.5shold - apply the preset only while the key is heldDepth, Conv, and FoV directly, or click Copy Current to fill them from the current Stereo tab values
toggle mode only; switch and hold keep only the first value)FoV = 0 falls back to the active profile’s global FoV+ Add Preset Row adds a new empty row; the X button removes a rowswitch preset that matches your default depth/convergence so you can easily get back to baselineSave Game Cfg or Save Default Cfg in the footerProfile: (default) if no per-game profile exists yetCtrl + Home (or Start + D-Pad Down on a gamepad) to open the OSD menuDepth, Convergence, FoV, and toggle Swap Eyes / Auto-Depth as neededCopy Current to capture the current values into a rowHeight under HMD Pose, and enable Pitch (right stick) / Yaw (right stick) under XInput (Xbox) Controller for games that need camera controlAsync Reprojection under Misc if it helps smoothness for this gameSave Game Cfg to write Steam\config\vrto3d\Game.exe_config.json (the button label includes the game name and is disabled until VRto3D detects a running game). Save Default Cfg writes the equivalent values to default_config.json for use as a global baselineCtrl + F7 (or the footer button) at any timeSteam\config\vrto3d\Game.exe_config.json with othersdisplay_index to the correct display enumeration order (or pick it from the OSD System tab) and restart SteamVRSteam\config\steamvr.vrsettings and Steam\config\vrto3d\default_config.jsonMenu -> SettingsStartup / Shutdown tabManage Add-OnsOff any virtual HMD drivers (ALVR, VRidge, OpenTrack, VCR, iVRy, etc)Steam\steamapps\common\SteamVR folderManage Add-Ons menu or delete the vrto3d folder from your Steam\steamapps\common\SteamVR\drivers foldervrto3d.txt log: <steam>/logs/vrto3d.txt (plus stderr in vrserver.txt)groups includes input; the OSD shows a warning toastWAYLAND_DISPLAY/DISPLAY reach vrserver (launch SteamVR from a desktop session, not a raw console)<steam>/steamapps/common/SteamVR/screenshotsSTEAM_PATH environment variable with the path to your main Steam folderSteamVR\drivers foldercd vrto3d
cmake -B build -G Ninja
cmake --build build
Dependencies: gcc/clang C++17, cmake, Vulkan headers, libX11 + libXrandr, wayland-client, libxkbcommon, libdrm headers. (Shaders ship pre-compiled as SPIR-V headers; regenerate with shaders/compile_shaders.sh if you edit them — needs glslc.)
For quick iteration, register the build output in place instead of copying it:
~/.local/share/Steam/steamapps/common/SteamVR/bin/vrpathreg.sh adddriver \
<checkout>/vrto3d/build/output/drivers/vrto3d