๏ปฟ# RaceVisor โ Controls Reference
RaceVisor is written in C# on WPF (.NET 10) and leverages DirectX (Direct3D 11 / Direct2D / DirectWrite) and the Windows platform directly โ shared-memory telemetry, DirectInput wheels, Media Foundation capture, Windows audio โ so it renders natively at up to 120 Hz and stays a single small signed exe.
Always-available rescue keys (baked in, cannot be rebound or broken)#
These two fire globally โ clickthrough on, window unfocused, sim running, doesn't matter:
| Chord | Action |
|---|---|
| Ctrl+Alt+Shift+` (backtick) | EMERGENCY RESTORE โ loads default layout, opacity 100%, window snapped on-screen, lands in interactive mode. For "the overlay is invisible/unreachable/borked." |
| Ctrl+Alt+Shift+1 | OPACITY RESCUE โ every widget, every background, and the overlay backdrop back to 100%. Undoes any amount of ghosting in one press (Ctrl+Z reverses it). |
Controllers#
Full DirectInput controller support โ map any overlay action to your wheel (e.g., Logitech G29), gamepad, or button box.
- Open the Hotkey Editor (Keys button on the toolbar) โ "Controller" column
- Click "press button" and tap a button on your physical wheel to bind it
- Load G29 Preset for instant defaults on Logitech wheels
- Wheel buttons work even when EasyAntiCheat has focus โ they can't be blocked
Keyboard#
F12 is the only rebindable global key. Everything else fires only while the overlay is in interactive mode and focused โ so Esc inside iRacing never quits RaceVisor.
| Key (default) | Action |
|---|---|
| F12 | Toggle clickthrough โ interactive (blue "๐ INTERACTIVE MODE" badge while interactive) |
| Esc | Close things in order: open menu/panel first, then help, then any child window โ and only with nothing left to close, press Esc twice within 2 s to quit (interactive + focused only) |
| Ctrl+1โฆ4 | Load preset 1โ4 |
| None (rebindable) | Previous preset |
| Ctrl+` | Open the Layout Designer |
| Ctrl+N | Save current layout |
| Ctrl+S | Load saved layout |
| Ctrl+Z | Undo layout change (moves, resizes, menu/panel edits, wheel fades, loads, resets, opacity rescue). Needs the overlay focused in interactive mode - in VR use the right-click menu's Undo last change instead |
| Ctrl+0 | Reset to defaults (undoable) |
| Ctrl+Q | Open the Hotkey Editor |
| Ctrl+R | Start/stop telemetry recording (data, not video!) โ red "โ TELEMETRY REC" badge |
| Ctrl+O | Open/stop a telemetry replay (loops) โ a RaceVisor .jsonl.gz recording or an iRacing .ibt file (see Replaying iRacing's own telemetry below) |
| None (rebindable) | iRacing .ibt disk telemetry on / off โ the same thing as Alt+L in the car, from a wheel button (global; iRacing only) |
| Num 0 (hold) | Driver Chat push-to-talk - your mic is sent exactly while it is held (global; bind a wheel button here) |
| Ctrl+M | Driver Chat: open mic on / off (talk without holding anything) (global) |
| Ctrl+T | Driver Chat: open the text box - type, Enter sends, Esc cancels; drops you back into clickthrough afterwards (global) |
| None (rebindable) | Driver Chat: mute on / off (hear nobody, still able to send) (global) |
| None (rebindable) | Stopwatch: start / stop, Stopwatch: lap, Stopwatch: reset - three separate bindings, all (global), meant for wheel buttons |
Bindings live in
Documents\iRacing\irDash_hotkeys.jsonโ everything above is rebindable in the Hotkey Editor, which warns about duplicates and risky keys.
The toolbar (docks onto the Control Bar widget)#
Visible in interactive mode. It sits on the Control Bar widget โ move/resize that widget and the toolbar follows. No Control Bar in the layout? It floats top-left.
โ [preset] โถ cycle presets ยท Save asโฆ ยท โ slider overlay backdrop opacity ยท Design inline designer ยท โฌ Group group-select mode ยท Fit shrink-wrap (monitor users only) ยท VR size biggest window = sharpest kneeboard (see "Fit costs sharpness in VR" below) ยท Designer full designer window ยท Keys hotkey editor ยท ๐ Find (below) ยท ๐ Lock back to racing
Fit costs sharpness in VR - keep the window big#
The kneeboard is a picture of the RaceVisor window: OpenKneeboard captures the window at its pixel size and stretches that onto the panel in the headset. So the window's size on the monitor is the kneeboard's resolution. Fit shrinks the window to hug the widgets - handy on a monitor, but in VR it throws pixels away, and with a busy layout (15-20 widgets) each widget is then drawn a few dozen pixels wide, so text goes soft and smears when you turn your head. Found 2026-09-15: an 18-widget layout in a 1300ร760 window looked fuzzy; the same layout in a 1920ร1080 window was crisp.
Rule for VR: press VR size on the toolbar (or type vr size in Find) - it makes the window the largest 16:9 that fits your main monitor and the size is remembered across restarts - and never press Fit before a VR session. More widgets = more pixels needed, not fewer. Two SteamVR settings help too, under Video: Advanced Supersample Filtering: Off (it softens flat overlays) and Overlay Render Quality: High.
๐ Find - one box for "how do Iโฆ" and "do it"#
Type a few letters into the Find box on the toolbar and a list drops down, best match first:
- Help - sections of this manual; Enter opens the Help panel on that section.
- Do - commands: open the designer or hotkey editor, save / load presets, undo, start recording, open a replay, recenter the kneeboard, stopwatch, media keys, FloDee, settingsโฆ
- Add widget - every widget in the palette; Enter drops it on the layout.
- Load preset - your saved layouts.
It uses the same forgiving heuristic as the Help panel's search: headings count most, an exact phrase beats scattered words, and letters-in-order still scores, so kneebord finds the kneeboard and stopwtch the stopwatch. Enter runs the top hit, โ โ pick another, Esc clears. In VR the drawn cursor clicks results like anything else; typing needs a keyboard.
Hover tooltips - every widget, every control#
Hover anything in interactive mode and a tooltip says what it is and what a click does: each widget (one line on what it shows and how to handle it, plus its live CPU cost), and every control inside a widget - pit-service tiles, media buttons, the sim replay transport, timing tower rows, audio rows and bars, stopwatch and Now Playing buttons, the notes keyboard, FloDee actions, Icon Bar icons and launchers. WPF-hosted widgets (OBS, Driver Chat, Kneeboard position) carry their own tooltips on every button.
Turning them off: Media widget โ SET โ Hover tooltips. One switch for all of them; the Find box and the in-app Help still work with tooltips off. They are interactive-mode only: the moment you go clickthrough (F12) tooltips stop, and any tip left open closes, and the same goes for the drawn cursor - in clickthrough the pointer belongs to the sim and the overlay draws nothing at it.
Mouse โ in the overlay (interactive mode; F12 first)#
| Gesture | Action |
|---|---|
| Drag a widget's body | Move it |
| Drag a widget's edge/corner | Resize it (opposite edge anchored) |
| Drag the window's outer edge (~10 px) | Resize the whole overlay |
| Drag empty space | Move the whole overlay window |
| Ctrl+wheel | Zoom the entire overlay |
| Alt+wheel over a widget | Fade that widget (5โ100%; sliders reach true 0) |
| Shift+wheel over a widget | Fade just its background โ gauges/text stay solid |
| Right-click any widget | Context menu, drawn inside the overlay so it shows in the headset too: Properties (desktop window) ยท Properties here (VR-friendly) ยท Show background ยท Bring to front / Send to back ยท Undo last change ยท Remove. Track Map adds saved-track, community-library and map-view pages (โน back returns). Wheel scrolls long lists; Esc or the X closes it. |
| Click a Timing row | Select that driver as differential opponent |
| Click the Timing title | Toggle full field โ relative-5 view |
| Click the Track Map title | Cycle map modes (All / Relative-5 / Pace / Classes) |
| Click the Setup panel | Snapshot baseline A for A-vs-current comparison |
| Plain wheel over Timing | Scroll the field |
Group movement#
| Gesture | Action |
|---|---|
| Ctrl+click widgets | Add/remove each from the group (outlined) |
| Ctrl+drag on empty space | Rubber-band select everything in the box |
| โฌ Group toolbar toggle | Same rubber-band without the keyboard (VR-friendly) |
| Drag any outlined widget | Move the whole group together (formation locked, edges clamp) |
| Click empty space | Clear the group |
| Drag an outlined widget's edge | Resize the whole group โ proportionally, as one bounding box |
| Ctrl while resizing a group | Same-amount instead: every widget changes by the same pixels and stays put |
Resizing a group#
Drag the edge or corner of any outlined widget and the whole group resizes:
- Proportional (default) โ you are resizing the group's bounding box. Every widget scales and repositions inside it, so the arrangement, relative sizes and gaps are preserved. This is the "make this whole cluster bigger" behaviour.
- Same-amount (hold Ctrl) โ every selected widget changes by the same number of pixels and stays where it is. Use it to make a row of widgets all 40 px taller without spreading them apart.
Ctrl is read live, so you can switch between the two mid-drag. Shrinking stops as a group: the smallest widget hits the minimum size and the whole group stops rather than some widgets collapsing while others keep going. Snapping is off during a group resize, the same as during a group move โ it would fight the formation.
Fit#
The Fit button packs nothing and rearranges nothing โ it slides the whole arrangement to the top-left and shrinks the window to hug it. Every widget keeps its exact on-screen pixels; only the empty border disappears.
Editing made VR-friendly#
Editing in the headset used to be much harder than on the monitor. Two things caused it: the resize edges were a fixed 14 surface pixels โ about 2.6 mm of physical kneeboard panel โ and they were invisible. Both are fixed, and every part is adjustable in SET โ EDITING & VR ERGONOMICS.
| Feature | What it does | Default |
|---|---|---|
| Resize handles | Eight visible grab handles (4 solid corners, 4 hollow edge midpoints) on whichever widget is under the cursor. Drawn at exactly the grab-zone size, so what you see is what you can hit. | On |
| Grab zone | How close to an edge counts as "resize", in surface pixels. 8โ72. | 28 |
| Sticky drag | Click once to pick a widget up, move with the button released, click again to drop. Releasing the button mid-drag can't strand a widget. | Off |
| Snap | Widget edges and centres snap to other widgets and to the surface's edges, thirds and centre lines โ so you stop needing precise pointing. | On |
| Snap distance | How close before it snaps, in surface pixels. | 12 |
| Alignment guides | Green lines showing exactly which edge or centre a drag snapped to. | On |
| Pin the toolbar | The toolbar normally docks onto the Control Bar widget, which lives in the layout โ so every preset puts it somewhere different and it seems to wander. Pinning fixes it to one spot no preset can move. | Off |
Group moves are deliberately not snapped โ snapping one member would break the formation the group keeps.
Overlapping widgets โ grabbing the right one#
Stacking widgets on top of each other - the gear digit over the brake and throttle bars, say - is a perfectly good way to build a dash, and it used to make editing miserable: every click grabbed the wrong one, and the only way to reach the bottom widget was to move everything off it. Since 2026-09-20 the answer is that you never have to hit the right widget with the pointer at all:
- Pick it from the list. The Layout Designer has a Widgets on this layout list on the right, top of the pile first. Click a name and that widget is selected, wherever it is and whatever covers it.
- Lock what you are not editing. The tick box beside each name locks that widget: the pointer passes straight through it, on the designer canvas and on the overlay, so clicks land on whatever is underneath. Locked widgets draw with a dim thin border and stay selectable from the list. On the overlay, right-click โ Lock / Unlock does the same, right-click always reaches a locked widget (so Unlock is never out of reach), and Alt+click grabs one too. The lock saves with the layout.
- Selection sticks. Once a widget is selected, its body and its handles float above everything and keep winning the click even where other widgets cover it. Drag it, resize it, set its properties; Esc lets go.
- Tab cycles the stack. In the designer, Tab steps down through the widgets under the pointer, top of the pile first - a covered widget is one keypress away.
- What you point at is what you grab still holds for a plain click: a widget's outside grab margin only counts over empty space, so a neighbour's edge cannot reach in and take a click meant for a body.
- Alt+click grabs the widget underneath, cycling further down on each Alt+click.
- Stacking order is yours to set. Right-click โ Bring to front / Send to back in the overlay. In the designer: the โฒ Bring to front / โผ Send to back buttons, or PageUp / PageDown (one step), Home / End (all the way). Delete removes the selected widget. Undo covers all of it.
๐ฒ Random layout#
A button in the Layout Designer builds a complete layout at random - not random noise: each press picks a discipline (Endurance, Sprint, Oval, Time trial, VR cockpit, Drift / rally), drops in the widgets that discipline actually needs, packs them so nothing overlaps, and adds a couple of the discipline's optional extras plus a few style choices (panel opacity, gradient bars, marks, colour-only spotters, auto-scaled g). The status line under the list says what it built and why. It replaces what is on the canvas (Undo brings the old one back) and names the preset "Random <discipline> <stamp>", so Save keeps it. Edit it, or press again.
Save and Save as#
The toolbar has Save and Save as... (2026-09-23). Save overwrites the preset the overlay is showing, no dialog - if what is showing is a built-in or has never been saved it falls through to Save as, so nothing is ever created or lost silently. Save as asks for a name and puts the date/time stamp AFTER it ("Bristol night 20260923_1412"), so the preset list sorts and reads by what you called it. Pick an existing preset in the dialog to overwrite it.
Recentring the VR view (the car around you, not the kneeboard)#
Under the SteamVR runtime, holding the Meta button recentres the Oculus space, which SteamVR ignores - so the car never moves and the SteamVR dashboard is out of reach without controllers. RaceVisor now does it for you: Hotkeys โ "SteamVR: recentre the view" binds it to any wheel button (or Find โ "recentre"). It resets SteamVR's seated position on your current head pose, which is the space iRacing sits in under SteamVR, exactly what the dashboard's Recenter does. Needs SteamVR running with RaceVisor attached to it (the VR Performance widget shows that). Not to be confused with the Kneeboard Position widget's Recenter, which moves the kneeboard to your head. Under the Meta Link runtime the Meta button works as expected and this hotkey has nothing to do.
Properties here (VR-friendly)#
Right-click a widget โ Properties here. This draws the properties panel inside the overlay, so it is visible in the headset without OpenKneeboard switching tabs away from the dash you are editing โ which is what made the normal Properties window awkward in VR.
The whole right-click menu is drawn inside the overlay the same way (2026-09-01), so widget editing finally works end-to-end from the headset. Two known limitations:
- The OBS panel and Kneeboard Position widgets keep their old desktop-style menus - they host live Windows controls, and their menus appear on the monitor only, not in VR.
- The hover tooltip can overlap the menu's top row for a moment; move the mouse and it clears. Cosmetic, known.
What Ctrl+Z actually undoes (read this if undo "never works" for you)#
Undo covers layout changes: widget moves, resizes, group moves, add/remove, everything changed through either Properties panel or the right-click menu, Alt/Shift+wheel fades, the opacity rescue, preset loads and resets. One press = one step back; the status line says how many steps remain.
It does not cover things that are not layout: OpenKneeboard's pose sliders (those have their own Reload / Original buttons), Media settings, or view-mode cycles like the timing tower's full-field/relative toggle.
The trap: Ctrl+Z only registers while the overlay window has DESKTOP focus, in interactive mode. Click the sim, the desktop, or anything else first and the keypress goes there instead - silently. From inside the headset the overlay almost never has desktop focus, which is why undo can feel like it never works in VR. The fix is the "Undo last change" row in the right-click menu - it needs no keyboard and no focus, so it works from the headset.
It carries opacity, background, font size, the accent swatches, and the no-background toggle, with oversized slider knobs meant to be hit with the drawn cursor. Drag its header to move it; X closes it. The regular Propertiesโฆ (window) entry is still there and still has everything, including the font picker.
Per-widget font#
Every widget has its own Font picker in Properties โ any typeface installed on your PC, or Default (Segoe UI). Font size stays a separate slider (60โ180%), so you can change typeface and size independently. A layout that names a font you don't have falls back to Segoe UI instead of failing, so presets from other people always render.
Build expiry (pre-1.0)#
Pre-1.0 builds age out on purpose, so a known-buggy copy someone downloaded once does not stay in use forever:
- After 30 days the overlay shows an orange banner naming the build's age and where to get a current one. Everything keeps working โ it never stops you racing.
The build date is stamped at compile time, and the banner is drawn in the overlay so it is visible in the headset too, not just on the monitor. Public builds only ever warn; they are never disabled, so a copy you downloaded once will still run months later.
The opacity system (three independent layers)#
| Control | Scope | Where |
|---|---|---|
| Overlay backdrop slider | The dark canvas behind everything (0 = widgets float directly on the sim) | Toolbar โ slider, saved per layout |
| Widget Opacity | The whole widget, content included (0 = invisible) | Toolbox/Designer slider, or Alt+wheel |
| Background Only | Just the widget's panel box โ content stays solid | Toolbox/Designer slider, or Shift+wheel |
| Borderless checkbox | Hard-off for the panel background | Toolbox/Designer |
| Transparent widget backgrounds (all) | One click strips every panel in the layout | Toolbox |
Everything is per-widget, per-layout, saved in your own file โ your ghosted-HUD taste never affects anyone else's presets. Ghosted too far? Ctrl+Alt+Shift+1.
Note: in interactive mode, background-less widgets show a faint gray placeholder so you can grab them โ it disappears when you Lock.
Sims#
Sim support beyond iRacing is in active development and changes constantly until it stabilises. Treat anything below as work in progress, not a promise: behaviour, and which channels appear, can change from build to build.
RaceVisor reads whichever sim is running and switches automatically as they open and close. Order of preference: iRacing -> Assetto Corsa / ACC -> Automobilista 2 -> rFactor 2 -> demo data. iRacing wins a tie because it is the only one that publishes opponents, deltas and a full session description, so every widget works.
Where each sim stands today#
| Sim | On the monitor | In VR |
|---|---|---|
| iRacing | fully supported | fully supported - the setup RaceVisor is built around |
| Assetto Corsa | working | working - but read the three VR traps below (DRIVE button, window focus, race hold) |
| ACC | working | working - native VR, none of the AC traps apply |
| Automobilista 2 | working | works, but the kneeboard may not appear - see below |
| rFactor 2 | working, needs a plugin once | working - verified 2026-08-31; see its gotchas below |
"Working on the monitor" means telemetry was read correctly and the widgets drove from it. Anything marked untested simply has not been sat in front of - it is not a known failure.
If you only care about VR, iRacing is the one to trust. The other sims each pick their own VR plumbing, and that is where the trouble lives - none of it is RaceVisor code.
The one rule that catches everyone: exclusive fullscreen#
A sim running in exclusive fullscreen will hide the overlay. Windows will not draw any other window over an exclusive-fullscreen game - not RaceVisor, not Steam's overlay, nothing. The overlay is still running and still reading telemetry; you just cannot see it.
Set the sim to windowed or borderless and it appears immediately:
| Sim | Where |
|---|---|
| iRacing | in-game graphics options |
| Assetto Corsa | the AC Launcher Video tab, or FULLSCREEN=0 in Documents\Assetto Corsa\cfg\video.ini. The in-game F11 toggle does NOT persist - the launcher owns that file. Content Manager offers true borderless. |
| ACC | in-game video settings |
| rFactor 2 | in-game Display settings (remember to press Apply), or WindowedMode=1 + Borderless=1 in UserData\Config_DX11.ini with the game closed - rF2 rewrites that file on exit |
None of this applies in VR: the kneeboard is composited by OpenKneeboard, so the sim's desktop display mode is irrelevant.
Also check which monitor it is on. The overlay reopens wherever you last left it. An overlay sitting on a second screen while the sim is on the first looks exactly like a broken overlay.
Assetto Corsa and Assetto Corsa Competizione#
Nothing to install or configure - both publish shared memory, and because ACC is an AC spin-off that kept the same interface, one code path serves both.
You get: rpm, gear, speed, throttle, brake, steering, fuel (litres and %), lap number and lap percentage, lap times, position, tyre temperatures, tyre wear, tyre pressures and g-force. The car's real rev limit drives the shift lights.
You do not get, because AC does not publish it: other cars (so the radar, timing tower and gap widgets stay empty), the best-lap delta (it shows -- rather than inventing one), and clutch position.
Automobilista 2 - one setting, off by default#
Settings -> System -> Shared Memory must be set to "Project CARS 2". It ships off, and with it off RaceVisor cannot tell AMS2 apart from AMS2 not running at all - you get demo data and no warning. This is the single most common "AMS2 does nothing" cause.
Set the game to Windowed or Borderless as well. In exclusive fullscreen AMS2 gets ejected from its display mode and will not restore from the taskbar.
AMS2 uses the Project CARS 2 shared-memory layout, so you get rpm, gear, speed, throttle, brake, clutch, fuel, lap and sector times, position, tyre temperatures and g-force, plus opponents.
VR: what actually has to be true#
The dash reaches the headset through OpenKneeboard, which composites it over the sim. RaceVisor itself is headset-agnostic - anything OpenKneeboard supports (SteamVR/OpenVR, OpenXR) will do, including Index, Reverb, Vive, Pimax, Quest over Link or Virtual Desktop, and Valve's Steam Frame in PC-VR (streaming) mode - it is a SteamVR headset, so it takes the same SteamVR + OpenKneeboard chain with none of the Quest/Meta-runtime gotchas below. Not in the Frame's standalone mode (nothing Windows runs there, the sims included). Not yet hands-on verified on a Frame.
Four things must be right, and every one of them cost the author a session to find:
1. OpenKneeboard -> Settings -> VR -> SteamVR support must be enabled if the sim runs through SteamVR/OpenVR. It is off by default. With it off the kneeboard never injects, nothing appears in the headset, and recentering does nothing at all. 2. OpenKneeboard needs a Window Capture tab pointed at the RaceVisor window, and that is the tab to select in the headset - not OpenKneeboard's own dashboard tab. 3. Start OpenKneeboard before the sim. It injects at game launch; starting it afterwards does nothing until the sim is restarted. 4. The Rendering API in OpenKneeboard's game entry must match the API the sim actually uses. Sims do not all agree, and the label on the Steam launch option is not evidence.
5. Trails / ghosting on the kneeboard (and everything else) while the GPU sits idle = the sim is being throttled and reprojected. When the VR runtime decides the sim finishes its frames too late, it holds the sim to half rate and fills in with synthesized, warped frames. High-contrast flat things smear worst, so the kneeboard's big gear digit is where you see it first. RaceVisor's VR Performance widget calls the state out in red ("SteamVR THROTTLING"). Two causes seen on the author's rig, 2026-09-15:
- A stalled controller poll. An overlay or helper hammering a DirectInput device that has just been re-enumerated (headset reboot, USB hub reset, the Quest's virtual gamepad coming and going) can stall the sim, which polls the same devices every frame - the sim's frame went from 4.5 ms to 20 ms with the GPU idle. RaceVisor had exactly this bug and it is fixed (the same bug killed F12); if hotkeys die at the same time as the trails appear, restart the overlay.
- Reprojection itself. On Quest / Link the knob is the Oculus Debug Tool โ (PC) Asynchronous Spacewarp โ Disabled (it resets on reboot); SteamVR's own Motion Smoothing shows Not Supported on that driver. With it off a missed frame judders instead of smearing, and the sim runs at what it can really do.
6. Anything that grabs keyboard focus while you race can cost you the sim's input - Assetto Corsa in particular reads the wheel only while its window has focus. A desktop helper can do that from behind your back: FloDee's floater, for one, takes focus the moment the mouse pointer rests on it, so a pointer parked on the dot while you are in the headset hands focus to FloDee. Park the pointer somewhere empty, or close FloDee before driving - the โ icon / FloDee widget does that from inside the dash. 7. A desktop app that repaints a transparent window nonstop halves the kneeboard's frame rate. OpenKneeboard shows whatever the overlay window last drew, and the overlay draws once per desktop frame tick. A layered (see-through) window that redraws itself continuously - FloDee with Floater colour rotate, Floater border rotate or Panel colour rotate switched on is the case measured (2026-09-15: overlay ticks fell from 62/s to 29/s the moment FloDee ran, and dipped to 12-17/s in stretches) - makes the kneeboard feel laggy and jerky, worst with Follow head on, while the sim itself stays perfectly smooth. Turn those colour-rotate options off in FloDee's settings (or close FloDee while racing; FloDee releases after 2026-09-15 pause those effects by themselves while a sim is in front or the mouse and keyboard have been idle 30 s). Verified on track after the fix: the overlay held the monitor's full 75 ticks/s, Follow head included. RaceVisor's opt-in perf log (Documents\RaceVisor\perflog.on) prints "WPF ticks/s" so you can see the tick rate directly. Also fixed the same day: the overlay's own refresh gate lost a quarter of the ticks when set to 60 Hz; settings of 55 Hz and above now render every tick.
8. Headset frozen on the last frame after the sim closes (SteamVR runtime + Quest Link). The picture in the headset stops dead, the desktop shows SteamVR Home with the kneeboard still up, and nothing recovers on its own. Seen twice in three sessions on the author's rig, 2026-09-17. The logs say what it is: SteamVR's compositor prints "WaitForAcquire timed out - the driver did not take the sync texture" every frame and vrserver prints "oculus: OVR Error" every frame - SteamVR's bridge to the Meta runtime has wedged. This time it followed a half-second USB re-enumeration of the Quest (the Oculus audio device vanished and came back) and the headset being lifted off and on. The Quest itself is NOT hung: Link keeps streaming the stuck frame. So do not hard-reset the headset - restart SteamVR on the PC instead: Recover-SteamVR.ps1 in the release workspace kills SteamVR and starts it again, and the picture is back in seconds. The real fix is to stop using SteamVR as the OpenXR runtime for Quest over Link at all: in the Meta Quest Link app set Meta Quest Link as the active OpenXR runtime (which the Passthrough Portal needs anyway) and keep SteamVR only for the VR View filming route. A USB blip preceded this one, so also try another port or cable.
Quest / Link users, note: a sim may quietly choose the native Oculus (LibOVR) API when you are on Link, even with SteamVR running. OpenKneeboard's Oculus path is legacy, and on a current Meta runtime it can black out the headset entirely while the desktop mirror keeps working. If the headset goes black the moment VR starts, set that game's Rendering API to No overlay to confirm, and expect no kneeboard in that sim until OpenKneeboard's Oculus support is fixed. Headsets with no Oculus runtime at all - Index, Reverb, Vive - do not hit this, because the sim falls back to SteamVR/OpenXR.
Assetto Corsa in VR - the three things that look like dead pedals but are not (each one cost the author hours):
1. You land at the pit/setup screen and must click DRIVE. In VR that screen is easy to miss entirely - the session looks started, the engine note plays, and the car sits held with the brake on ignoring every input, because it is not yours yet. Point the mouse at DRIVE in the headset view and click. 2. AC only reads the wheel while its desktop window has focus. Click anything else on the desktop - even once - and every pedal and button goes dead until you click AC's window again. On the monitor you notice immediately; in VR it just looks broken. 3. In a RACE session the AI holds your car with the brake on until the start sequence hands over. Telemetry shows brake pinned at 1.0 and a fixed rpm - that is the hold, not a fault. Test in PRACTICE first.
Most of the community runs Content Manager instead of the stock launcher - not required for VR to work, but it puts session, controls and VR mode in one place. Content Manager is a third-party launcher by x4fab, free from acstuff.club/app (a paid key unlocks extras; the free Lite version covers everything mentioned here).
None of the above affects the monitor overlay, which works regardless.
rFactor 2 - needs a plugin, once#
rF2 publishes nothing to third parties on its own. It needs The Iron Wolf's rF2 Shared Memory Map Plugin - the same one Crew Chief and TinyPedal use. Also covers Le Mans Ultimate.
1. Put rFactor2SharedMemoryMapPlugin64.dll in rFactor 2\Bin64\Plugins\ 2. Launch rF2 once and quit fully - that is what registers it 3. With rF2 closed, open UserData\player\CustomPluginVariables.JSON and set the plugin's " Enabled" to 1. Note the leading space in that key name - the one without it does nothing. rF2 rewrites this file when it exits, so editing it while the game runs is wasted. 4. Start rF2. Check_rF2_Telemetry.ps1 confirms the plugin is publishing.
rF2 gives everything AC does plus opponents (up to 128 cars), so the radar, timing tower and track map work there. Its gear numbering already matches RaceVisor, and it reports the true rev limit per car.
rFactor 2 gotchas (every one verified the hard way):
- rF2 keeps its own wheel bindings, and they go stale. If you recalibrate pedals, add or remove Logitech G HUB, or change anything about how the wheel enumerates, rF2's stored bindings can silently point at a device that is no longer there - the game simply ignores the pedals while every other app sees them fine. Fix: rF2 Settings -> Controls, re-detect throttle and brake by pressing them, recalibrate. Check the on-screen bars respond THERE before blaming anything else.
- rF2 grabs the mouse and keyboard exclusively while running. You cannot alt-tab-and-type somewhere else without giving the game up; this is rF2 behaviour, not the overlay's.
- First load of a track builds shaders and can take several minutes with one CPU core pinned and the memory use flat. It looks hung; it usually is not. Loads after that are fast.
- The window focus rule applies here as in AC: input flows only while the game's desktop window is the foreground window.
- The dash shows the car flagged as the player. In a session with AI, rF2's vehicle list is in no particular order - RaceVisor finds you by rF2's own is-player flag, so the dash follows your car, not slot 0. (Fixed 2026-08-31; before that an AI's dashboard could show.)
Launch scripts you can copy and adapt#
Getting a VR session up is mostly about starting things in the right order. These scripts are plain PowerShell - save them as .ps1 files, adjust the paths in the CONFIG block at the top, and run them from a shortcut or terminal. Everything you might need to change is in that block; the logic below it should not need touching.
VR session launcher#
Starts the whole chain in the order that works: wheel software -> SteamVR -> OpenKneeboard -> RaceVisor -> the sim. Each step is skipped if the program is already running.
```powershell
$WheelSoftware = "C:\Program Files\LGHUB\lghub.exe" # G HUB / SIMAGIC / whatever your wheel needs; "" to skip $SteamVR = "C:\Program Files (x86)\Steam\steamapps\common\SteamVR\bin\win64\vrstartup.exe" $OpenKneeboard = "C:\Program Files\OpenKneeboard\bin\OpenKneeboardApp.exe" $RaceVisor = "C:\Path\To\RaceVisor.exe" # wherever you put it $SimSteamId = "244210" # Steam app id: iRacing 266410, AC 244210, ACC 805550, AMS2 1066890, rF2 365960 $NeedSteamVR = $true # $false for sims that do not use SteamVR/OpenVR
function Start-IfNeeded($exe, $procName) { if ($exe -and -not (Get-Process $procName -ErrorAction SilentlyContinue)) { Start-Process $exe return $true } return $false }
if ($WheelSoftware) { Start-IfNeeded $WheelSoftware ([IO.Path]::GetFileNameWithoutExtension($WheelSoftware)) | Out-Null; Start-Sleep 8 } if ($NeedSteamVR) { if (Start-IfNeeded $SteamVR "vrmonitor") { while (-not (Get-Process vrmonitor -ErrorAction SilentlyContinue)) { Start-Sleep 3 } Start-Sleep 8 # let the compositor settle before anything tries to inject } } Start-IfNeeded $OpenKneeboard "OpenKneeboardApp" | Out-Null; Start-Sleep 6 # BEFORE the sim - it injects at game launch Start-IfNeeded $RaceVisor ([IO.Path]::GetFileNameWithoutExtension($RaceVisor)) | Out-Null; Start-Sleep 4 Start-Process "steam://rungameid/$SimSteamId" Write-Host "Chain up. Remember: click DRIVE (AC/rF2), keep the sim window focused, headset on before it loads." ```
To adapt it: change the paths, change $SimSteamId, and set $NeedSteamVR = $false for a sim running native Oculus or OpenXR-on-Meta. Add extra programs (OBS, crew chief, etc.) as more Start-IfNeeded lines - order matters, OpenKneeboard must beat the sim.
Telemetry sanity check#
When the dash shows nothing, this settles in seconds whether the sim is even publishing. Run it while the sim is on track; each section prints live values or "absent".
```powershell
try { $m=[IO.MemoryMappedFiles.MemoryMappedFile]::OpenExisting('Local\acpmf_physics','Read') $a=$m.CreateViewAccessor(0,0,'Read') "AC/ACC live: rpm={0} throttle={1:N2} brake={2:N2}" -f $a.ReadInt32(20),$a.ReadSingle(4),$a.ReadSingle(8) $a.Dispose();$m.Dispose() } catch { "AC/ACC: absent (not running, or not in a session)" }
try { $m=[IO.MemoryMappedFiles.MemoryMappedFile]::OpenExisting('$pcars2$','Read') "AMS2: publishing (remember Shared Memory = 'Project CARS 2' in its settings)" $m.Dispose() } catch { "AMS2: absent (game closed, or Shared Memory setting is OFF - it ships off!)" }
try { $m=[IO.MemoryMappedFiles.MemoryMappedFile]::OpenExisting('$rFactor2SMMP_Telemetry$','Read') $a=$m.CreateViewAccessor(0,0,'Read') "rF2: publishing, {0} vehicles in session" -f $a.ReadInt32(12) $a.Dispose();$m.Dispose() } catch { "rF2: absent (game closed, or the shared-memory plugin is not installed/enabled)" } ```
How to read the results: absent while the sim is on track means the sim-side setup is wrong (AMS2's shared-memory setting, rF2's plugin) - no overlay setting will help until that prints live values. Live values here but a frozen dash means the car is not actually yours yet (AC's DRIVE button, a race-start AI hold) or the game window lost focus.
Several instances at once#
RaceVisor has no single-instance lock: launch RaceVisor.exe as many times as you like (monitor overlay + headset overlay + an OBS feed, each on its own layout/preset). They share the same settings files and track cache; the community library syncs once per instance.
Presets#
- Layout 01โ20 โ hand-designed defaults
- Mega 01โ30 โ every widget type on screen at once, 30 different arrangements (different orderings, densities, hero widgets, mirrorings). Use them as starting material: pick one with good bones, remove what you don't want, Fit, Save asโฆ
- The Layout Designer opens on what is on screen - the live layout, unsaved edits and all - not on whatever preset it was last closed on.
- Saving works the same everywhere. Whether you save from the Control Bar's Save asโฆ, the inline toolbox, or the Layout Designer, you get the same dialog: a list of every layout you already have, a name box pre-filled with the one currently loaded, and a line telling you whether Save will create a new layout or overwrite an existing one. The name box is pre-filled with a fresh
yyyyMMdd_HHmmstamp + the current layout's name, so you can just hit Enter: that always creates a new layout, never overwrites the one you started from. (Enter works in the inline toolbox's name box too.) Click any layout in the list to reuse its name. Every path also applies the same filename rules, so names stay consistent no matter where you saved from. Saving from the Designer also applies that layout to the overlay immediately and selects it in the spinner, so what is on disk, what is on screen, and what the spinner says are always the same thing. - RaceVisor reopens exactly as you closed it. The layout on screen - including edits you never saved as a preset - is snapshotted every few seconds and at close, and restored on the next start; the spinner still names the preset it came from. A Reset Defaults clears the snapshot. (With several instances open, the one that closes last is what comes back.)
- Your saves live in
Documents\RaceVisor\layouts\*.jsonand appear in the spinner and designer automatically. Resetting defaults never touches your named saves (except a full Reset Defaults, which wipes and regenerates the folder).
Widgets#
RPM (cluster/horiz/vert) ยท Shift light ยท Gear ยท Speed (km/h / mph) ยท Inputs ยท Tires ยท Fuel & engine ยท Timing tower ยท Differential ยท Delta / Gap graphs ยท Tire wear trends ยท Fuel consumption ยท Setup comparison ยท Corner pace ยท G-force circle (with auto scale) ยท G Long bar / G Lateral bar (g as a sweeping centre-zero bar, vertical or horizontal) ยท Brake vs G / Throttle vs G (pedal beside the g it produced - shows a locking or spinning wheel) ยท Steering vs G (steering beside the lateral g it produced) ยท Steering bar ยท Spotter ยท Radar (with closing speed) ยท Pit Stop Planner (fuel to the end, litres to add, PIT THIS LAP) ยท Weather ยท Pit service (sends real pit commands) ยท Media ยท Track map ยท Control Bar ยท Track Progress (Horiz / Vert) - a flat/linear track map: the lap unrolled into a straight strip with start-finish at both ends, quarter-lap ticks, and every car on track placed by lap distance. You are the fat accent marker, the selected opponent gets a green ring, cars in the pits go dim. Because it needs no track shape it works on lap one of a track you have never driven, which the Track Map cannot. Horizontal runs left to right, vertical runs bottom to top. The original Track Map is unchanged - these are extra widgets, not a replacement. ยท Gear (RPM + brake color) (one big digit that is also a rev gauge: it fills from the bottom up with rpm / redline, blue at the bottom through the cold-to-hot gradient to the colour for that rpm at the fill line, the rest of the digit dimmed; it strobes red at the shift point, and brake pressure pulls the whole digit toward pure red - 100% brake = 255,0,0, 0% leaves the rpm colours alone; N and R keep the warn color. Properties -> Bar marks & gradient -> Gradient fill off gives the older single-colour digit that just changes hue with rpm) ยท Steering wheel (round, turns with your real wheel, angle in degrees; the Inputs widget carries the same wheel plus % values on its pedal bars) ยท Clutch / Brake / Throttle (one pedal each, big % readout; pick the (Horiz) or (Vert) palette entry, or just resize - wider than tall lies flat, taller than wide stands up; force it in Properties โ Pedal orientation) ยท Spotter Left / Right / Clear-Hold (the spotter split into three lamps you can park where you look: LEFT and RIGHT light amber for one car, red for two or 3-wide; the status lamp shows HOLD while anyone is alongside, CLEAR once both sides have been quiet for the set delay and no car is within the set range, CLOSE in between) ยท Clocks: Local (wall time + date), Track (sim time of day), Session (elapsed), Remaining, All-in-one, and Clock (Analog) - a proper dial with hour, minute and sweeping second hands showing local time, date underneath when the box is tall enough ยท Stopwatch (Analog) and Stopwatch (Digital + laps) - see Stopwatch below ยท Driver Chat (voice + text with other RaceVisor users, independent of the sim's comms - see its own section below).
Why the tire temps and wear never move while you drive: iRacing itself only refreshes the tire temperatures, wear and cold pressures it publishes to any telemetry app when you are stopped in your pit stall (and once more when you leave the garage). That is a deliberate anti-cheat in the sim - live tire data is not available to overlays in official sessions - so the Tires widget shows the last pit-stall reading, which is why it looks different every time you check but never changes in front of you. Nothing is stuck; the sim is not sending it. The other sims (AC, ACC, AMS2, rF2) publish live tire data and the widget moves normally.
Widget Properties (right-click โ Propertiesโฆ)#
Every widget has its own control panel: opacity, background-only opacity, font size (60โ180%), font family (any installed typeface), accent color (hex + swatches), outline text, borderless, shadow, remove.
Outline text draws a dark outline behind everything the widget writes. Turn it on when light text sits over a pale sky, a bright livery or a busy wallpaper โ a white gear digit over a blue sky is otherwise almost unreadable. The outline is a true stroke of the glyph shapes with round corners (since 2026-09-23 - the old one was a ring of offset copies and scalloped every corner), in any colour and width you set. It costs a little extra draw time on text-heavy widgets (the hover tooltip's ms/frame readout will show it), which is why it is per-widget and off by default.
Drop shadow puts a soft shadow behind the widget's panel and behind every character it writes. Angle (0 = right, 90 = down, 180 = left, 270 = up) and Distance (surface pixels, 0 = directly behind, i.e. invisible) move it; the default is 45ยฐ / 4 px, down and to the right. Text drawn straight over the sim with no panel gets the character shadow only, which is often all the separation it needs without the heavier outline.
Color dropper โ grab your team colors. Next to the accent swatches, โ Pick color from screen samples any pixel on your desktop: click it, move the cursor over a livery, a logo, a sponsor page or another app, and the widget previews that color live as you move. Click to keep it, Esc to cancel and put the old color back. It reads the screen directly, so it is not limited to RaceVisor's own window. Edits apply live and save with the layout.
G-force meters get their own block: lock horizontal (ignore lateral - a pure accel/brake meter) or lock vertical (ignore accel/brake - a pure cornering meter), trail on/off, dot size (50% to 400% of the normal dot on the g circle - bigger for a small or far-away widget), peak hold on every g widget - the circle, the Long g and Lateral g bars and the Brake vs g / Throttle vs g bars (amber ticks at the highest g per direction plus the peak numbers; Hold peak for sets how long a peak stays, 1-30 s, before it bleeds off at a quarter g per second), flip up/down or left/right, full scale 1-5 g in half-g steps, auto scale (the outer ring follows the highest g of the last ~10 s, rounded up to the next half g, eased so it never jumps - a road car and an open-wheeler both fill the circle; the full-scale slider is ignored while it is on), and dot smoothing.
Spotter lamps get their own block: how long a lamp stays lit after the spotter goes quiet (default 0.5 s - kills flicker at the overlap line); for the Clear/Hold lamp also the quiet time before it says CLEAR (default 1 s) and the distance that must be car-free ahead and behind (default 10 m; 0 = trust the spotter alone). No words (colour only) turns a lamp into a plain colour block with nothing written on it - no LEFT / RIGHT / CLEAR / HOLD / 3-WIDE. Grey is spotter-off, green clear, amber a car alongside (or hold), red two cars or 3-wide. Faster to read out of the corner of your eye, and it still works shrunk to a thin strip along an edge.
Rotation - every widget (Properties -> Rotation): turn any widget about its own centre, 0 to 359 degrees clockwise. Drawing, resize handles and clicking all follow the angle, on the overlay and in the Layout Designer. The slider snaps to the step you pick (free, 5, 15, 30, 45 or 90 degrees) and the 0 / 90 / 180 / 270 buttons jump straight there. A vertical pedal bar at 90 is a horizontal one that fills the other way; a gear digit at 15 degrees matches a tilted wheel.
Bar marks & gradient - every sweeping bar (pedals, the g bars, Brake vs g, Throttle vs g, the horizontal and vertical rpm bars and the three bars inside Inputs): Properties -> Bar marks & gradient. The rpm bars are a cold-to-hot gradient from idle to the redline by default - untick Gradient fill there and they paint the accent colour flat instead. Marks puts a line across the bar every N percent (25 = marks at 25 / 50 / 75, the 50 line brighter), so you can see how far an analog pedal actually travelled instead of guessing from the fill; Number the marks prints the percentage beside each one when the widget is big enough. Gradient fill runs cold to hot like a heat map: blue at 0%, through cyan, green and yellow, to red at 100%. Pick a far colour instead (amber, green, cyan, purple, white) and it runs blue to that colour. The rpm bars, the cluster arc and the shift LEDs use the same cold-to-hot scale. Marks flip with Fill from the other end, so 25% is always a quarter of the travel.
Over-rev threshold (Properties -> At the shift point -> Over-rev at, on the rpm cluster, both rpm bars, the shift light and Gear (RPM + brake color)): where this widget starts its flash / solid light, as a percentage of the car's redline (50-120%). Far left = Auto, the car's own shift rpm from the session data, which is the default. Each widget has its own, so a shift light can fire early as a warning while the gear digit waits for the real shift point.
Rpm bars - the over-rev light (Properties -> At the shift point -> Over-rev light at the end of the bar): the round light at the end of the horizontal / vertical rpm bar can be switched off. The bar then takes the whole box and still strobes red past the shift point on its own.
G-force bars (g as a sweeping bar)#
The g circle shows both axes at once; sometimes you want ONE axis as a bar you can read like a pedal. G Long bar is braking and acceleration, G Lateral bar is cornering. Both are centre-zero: the fill grows out of the middle toward whichever way the force pushes, with a centre line and, with marks on, ticks outward in both directions (50 = half of full scale each way). Palette entries come in (Vert) and (Horiz); Fill from the other end flips which way counts as positive, so up/down/left/right are all reachable. Range, auto scale, the flip switches and smoothing are shared with the g circle (same Properties block, minus the circle-only rows), so every g widget on a layout agrees.
Brake vs G is the one to put on a wet track. Two lanes sharing one sweep: the pedal and the deceleration it actually produced (longitudinal g, decel only, on the same scale as the g bars). Push harder and watch the second lane: when the pedal keeps rising and the g lane FALLS, the tyres have locked - which is exactly the thing you cannot feel through a wheel. The widget frames itself red and says LOCKING when hard pedal meets a g that has dropped well below its own recent best, and clears as soon as the g comes back. Match your braking to the g lane and you are braking at the limit the surface allows. Lay it over the plain Brake bar if you like the pedal big and the g small.
Throttle vs G is the same idea the other way round: the throttle pedal beside the acceleration it actually produced. Feed in more throttle and watch the g lane - when it falls while the pedal keeps rising the driven wheels are spinning, and the widget frames red and says SPINNING. That is the traction limit out of a slow corner, in the wet or on cold tyres, made visible. Every g widget - the circle, both g bars, Brake vs G and Throttle vs G - has the same auto scale switch, so pick it per widget or leave the range fixed.
Steering vs G does for cornering what Brake vs G does for braking. Two centre-zero bars sharing one sweep: the steering wheel on top and the lateral g it produced under it. Turn left and both bars sweep left; turn right and both sweep right. Wind on more lock and watch the g bar - when the steering keeps growing and the g does not, the front tyres have stopped answering. Palette entries come in (Horiz) (two rows) and (Vert) (two columns). In Properties: Lateral g bar first swaps the two bars; Invert mirrors the steering bar and Flip left / right mirrors the g bar, for a sim that publishes either one the other way round; Auto scale steering (on by default) lets full scale follow the most lock you used in the last 10 seconds, or turn it off and set Full lock yourself (30-900 degrees each way); the g bar has the usual range, auto scale, smoothing and peak hold; Gradient fill can go on both bars or on just one (Gradient on); tick marks and Fill from the other end work as on every other bar.
Steering bar is the steering lane alone, (Horiz) or (Vert), with the same steering options. Its partner as a separate widget is the G Lateral bar above, so you can place and size the two independently instead of using the combined widget.
Flash or just turn on (Properties -> At the shift point): every widget that reacts to the shift point - the cluster, both rpm bars, the shift light and Gear (RPM + brake color) - can strobe as before, or simply light solid the whole time you are past the shift rpm. Per widget, so one gauge can flash while its neighbour stays steady.
Pedal threshold flash (Properties -> Threshold flash, on Clutch / Brake / Throttle): tick it and set a percent (default 90%). At or above that the whole widget flashes - the bar strobes red and a red frame pulses round the panel - and it keeps flashing the entire time you are above the threshold, rather than blipping once as you cross it. Meant to be caught in peripheral vision.
All five rpm meters get a peak-rpm marker (Properties -> Peak rpm marker): Off, Hold for a few seconds (0.5-10 s after the peak, default 2), or Keep the highest until reset. Show only above is the threshold: the marker stays hidden until the peak is at least that percentage of the car's redline (always, by default), so it ignores the low peaks from pootling around and only reports the ones that matter near the shift point. The cluster dial marks it with a white tick (the red tick stays the redline) and prints the number beside the live rpm; the horizontal and vertical bars get a white line across them; Gear (RPM + brake color) gets a white line across the digit at the peak's height on its gauge scale plus the number underneath; the single shift light, having no scale, wears a ring tinted with the gradient colour that rpm reached. Every rpm widget shares one peak, so two gauges can never disagree - only the display rule is per widget, which is what lets one gauge hold until reset while another forgets after two seconds. Reset it from the button in Properties, the Reset peak rpm Icon Bar icon, or the rebindable global hotkey.
Radar widgets get their own block: car blip width and length (0.5-2.5x), the distance at which a car counts as alongside (slides into its lane, border warning - default 7 m), the distance at which it clears again (default 10 m, never less than the first, so blips do not flicker at the boundary), and Swap left and right if the spotter's sides read backwards to you. Since 2026-09-16 the radar also reads closing speed: a blip behind you that is gaining at more than about 5 km/h turns amber, and the strip under the plot names the nearest car ahead and behind with the distance and "closing 9 km/h" / "pulling away 4 km/h" - the difference between a car that is racing you and one that is just there.
Pit Stop Planner (fuel to the end, pit this lap)#
The question you leave the headset to do maths for. One panel, one verdict line at the top:
- NO STOP NEEDED (green) - the tank covers the rest of the session plus the reserve.
- stop in N laps - a stop is coming, here is how long the tank lasts before the reserve.
- PIT WINDOW OPEN ยท N laps left (amber) - three laps or fewer of fuel above the reserve.
- PIT THIS LAP (red) - one lap or less above the reserve.
Under it: fuel now, use per lap (measured from the fuel level at each lap change, averaged over the last three clean laps - "(est)" means it is still using the sim's instantaneous rate until two laps exist), laps in the tank, laps to go (from the lap count in a lap-limited session, else time left รท lap time, marked "timed"), fuel to finish including the reserve, add at stop in litres (next to the amount currently set in the sim's pit menu, amber when that is short), and the worst tyre's remaining wear. The reserve is one lap by default (Properties โ Pit reserve, 0 to 5). Tyre wear, like tyre temps, only updates when the sim reports it - in iRacing that is in the pit stall.
Icon Bar widget#
A strip of tiny always-available action icons โ place it anywhere, size it, fade it like any widget, and it stays clickable even in clickthrough mode while you race.
Default icons: ๐จ Designer ยท โจ Hotkeys ยท ๐/๐ Lock ยท โ Close RaceVisor ยท โ โถ preset spinner ยท โ Favorite preset (left-click loads it, right-click sets the current preset as favorite). The โ gear (interactive mode only) opens Properties, where checkboxes add/remove icons. Fully opaque by default โ fade it only if you choose to. Optional icons: ๐ฏ Recenter kneeboard ยท ๐ Fade ยท โป Reset peak rpm ยท ๐ Kneeboard on/off ยท ? Help ยท ๐ฌ Driver Chat text box ยท ๐ Driver Chat open mic on/off ยท โฑ Stopwatch start/stop (turns red while running) ยท ๐ Stopwatch lap ยท โบ Stopwatch reset ยท โฏ โญ โฎ Media play/pause, next, previous (system media keys - drive whichever player has the music).
Launchers - start any app from the bar. In the Icon Bar's Properties, the Launchers box takes one line per launcher: Label | path | arguments (label and arguments optional). Each line becomes a purple icon showing the label's first two letters; clicking it starts that program, script, shortcut or file - Crew Chief, OBS, SimHub, a PowerShell script, a setup PDF. Add app / fileโฆ browses for one; Import FloDee shortcuts pulls every app and script on your FloDee user grid in one go (folders are skipped), so the two share one launch list. Hover an icon for its label and path. Works in clickthrough like every Icon Bar icon.
Window Portal (any desktop window inside the dash)#
The reason VR racers take the headset off: the browser, Discord, OBS, Crew Chief, a notes file - all on the monitor. The Window Portal widget shows any of them live inside the dash, so it floats in the cockpit with everything else. Add as many portals as you like, one window each.
- Pick the window: unlock (F12), right-click the portal โ Pick window โ the list of every open window (live, works in VR). Or in Properties, choose from the list or type part of the title - first match wins, case doesn't matter, so
DiscordorGarage 61is enough. - The portal shows the window exactly as Windows draws it, refreshed about 12 times a second, aspect-fitted into the widget. It does not need the window on top: it can sit behind the sim or behind RaceVisor. The one thing it can't show is a minimized window - Windows gives no picture for those - so the portal tells you to restore it.
- View-only for now: reading a page, watching Discord, checking OBS. Clicking through the portal into the window is the next step.
- A portal nobody is looking at stops capturing after a few seconds; it costs nothing when the window is gone or the widget is off the layout.
- Crop - show only part of the window: Properties โ Crop has Left / Top / Right / Bottom sliders in percent of the captured window; the overlay updates as you drag, and Show whole window clears it. Use it to show one panel of a browser page, the chat column of Discord, or the keyboard from a webcam (below).
- Freehand mask - any shape: unlock (F12), right-click the portal โ Draw mask, then click the corners of the shape on the live picture (as many as you like; the drawn cursor works in VR), and right-click or press Enter to finish (Esc cancels). Only the inside of that shape shows; everything outside is see-through. The edge is outlined while the overlay is unlocked so you can see what you cut. Right-click โ Clear mask or the button in Properties removes it. The mask is stored in percent of the captured window, so it survives resizing the widget or the window, and it stacks with the crop.
- Editing a mask: while the overlay is unlocked every corner shows as a dot. Drag a dot to move it, Ctrl+click a dot to remove it (a mask keeps at least 3), Shift+click on an edge to add a corner there and drag it into place. Ctrl+Z undoes each step.
Passthrough Portal (the headset's cameras through a hole - Quest Link)#
A Window Portal shows a window. The Passthrough Portal shows the real world: the Quest's colour cameras, through a hole of any shape, exactly where you put it on the kneeboard - your keyboard, the button box, a coffee cup. On the monitor it is only an outline; the picture is composited inside the headset by RaceVisor's own OpenXR API layer, which sits between the sim and the runtime, switches on Meta's passthrough on the sim's behalf, and draws the camera feed on a mesh in the shape you drew. The sim itself never knows.
What it needs, and this is the catch: 1. Meta Quest Link as the active OpenXR runtime (Meta Quest Link app โ Settings โ General โ Set Meta Quest Link as active). SteamVR's runtime has no passthrough API, so the portal is simply absent under SteamVR - nothing breaks, it just does not draw. Virtual Desktop's runtime exposes the same Meta extension on recent versions. 2. Passthrough over Link switched on in the Meta Quest Link app (Settings โ Beta). 3. The layer installed once: Find box โ "passthrough" โ Install (one UAC prompt; it registers %LOCALAPPDATA%\RaceVisor\PassthroughLayer as an implicit OpenXR layer, like OpenKneeboard does). "Remove" in the same place takes it out. Restart the sim after either. 4. A Quest 2 / 3 / 3S / Pro. Headsets without cameras that reach the PC have nothing to show.
Then: add Passthrough Portal from the palette, size and place it on the kneeboard, and right-click โ Draw mask for any shape (or leave it as the whole box). The widget says on its face whether the layer is installed. It follows the kneeboard: RaceVisor writes the portal's position on the kneeboard's plane (from the Kneeboard Position widget's pose) to %LOCALAPPDATA%\RaceVisor\passthrough.json, and every Recenter / Follow head re-origins the portal and the kneeboard at the same instant, so they stay together. If the hole sits a little off the keys, nudge the widget - small differences in how OpenKneeboard fits the picture show up as a small offset.
Why the two portals both exist: the Window Portal + a webcam works on every headset and every runtime, sharper than passthrough; the Passthrough Portal needs no webcam and shows your real hands, but only on Quest over Link. A log of what the layer did is at %LOCALAPPDATA%\RaceVisor\passthrough-layer.log.
See your real keyboard in VR (keyboard cam): point any USB webcam at the keyboard, open the Windows Camera app (it can sit behind the sim), add a Window Portal, Pick window โ Camera, then crop it down to the keys. You now have a live, readable view of your hands and keycaps in the cockpit, on its own layout or in a corner of the kneeboard. Sharper and in colour, unlike the Quest's grey passthrough (double-tap the headset), which still works for a quick glance.
Audio widget (devices, volumes, mic mute - without leaving the headset)#
Which device Windows sends the sim to, what you hear in the headset, how loud Discord is next to the engine: all of that lives in Windows' sound settings, on the monitor. The Audio widget puts it in the dash. Three blocks:
- OUTPUT - every playback device. The default has the โ mark. Click a name to make it the Windows default (for every role at once). This is the fix for "the sim is playing through the speakers while OBS records the Quest": one click, no headset off, no Windows sound panel.
- MICROPHONE - every input device, same idea: click a name to make it the default mic.
- APPS - one row per app that is making sound on the default output (iRacing, Discord, a browser, RaceVisor's own chatโฆ), โถ marks the ones audible right now. Click the name to mute / unmute that app alone.
Every row has a volume bar - click anywhere on it to set the level (5% steps, easy to hit in VR) - and a mute button at the end (โช = on, โ = muted). Everything applies instantly and is plain Windows state, so the Windows sound panel and the widget always agree. The widget refreshes its device list once a second, so a headset that just connected appears on its own.
Like the Media widget, it is a hot island: with Hot zones on (Media settings) it stays clickable in clickthrough; otherwise unlock with F12 first.
VR Performance widget (what the headset is really getting)#
Tuning VR graphics is done blind - "it feels stuttery" is the only readout. The VR Performance widget shows SteamVR's own frame timing in the cockpit, next to the settings that move it:
- fps of NN Hz - frames the compositor actually got per second, against the headset's refresh (detected), green while it holds refresh, amber when reprojecting, red when dropping.
- App GPU and Compositor bars against the frame budget (11.1 ms at 90 Hz, 13.9 at 72), with the budget marked - the single most useful number for choosing resolution scale / pixel density.
- Reprojection - how many frames were synthesized and why (GPU-bound, CPU-bound, motion smoothing), frame interval, and RaceVisor's own draw cost so you can see it is not the culprit.
- One line of advice at the bottom: GPU-bound โ lower pixel density / shadows; CPU-bound โ fewer AI cars, view distance, background apps; headroom โ you can raise a notch.
Needs SteamVR running (it does not have to be the OpenXR runtime, same as the head-pose features) and a VR app presenting frames. Without either it says so and just shows RaceVisor's draw cost.
Notes widget (pit notes per track, typed in the headset)#
The Notepad on the monitor - brake markers, fuel per lap, "T4 is treacherous in the rain" - moves into the cockpit. The Notes widget keeps one note per track (named after the track and layout the sim reports) plus a General note; the header button flips between them.
- Write: unlock (F12) and click the text area. A big drawn keyboard appears under the text - letters, digits, punctuation, one-shot โง, space, โซ, โต for a new line, Done. Made for the drawn cursor in VR, so keys are large. A real keyboard works too while editing: type, Backspace, Enter, and Esc = Done.
- Every keystroke is saved immediately to
Documents\RaceVisor\notes.json, so nothing is lost if the sim crashes mid-sentence. Switching track (or the sim ending) closes the edit and keeps it. - Reading needs no unlock: the note for the current track is just there, and with Hot zones on the widget is clickable in clickthrough too.
FloDee widget (the author's desktop companion, driven from the dash)#
RaceVisor and FloDee are from the same author, and they work together. The FloDee widget shows whether FloDee is running and puts its actions in the cockpit:
- โ Open / Close FloDee (or Start FloDee when it isn't running) - the big button. Also an Icon Bar icon โ and a rebindable global hotkey (FloDee: open / close), so a wheel button can summon it.
- Below it, FloDee's own action catalog - Command Palette, Capture Region, Record Video, Voice to Text, Text Snippets, Screen Ruler, Pull Window to Mouse, Rotate Deskspaces and the rest - exactly the actions FloDee's keybind editor offers, fetched live from the running FloDee.
- How it talks to FloDee: FloDee 1.0.510 and newer has a local remote control (a named pipe, same Windows user only). With an older FloDee, Open / Close still works - RaceVisor sends the summon shortcut you configured in FloDee (the mouse side button or key combo) - and the widget says the other actions need a FloDee update. Not installed? The widget says that too.
- The Icon Bar's Import FloDee shortcuts (see Launchers above) is the other half: FloDee's user grid becomes launcher icons on the dash.
Now Playing widget (media keys)#
Play / pause, next, previous and stop for whatever is playing - Spotify, a browser tab, VLC - without leaving the headset. The buttons send the system media keys, exactly what the keys on a keyboard send, so every player responds and nothing needs an integration. The line above the buttons shows what is playing when the player says so in its window title (Spotify does: "Artist - Song"; browsers show the page title for YouTube / music tabs). The same three actions are also Icon Bar icons โฏ โญ โฎ. Hot island: clickable in clickthrough with Hot zones on.
Stopwatch#
One stopwatch, two faces. Stopwatch (Analog) is the classic: a big red sweep hand doing one turn a minute, a 30-minute sub-dial, the time in digits underneath, and the ring turns green while it runs. Stopwatch (Digital + laps) is the working one: big digits, the lap you are on and its running time, a lap list (newest first, the best lap in green, each lap's gain or loss against the one before it), best and average once you have two laps, and three buttons - START / STOP, LAP, RESET. Both widgets show the same timer, so add either or both.
Driving it, in order of usefulness while racing:
- Wheel button or key - three global, rebindable bindings in the Hotkey Editor (Stopwatch: start / stop, lap, reset). They work with the sim focused.
- Icon Bar icons โฑ ๐ โบ - clickable even in clickthrough, like every Icon Bar icon.
- The buttons on the digital widget - in interactive mode (F12), or in clickthrough with Hot zones on (Media settings; the digital stopwatch is a hot island like the Media widget).
Rules: LAP only counts while running; RESET only works when stopped (so a mis-press can't wipe a live timer); every action flashes what it did in the status line. Times read m:ss.hh and grow to h:mm:ss.t past an hour. The stopwatch is wall-clock, independent of the sim - it keeps running through a sim crash, a replay, or with no sim at all.
Track Map#
The map learns each track's real shape from one clean lap (dead-reckoned from speed + heading at 60 Hz โ no GPS). Until a shape is learned it shows a plain placeholder ring with "learning shapeโฆ N%" in the corner; the learned outline is saved per track and reused forever after. Pit lane and partial laps are ignored, so drive one full lap on track.
Click the title to cycle modes: All cars ยท Relative-5 ยท Pace vs you ยท Classes.
Right-click the map:
- View saved track โ show any learned track, live or not (stays pinned until you choose "Live (follow session)"). Works after leaving iRacing and during playbacks.
- Map view (menu stays open while you toggle; click/right-click outside to close):
- Rotate with driver (heading-up) โ your car fixed at center, track turns around you
- Rear chase view (zoomed) โ heading-up, car low on screen, zoomed on the road ahead
- Focus selected opponent instead of me โ pivot around your timing-tower pick
- Chase zoom +/โ (1โ6ร) with a live readout
- Rotate/chase only engage once a real shape is learned; the placeholder ring stays plain.
- Same options live in Propertiesโฆ โ Track Map View (checkboxes + zoom slider).
Your own car draws big and bright (glow + white ring); other cars are smaller dots. Leaving a session keeps the map on the track you just drove. Each widget saves its own view, so a north-up overview and a chase map can coexist on one layout.
Community Track Library & Track Pioneers#
### โณ Available soon โ currently switched off The Community Track Library is not active yet. RaceVisor makes no connection to it: it does not download shapes, does not upload anything, and the settings below are visible but disabled. When it goes live the existing track list will be cleared and Track Pioneer credit starts from scratch, so nobody is advantaged or disadvantaged by having tested early. Everything described below is what will happen once it is enabled.
RaceVisor ships with no track outlines โ every shape is learned by a driver. The Community Track Library links the app to the website so learned shapes are pooled, and the first driver to learn a track is credited forever as its Track Pioneer โ in the app and on racevisor.flodeeapp.com โ Track Pioneers.
What happens by default (no opt-in needed): at start-up and every 6 h, RaceVisor downloads any community shapes you don't have yet (read-only; sends nothing about you), so your Track Map knows a circuit before your first lap. The map's corner shows ๐ pioneer: <name> and the View saved track menu shows the pioneer + date/time as a tooltip.
Sharing & claiming credit (opt-in): Settings (Media widget โ โ / Icon Bar โ Settings) โ COMMUNITY TRACK LIBRARY ยท TRACK PIONEERS:
- Download community track shapes automatically โ on by default; untick to stay fully offline.
- Share tracks I learn & claim Track Pioneer credit โ off by default. When on, each newly learned shape is uploaded the moment the clean lap completes. If nobody shared that track before, you get the flash
๐ NEW TRACK! You're the Track Pioneer of โฆ; otherwisetrack shared ยท โฆ was pioneered by <name> on <date>. - I am not iRacing staff โ required to claim credit (iRacing employees get every track before the rest of us, so they are ineligible). Honor system plus a server-side name/ID check; ineligible uploads still store the shape for everyone, credited to "RaceVisor community".
- Pioneer display name โ how you are credited; blank = your iRacing name from the session.
- Sync now / Track Pioneers page โ โ manual refresh and the public leaderboard.
- The same toggles live in the Track Map's right-click menu โ Community track library.
What is logged: track (name/config/iRacing id), driver display name + iRacing customer id, date and time (UTC), RaceVisor version, hashed IP (rate limiting). Never laps or telemetry.
Track Pioneer credit is an acknowledgement only. Being listed confers no rights, privileges, priority or additional support, compensation, or other consideration of any kind, and creates no relationship with the author beyond the listing itself. Participation is strictly opt-in. The author may withhold, correct or remove a credit at any time (errors, ineligible or abusive entries, removal requests). Full terms: LICENSE.md ยง4.
Community shapes are plain <track key>.v2.json files in Documents\RaceVisor\trackmaps, identical to locally learned ones; pioneer credits are cached in _community_index.json there. A locally learned shape is never overwritten by a download.
Driver Chat (voice + text between RaceVisor users)#
Talk and type with other drivers without touching the sim's own voice or text chat - it works across sims, in practice, in a private league room, or while one of you is still in the menus. One driver hosts, the others join; the host relays everything. No RaceVisor server is involved and nothing is recorded or sent anywhere else.
Setting it up (once):
1. Add the Driver Chat (voice + text) widget to a layout (Layout Designer palette, or right-click the overlay โ Add widget). Size it like any widget. 2. Click โ on the widget: your name, the port (default 41777), microphone and speakers (pick the headset, or chat comes out of the monitor speakers), mic gain, volume, and optional auto-host / auto-join at launch. 3. Host: click Host. Give the others your address. Join: type the host's address (name-or-IP, or IP:port) and click Join.
Your address is on the widget, always. A Give friends: strip sits under the title and shows the addresses to read out, each already carrying your port - click any one to copy it:
| Chip | What it is | When to give it out |
|---|---|---|
| LAN | your address on this network | anyone in the same house or on the same LAN |
| Tailscale / ZeroTier / Hamachi | your mesh-VPN address, shown automatically when one of those is running | the easy way to play over the internet |
| WAN | your internet-facing address | only works if you forward the port on your router |
Adapters a friend could never reach are left out on purpose - VirtualBox and Hyper-V host adapters, Bluetooth, and any interface that failed to get an address. The strip re-checks itself every few seconds, so starting Tailscale or plugging in a cable mid-session just appears. Finding the WAN address means asking an outside service (checkip.amazonaws.com, then api.ipify.org); switch that off with โ โ Show my public IP in the widget and the LAN and VPN chips still work.
Reaching each other: on the same LAN, the host's local IP just works. Over the internet the easiest route is a mesh VPN - Tailscale, ZeroTier or Hamachi - which gives every PC an address the others can reach with no router changes. Otherwise only the host forwards the one TCP port on their router; the joiners need nothing.
If port forwarding just will not work, it is probably not your fault. Many ISPs put customers behind carrier-grade NAT (CGNAT), where your router's "public" address is shared with other customers and nothing you forward is reachable from outside. Mobile broadband and Starlink are almost always CGNAT; cable and fibre often are now too. How to tell: compare the WAN chip on the widget with the WAN/internet address on your router's own status page. If they differ - or the router shows something starting
100.64.through100.127.,10., or192.168.- you are behind CGNAT. The fix is the VPN route, which works regardless because both ends dial out rather than accept an incoming connection. Some ISPs will give you a real public address on request, occasionally for a fee.
While racing:
- Push-to-talk - hold Num 0 (rebind it to a wheel button in the Hotkey Editor; the binding accepts a controller button like every other one). The mic lamp on the widget turns green while you are being sent.
- Open mic - Ctrl+M or the widget's Open mic toggle: transmit continuously.
- Text - Ctrl+T (or the ๐ฌ Icon Bar icon) focuses the text box even in clickthrough: the overlay flips to interactive so you can type, Enter sends, Esc cancels, and it flips back to clickthrough on its own (โ โ Back to clickthrough after Enter / Esc). Incoming messages also show in the status line so you see them with the widget off-screen (โ โ Flash incoming text).
- Mute - the widget toggle or its (unbound) hotkey silences everyone for you. The ๐ next to each name mutes just that driver, for you only.
- The roster on the right shows who is in the room; a green dot lights while someone talks; a short two-note cue plays on join / leave (โ turns it off).
Audio: 16 kHz mono voice, sent only while transmitting - a talker costs about 16 kB/s. The mic level meter on the widget moves even when you are not transmitting, so you can check the right mic is selected before anyone joins. Leaving the room releases the microphone.
Wheel buttons: in the Hotkey Editor, every Driver Chat action can take a controller button as well as a key, exactly like the layout hotkeys - push-to-talk on a wheel button is the natural setup in VR.
Security - read this before port-forwarding#
A driver who forwards the chat port is exposing a service to the internet, so Driver Chat carries the same layers as the author's JVNC remote desktop, scaled to a chat room. All are in the widget's settings, and all are on by default except approval and the allow list.
The honest summary. Best: put everyone on a VPN (Tailscale, ZeroTier, Hamachi) and never open a router port - the room is then unreachable from the internet regardless. If you must port-forward: keep encryption on and set a room password. With both, a stranger who finds the port gets a TLS handshake, then a password challenge they cannot pass, then a 15-minute ban.
| Layer | What it does |
|---|---|
| Room password | One password for the room. The host stores only a PBKDF2-SHA256 verifier (100 000 iterations, random salt); joiners keep their copy encrypted with Windows DPAPI for their own account. On join the host sends a salt and a random nonce and the joiner answers with an HMAC of them - the password never crosses the network and a captured exchange cannot be replayed. |
| Encryption (TLS 1.2 / 1.3) | Voice, text and the password proof are encrypted. The host's self-signed certificate is created on first use; the widget and settings show its fingerprint. Joiners pin it on first connect (trust on first use) and are refused with a loud warning if it ever changes - either the host regenerated it, or someone is in the middle. Forget pinned hosts in settings resets that, and only then. |
| Public-address rule (default on) | With no room password, only LAN / VPN / Tailscale addresses can join; internet addresses are refused. So a forgotten port-forward can never expose an open room. |
| Lockout (always on) | 5 wrong passwords from one address = 15-minute ban, and every wrong password costs a second. Brute force dies. |
| Approve each join | The host sees "X wants to join" with Allow / Deny in the widget's roster (works in VR); the joiner waits up to 45 s. |
| Allow list | Optional IPs / networks that may connect at all - 192.168.1.0/24, 100.64.0.0/10 (all Tailscale). Everyone else is dropped silently, before the greeting. |
What it does not do: RaceVisor's protocol code is small and reviewed, not independently audited; a joiner who knows the password is inside the room and hears everything; and nothing here protects the sim's own comms, only Driver Chat. Both sides need the current RaceVisor - an older build cannot join a secured room and says so.
Hover tooltips#
Everything shows a tooltip on hover (icons by name; widgets show the drag/resize/right-click hints). Learned the app? Turn them off: SET โ "Show hover tooltips in the overlay."
Resource cost in tooltips: hovering a widget in interactive mode also shows its live CPU draw cost โ cost: 0.31 ms/frame ยท 18% of overlay ยท medium โ so you can see which widgets are heavy (rating: low < 0.15 ms, medium < 0.5 ms, HIGH above). Segmented rpm bars, a rotating track map, and the timing tower are the usual heavyweights.
System requirements#
| Minimum | Nominal (recommended) | Preferred | |
|---|---|---|---|
| OS | Windows 10 64-bit (21H2+) | Windows 11 | Windows 11 |
| CPU | Quad-core (i5-8400 / Ryzen 5 2600) | 6โ8 cores (i5-12400 / Ryzen 5 5600X) | 8+ cores (i7-13700 / Ryzen 7 7800X3D / Ryzen 9) |
| RAM | 8 GB | 16 GB | 32 GB+ |
| GPU | Any DirectX 11 GPU, 2 GB VRAM | GTX 1660 / RTX 2060 class | RTX 3070+ (RTX 4080/4090 for VR at max) |
| Storage | 300 MB free | 1 GB (recordings grow) | NVMe SSD, 10 GB+ for videos/telemetry |
| Display | 1080p monitor | 1440p or second monitor for the dashboard | Quest 3 / PC-VR + OpenKneeboard, or triple screens |
| Overlay refresh | 30 Hz (โก Low power) | 60 Hz | 120 Hz |
| Also | iRacing installed; .NET 10 runtime (bundled) | + OpenKneeboard for VR | + OBS Studio for streaming/recording control |
The overlay itself is light โ measured โ2% of a 12-core Ryzen 9 at 60 Hz (about half a thread), 10โ20% of a quad-core. iRacing's own requirements dominate; anything that runs iRacing comfortably runs RaceVisor at Nominal.
Performance / Low power#
The overlay is light (โ2% of a 12-core Ryzen at 60 Hz โ half a thread), but that same work is ~10โ20% of a modest quad-core. SET โ Overlay refresh throttles render + poll together; the โก Low power (30 Hz) button halves the work with no readability loss. Rotating/chase track maps rebuild their geometry every frame โ switch the map to north-up on weak machines.
Media widget#
| Button | Action |
|---|---|
| โ REC / โ STOP | Record MP4 (screen + overlay, H.264 + AAC) โ Documents\RaceVisor\videos |
| SHOT | Screenshot โ Documents\RaceVisor\screenshots |
| SCR: 1 / ALL | Capture primary monitor or all monitors |
| SET | Recording settings: fps, bitrate, resolution cap, audio source, overlay refresh rate, cursor size, YouTube setup |
| YT โ | Upload latest recording to YouTube as private โ title/description/tags pre-filled from the session (track, car, finish position, best lap, conditions). Review dialog: edit anything or just hit Upload. One-time OAuth setup via SET โ "Setup guide โ". |
| Transport row | Open/play/seek recordings in-overlay; bottom row drives the iRacing replay itself |
The Media widget can stay clickable even in clickthrough mode (hover it - it is a "hot island").
Hot zones now ship OFF. They were catching clicks meant for the sim underneath - a click on AMS2's DRIVE button, and getting on track in Assetto Corsa, both went to the overlay instead of the game. Turn them back on in Media settings -> Hot zones if you actually drive the Media, OBS or Icon Bar widgets from inside clickthrough; leave them off otherwise and use interactive mode (F12) for those widgets.
Ctrl+R is NOT video โ it records telemetry data for replay analysis. Video is the REC button.
Replaying iRacing's own telemetry (.ibt)#
iRacing writes its own telemetry file when you press Alt+L in the car (or always, if Options โ Misc โ Auto-log telemetry is on): a .ibt in Documents\iRacing\telemetry, every channel at the sim's full 60 Hz, plus the session info โ track, car, driver names. It is the same file MoTeC i2, Garage 61, VRS and the other analysis tools read.
RaceVisor plays those files straight through the dash: Ctrl+O, pick the .ibt, and every widget runs off it exactly as it did live โ loops at the end, Ctrl+O stops. The status line shows โถ replay โ <file>. Nothing is converted or written; the file is memory-mapped read-only.
Two ways to make one from RaceVisor's side, both iRacing only:
- The
.ibthotkey (unbound by default; bind it in the Hotkey Editor, ideally to a wheel button) starts and stops iRacing's disk logging from the overlay. It is the sim's own Alt+L sent over the official broadcast channel โ RaceVisor does not write the file, iRacing does. While the sim is writing, the status line shows โ iRacing .ibt. - Ctrl+R still records RaceVisor's own compact
.jsonl.gz(about 15 Hz, works in every sim, not just iRacing). Use.ibtwhen you want full-rate data or a file other tools can open.
A file the sim is still writing can't be opened yet โ stop logging first (Alt+L again, or the hotkey) and it appears on disk complete.
Works offline too: while the iRacing service is down for maintenance, its Demo Drive still writes .ibt files on Alt+L, and RaceVisor plays them the same way (verified 2026-09-09).
VR (OpenKneeboard)#
- Start order: OpenKneeboard โ RaceVisor โ iRacing
- Auto tab switching: with capture tabs named
iRacing Dash,Layout Designer, andRaceVisor - Hotkeys & Controllers, the kneeboard flips to the Designer or Hotkey Editor the moment you open them and back to the overlay when you close them. Works with stock OpenKneeboard (uses its official remote control) โ no modified OKB needed. Renamed your tabs? Match them inDocuments\iRacing\irDash_media.json(OkbTabOverlay/OkbTabDesigner/OkbTabHotkeys). - The drawn cursor is the only cursor you get in VR. It is baked into the overlay's pixels so the kneeboard shows it, and since 2026-09-08 the Layout Designer and Hotkey Editor windows draw the same cursor over themselves, so they are pointable in the headset too - before that they were blank pages in VR because a window capture carries no pointer. All three follow the same Media settings switch and size. iRacing's own pointer cannot help you here: the kneeboard is composited over iRacing, so the moment the pointer reaches the dash it is hidden behind it. Size it for VR in Media settings -> Cursor size: the range goes to 64 and the default is 16. The old default of 6 works out to roughly 4 pixels at kneeboard scale - invisible (fixed 2026-08-27). It draws as a ring plus a crosshair with a black halo, so it stays readable over a bright livery or a busy panel.
- The "RaceVisor" header bar and clock footer you may see in VR are OpenKneeboard's, not ours โ turn them off in OKB Settings โ Advanced โ In-Game Interface
- Kneeboard Position widget - real sliders for everything OpenKneeboard's VR pose has: left/right, eye height, forward, pitch, yaw, roll, width, height. Dragging writes straight into OKB's own settings (
Views.json, backed up once as.racevisor-backup; Original restores it).
Every position is measured from your eyes - specifically from where your head was at the last recenter, which OpenKneeboard treats as 0,0,0. So 30 cm / 11.8 in ahead means exactly that, in front of your eyes. Distances are shown in both centimetres and inches (feet and inches past a foot). Recenter while seated in your driving position - recenter while leaning in to the desk and every offset is wrong by that much.
The one thing to know: OpenKneeboard reads this pose only when it starts. It ignores the settings file while it is running, so dragging a slider changes nothing you can see, and Recenter just re-anchors the pose OKB already had in memory - which is why the kneeboard seems to land in the same place no matter what the sliders say. That is why Restart OpenKneeboard on Apply is on by default. Set your pose before you launch the sim. OpenKneeboard injects into the game at launch, so restarting it mid-session leaves you with no kneeboard at all until the sim restarts too.
Reset sliders puts everything back to OpenKneeboard's default pose - 30 cm / 11.8 in ahead, 20 cm / 7.9 in below eye level, tilted back 19 degrees, 40 x 75 cm - and applies it. That is the rescue when you have dragged the kneeboard somewhere you can no longer find it. (It deliberately does not zero every slider: 0,0,0 is your eyeballs, which would bury the kneeboard in your face.)
Snap (on by default) notches every slider at its centre (position and angles) or OKB's default (width/height); off = fully free.
- Recenter - button on that widget, and a Recenter kneeboard icon you can add to any Icon Bar. Same as OKB's own recenter binding: the kneeboard's origin moves to where your head is.
- Kneeboard on / off - show or hide the kneeboard itself without closing OpenKneeboard, so you can park it after a layout tweak and bring it straight back. Three ways: the On / off button on the Kneeboard Position widget, the Kneeboard on / off Icon Bar icon, or Hotkeys & Controllers -> "Kneeboard on / off" (global and unbound by default, so bind it to a wheel button and it works while the sim has focus). It sends OpenKneeboard's own TOGGLE_VISIBILITY, so it is the same thing as OKB's own show/hide binding.
- Recentering the sim and the kneeboard together (recommended setup). Pick one wheel button and bind it in all three places: 1. iRacing โ Options โ Controls โ Reset VR view 2. RaceVisor โ Hotkeys & Controllers โ Recenter kneeboard (unbound by default; it is global, so it fires while the sim has focus, and it flashes a confirmation) 3. OpenKneeboard โ Settings โ Input โ Recenter One press then recenters everything. Binding both 2 and 3 is deliberate, not a mistake: recentering is idempotent - it moves the origin to wherever your head is now, so firing it twice lands in exactly the same place - and having both means it still works when RaceVisor is closed, or if one of the two misses the button press. The headset's own recenter (the Meta button) can't be caught by anything outside the runtime, so it will never bring the kneeboard along - use the wheel button instead.
- Fade the overlay out / in, fast (~120 ms). Bindable to a key or wheel button in Hotkeys & Controllers ("Fade overlay out / in", global, unbound by default), and available as a Fade icon for any Icon Bar. It fades the whole overlay, live WPF panels included.
- Look-down fade (Media settings): tick Fade the overlay out when I look down and set the angle (5-80 degrees, default 35). Look further down than that and the overlay fades out; it comes back 5 degrees before the threshold, so it cannot flicker on the boundary. Needs SteamVR running - RaceVisor reads the headset pose through OpenVR in background mode. It does not have to be your OpenXR runtime, but with SteamVR closed the feature simply does nothing.
- Follow head: + vertical - the toggle next to Follow head. OpenKneeboard's recenter re-anchors yaw and horizontal position only, so height is followed separately by writing the eye-height offset (gated at 1 cm, so a still head writes nothing). Same SteamVR requirement.
- Follow head (on the Kneeboard Position widget) - keeps recentering ~15x a second so the kneeboard rides along with your head (position and yaw). OpenKneeboard has no native head-locked mode; this is the closest thing, good for a heads-up layout, wrong for a knee-mounted one.
- Recording or streaming the dash from VR - OpenKneeboard draws into the VR compositor's output, not into iRacing's own window, so a capture pointed at the sim's desktop window shows the race with no dash on it, every time. Capture the runtime's mirror window instead: with SteamVR as the OpenXR runtime, open SteamVR menu โ Display VR View, full-screen it on your biggest monitor (a window capture records at the window's on-screen size), and in OBS use Window Capture โ
[vrmonitor.exe]: VR Viewwith Capture Method Windows 10 (1903 and up). That window only exists while VR View is open, so it has to be re-picked in OBS each session. - Bind a wheel/keyboard button in OKB Settings โ Input to show/hide the kneeboard
- Position/size the panel in OKB Settings โ Virtual Reality (raise Y if you only see the bottom of the overlay)
Capturing the VR view - troubleshooting#
| Symptom | Cause and fix |
|---|---|
| Capture shows iRacing but no dash | OpenKneeboard is drawn by the VR compositor, on top of what the sim submits - it is never inside iRacing's own window. Capture SteamVR's VR View mirror instead. |
| "VR View" missing from OBS's window list | That window only exists while it is open. Open SteamVR menu -> Display VR View first, then pick it in OBS - and re-pick it each session, because it leaves the list when SteamVR closes. |
| Capture shows the SteamVR Status window | Both windows belong to vrmonitor.exe. Set the source's Window Match Priority to Window title must match. |
| Capture shows your desktop / whatever is on top | Capture Method is on Auto (BitBlt). Set it to Windows 10 (1903 and up). |
| Recording is entirely black | In order: wrong source (not the VR View window); OpenXR runtime is not SteamVR, so the session never reaches its compositor; headset asleep - iRacing stops rendering when the proximity sensor sees nothing (black with the dash floating on it means exactly this). |
| Dash missing in the headset, not just the capture | OpenKneeboard must be running before the sim starts, the sim must be on the OpenXR path (not OpenVR), and OpenKneeboard must be on the tab capturing RaceVisor. |
| Recording blurry though the dash is visible | A window capture records at the window's on-screen size. Full-screen the VR View on your biggest monitor, then in OBS: Transform -> Reset, Fit to Screen, Scale Filtering -> Lanczos. |
Files & folders#
| What | Where |
|---|---|
| Layouts (yours + presets) | Documents\RaceVisor\layouts |
| Track map cache (learned + community) | Documents\RaceVisor\trackmaps (_community_index.json = pioneer credits) |
| Videos / screenshots | Documents\RaceVisor\videos, โฆ\screenshots |
Telemetry recordings โ RaceVisor .jsonl.gz and iRacing's own .ibt | Documents\iRacing\telemetry |
| Hotkeys | Documents\iRacing\irDash_hotkeys.json |
| Driver Chat settings (name, port, devices) | Documents\RaceVisor\driver-chat.json |
| Media, YouTube + Community Track Library settings | Documents\iRacing\irDash_media.json |