LÖVR: a Lua framework for VR that starts with one file
Lua Virtual Reality Framework
At a glance
- What is it?
- LÖVR is a C11 and LuaJIT framework for building 3D games and VR experiences that run on OpenXR headsets. It is small, scriptable and deliberately minimal, which makes it a good fit for prototypes and a poor fit for teams that need a full editor.
- Who is it for?
- Adopt LÖVR if you want to write VR scenes as Lua scripts and are comfortable reading the documentation at lovr.org rather than clicking through an editor. Skip it if your project depends on a visual scene graph, a built-in asset pipeline or a large plugin ecosystem, because the README lists none of those.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Who LÖVR is aimed at, and what it replaces
LÖVR targets people who want a 3D or VR scene running quickly and are willing to write it in Lua. The README describes it as "a simple Lua framework for rapidly building 3D games and VR experiences", and the examples back that up: a spinning cube is one function call, a hand-tracking demo is a loop over lovr.headset.getHands(). There is no scene editor, no prefab system and no project wizard. You write main.lua and run it.
That places it against two different neighbours. On one side sit full engines where scenes are assembled in a GUI and scripting is an add-on. On the other sit general-purpose Lua runtimes such as LÖVE, which the README credits as the main inspiration but which is a 2D framework. LÖVR takes the LÖVE model of a small runtime plus a callback table and points it at headsets, with stereo rendering, spatialized audio and rigid body physics already included. If your work is a VR prototype, a research demo or a tool that needs to render in a headset, the loop from idea to running build is short. If your work needs artists iterating in an editor, this is not that tool.
The callback table, the render pass and the headset module
The architecture visible in the README is a callback table named lovr. You define functions such as lovr.load and lovr.draw, and the runtime calls them. lovr.draw receives a pass object, and drawing goes through it: pass:text, pass:cube, pass:sphere, pass:draw. That pass is where the single-pass stereo rendering happens, so the same draw call lands in both eyes without you writing the loop.
Device input funnels through lovr.headset. The hand-tracking example queries lovr.headset.getHands() and then lovr.headset.getPosition(hand) for each hand, which returns a position that can be wrapped in vec3 and handed to a sphere. That vec3 comes from the built-in vector library, which also covers quaternions and matrices. Assets are loaded through lovr.graphics.newModel, shown with a glTF file path, and the README lists compressed textures, cubemaps, fonts and skeletal animation as supported import types. Physics is JoltPhysics with 7 collider shapes and 6 joint types; audio spatialization is SteamAudio with HRTFs, audio meshes and reverb. The C11 core plus LuaJIT is what the README means by fast, and the whole framework is described as a couple of megabytes with modules that can be disabled or removed.
Installing LÖVR and running a first script
The README does not ask you to install anything for the normal path. It says to grab a copy of the executable from https://lovr.org/downloads, write a main.lua script, and drag it onto the executable. So the install step is a download, and the project's own instruction for getting started is the drag-and-drop gesture. Nightly builds for Windows are listed separately under Resources at https://lovr.org/download/nightly.
A first script can be as short as the Hello World example, which draws text one metre above the floor and three metres in front of the viewer:
function lovr.draw(pass)
pass:text('Hello World!', 0, 1.7, -3, .5)
endSave that as main.lua, drag it onto the executable, and the string should appear in the headset at eye height. The spinning cube example adds animation by passing the elapsed time as a rotation argument:
function lovr.draw(pass)
pass:cube(0, 1.7, -1, .5, lovr.timer.getTime())
endFor anything beyond a single file, the README points at the docs page and the Compiling Guide. Building from source uses CMake, and the README gives the three commands directly:
mkdir build
cd build
cmake ..
cmake --build .After that, tests live in test/lovr and run through the built binary, either the whole suite or one module at a time:
./build/bin/lovr test
./build/bin/lovr test dataWhere LÖVR stops short
The same minimalism that makes the first five minutes pleasant becomes a constraint later. There is no editor in the repository layout, and the README does not describe one, so level layout, material authoring and asset organisation are your problem. The README also does not document rollback, hot reloading of scripts, or a debugging story beyond the test runner, and it says nothing about how to package a finished build for distribution. You should assume those gaps exist until the documentation at lovr.org says otherwise.
Device support is another boundary. The README states that LÖVR supports any headset that works with OpenXR, which is broad but not universal: a headset whose runtime does not expose OpenXR is out of scope. A keyboard and mouse VR simulator is mentioned for development without a headset, and Windows, macOS, Linux and Android are the listed platforms, so a console or an iOS-only target is not on the table. Finally, the release history is uneven. v0.18.0 arrived on 2025-02-15 and v0.19.0 on 2026-06-07, so upgrades can be far apart and a project pinned to an older release may wait a long time for a fix. The last push to the repository was on 2026-09-22.
How it compares with Love2D and with full VR engines
The closest relative is LÖVE, which the README names as the inspiration and which shares the callback-table style and the Lua scripting model. The difference is scope: LÖVE is a 2D framework, while LÖVR adds the pieces a headset needs, namely stereo rendering through the pass object, headset and hand tracking through lovr.headset, spatialized audio through SteamAudio and 3D rigid body physics through JoltPhysics. Porting a LÖVE project upward is not a drop-in change, because the drawing API and the input model are different.
The other comparison is with engines that ship an editor and a content pipeline. Those give you a visual scene graph and a large library of third-party plugins, at the cost of a heavier runtime and a longer path from a clean machine to a running headset build. LÖVR's answer is to keep the framework at a couple of megabytes and let you delete modules you do not use. That is a real trade: you get a small surface to learn, and you give up the tooling that a team of artists would expect.
Licence and the cost of staying current
LÖVR is MIT licensed, with the LICENSE file at the repository root. That is permissive and places few conditions on reuse, but the README's licence section covers the framework only. The repository contains a deps/ directory, and the README states that LÖVR includes JoltPhysics and uses SteamAudio, both of which are third-party components with their own terms. Anyone shipping a commercial build should read those licences separately rather than assuming the MIT header applies to everything in the tree. This is not legal advice.
On maintenance, the last push to the dev branch was on 2026-09-22, so the repository is not dormant. The release cadence is the thing to plan around: 2025-02-15 for v0.18.0 and 2026-06-07 for v0.19.0, with v0.17.1 before that on 2024-03-12. If you build from source you can follow the dev branch instead of waiting for a tagged release, and the README's CMake steps plus the Compiling Guide are the whole upgrade procedure. If you ship a compiled binary to users, you own the rebuild for each platform you support, and the README lists four.
Editorial conclusion
Adopt LÖVR if you want to write VR scenes as Lua scripts and are comfortable reading the documentation at lovr.org rather than clicking through an editor. Skip it if your project depends on a visual scene graph, a built-in asset pipeline or a large plugin ecosystem, because the README lists none of those. Before committing, open the Compiling Guide, build from source with CMake on your target platform, and confirm your headset is covered by OpenXR rather than a vendor-specific runtime. The MIT licence keeps the code reusable, but the vendored dependencies under deps/ carry their own terms and need a separate read.
Frequently asked questions
What is LÖVR and what is it used for?
LÖVR is a Lua framework for building 3D games and VR experiences, written in C11 and scripted with LuaJIT. It runs on Windows, macOS, Linux and Android and supports any headset that works with OpenXR.
How do I install LÖVR?
The README does not describe an installer. It says to download the executable from https://lovr.org/downloads, write a main.lua script, and drag that script onto the executable. Nightly Windows builds are listed at https://lovr.org/download/nightly.
Can I use LÖVR without a VR headset?
Yes. The README lists a keyboard and mouse VR simulator among the features, alongside support for any headset that works with OpenXR.
How do I build LÖVR from source?
The README gives the CMake steps: create a build directory, run cmake .. and then cmake --build . . The Compiling Guide at lovr.org/docs/Compiling has more detail, and tests are run through the built binary with ./build/bin/lovr test.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bjornbytes-lovr)