Skip to content

Window - #1007

Open
bjornbytes wants to merge 1 commit into
devfrom
window
Open

Window#1007
bjornbytes wants to merge 1 commit into
devfrom
window

Conversation

@bjornbytes

@bjornbytes bjornbytes commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Window

This adds support for OpenXR's new XR_EXT_spatial_container extension, which is basically a way for apps to create windows in VR.

Windows can be both 2D panels and 3D boxes, and they can contain regular 3D content or 2D Layer objects.

Note that this is still a proof of concept. It hasn't been tested on a real runtime yet, and the API is subject to change.

API

Spatial containers are exposed as a new Window object. You can create a window and optionally give it a size:

window = lovr.headset.newWindow(width, height, depth)

Once you have a window, you can query things about it, like its position, size, and whether it's visible, focused, or fullscreen:

window:getPosition() --> x, y, z of the center of the window
window:getOrientation() --> angle, ax, ay, az
window:getPose() --> x, y, z, angle, ax, ay, az

window:getWidth()
window:getHeight()
window:getDepth()
window:getDimensions() --> width, height, depth

window:isVisible()
window:isFocused()
window:isFullscreen()

You can request that the runtime show/hide the window, or make it fullscreen. These are just requests, the runtime doesn't have to listen to you (although hiding a window will always succeed).

window:setVisible(visible)
window:setFullscreen(fullscreen)

To render stuff to a window, you can get its Texture or a Pass that renders to its texture.

window:getTexture()
pass = window:getPass() --> will automatically have canvas/cameras configured

-- draw to the window's render pass
pass:cube()

You can manually fetch the camera info for the window as well, just like lovr.headset.getViewPose and lovr.headset.getViewAngles. However, the view angles will be "shrinkwrapped" around the window's bounds, so you won't waste time rendering things outside the window.

window:getViewPose(view) --> x, y, z, angle, ax, ay, az
window:getViewAngles(view) --> left, right, up, down

You can give windows a background and Layer objects, similar to the corresponding methods on lovr.headset:

window:getLayers() --> returns a table of layers
window:setLayers({Layer, main = boolean}) --> sets layers, enables/disables the main layer
window:setBackground(texture) --> can be nil or a cubemap/equirect texture

Finally, if you're done with a window, you can close it. Once you close a window, it won't show up anymore, and its methods will generally return empty data or behave like noops:

window:close()
window:isOpen() --> false if window has been closed

Certain events are extended to report changes to windows as well:

lovr.focus(focused, display) --> display can be a Window now
lovr.visible(visible, display) --> display can be a Window now
lovr.resize(width, height, depth, window) --> depth + Window indicate a Window resized

Default Window

LÖVR places the existing scene in a "default" window.

window = lovr.headset.getWindow()

The default window works even if the runtime doesn't support spatial containers -- LÖVR emulates the window functionality on top of regular OpenXR APIs. Certain top-level lovr.headset functions behave the exact same as calling the corresponding methods on the default window:

lovr.headset.isVisible() --> defaultWindow:isVisible()
lovr.headset.isFocused() --> defaultWindow:isFocused()
lovr.headset.getViewPose() --> defaultWindow:getViewPose()
lovr.headset.getViewAngles() --> defaultWindow:getViewAngles()
lovr.headset.getTexture() --> defaultWindow:getTexture()
lovr.headset.getPass() --> defaultWindow:getPass()
lovr.headset.setBackground() --> defaultWindow:setBackground()
lovr.headset.getLayers() --> defaultWindow:getLayers()
lovr.headset.setLayers() --> defaultWindow:setLayers()

This ensures that existing apps will behave the same way even when windows are enabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant