- rm :getTallyData, it's totally lame, just do a readback
- rm gpu_tally_get_data too, webgpu doesn't support it anyway
- Clamp tally copy count so it doesn't overflow buffer
- Tally buffer offset's gotta be a multiple of 4
- Return nil instead of 2 values when tally buffer isn't set
- Copy correct number of tallies (multiply by view count instead of max
view count)
- Skip occlusion queries entirely if no tally buffer was set
Quat:mul also takes numbers.
They both require 3 args when using numbers.
I didn't opt for the 4-component Mat4:mul(numbers) variant, mostly out
of laziness.
Co-Authored-By: Josip Miskovic <josipmiskovic@gmail.com>
They defaulted to 1 to avoid confusion when mipmaps weren't generated
during a render pass (withou the { mipmaps = true } flag), but now the
mipmaps flag is obsolete and render passes automatically generate
mipmaps for all levels in their texture views. This means that render
passes can have mipmaps by default again, which leads to better
appearance when sampling them later.
Currently I don't think there's a way for plugins to use JNI, because they
have no way to access the JavaVM or JNIEnv pointers. JNI_OnLoad is only
called for native libraries loaded by Java, and the plugin library has
no way of loading liblovr.so or accessing its symbols because the
library is inside the APK. This change emulates JNI_OnLoad as a means
of smuggling the JavaVM over to plugins before they're loaded. On
Android API level 31, the JNI_GetCreatedJavaVMs function was exposed on
Android, so that may be an alternative for plugins to use in the future.
- state.features.overlay should remain a bool since it just indicates
whether the extension is supported/enabled.
- split the config value into a bool/u32 pair so the full u32 range can
be used for the order (seems important to coordinate with other apps).
- Also you can use a boolean now like before, which uses 0 as the order.
It's useful. quat(lovr.headset.getOrientation()):direction() is
verbose, noob-unfriendly, and somewhat wasteful. I think this was
originally removed because something about not exposing the full
rotation basis.
The "vec3 is 4 floats" thing was consistently confusing to people. It's
reverted everywhere except for Curve.
maf now has full sets of methods for vec2/vec3/vec4, for consistency.
Vector bindings now use luax_readvec* helper functions for the
number/vector variants, and use maf for most functionality, which cleans
things up a lot.
- Adds Pass:setViewCull to enable/disable frustum culling.
- Renames Pass:setCullMode to Pass:setFaceCull (with backcompat).
Some stuff currently missing:
- Text is not culled, but should be.
- VR view frusta are not merged yet.
The radius is also included as the 4th number in the table,
but I think this was a mistake.
Not going to remove it yet, but maybe we can start to prefer reading it
from a string key.
Origin type used to be a query-able property of the VR system that
indicated whether the tracking was roomscale or seated-scale.
The t.headset.offset config value could be used to design an
origin-agnostic experience, which by default shifted content up 1.7
meters when tracking was seated-scale. That way, stuff rendered at
y=1.7m was always at "eye level". It worked pretty well.
It's getting replaced with a t.headset.seated flag.
- If seated is false (the default), the origin of the coordinate space
will be on the floor, enabling the y=1.7m eye level paradigm. If
tracking is not roomscale, a floor offset of 1.7m will be emulated.
- If seated is true, the origin of the coordinate space will be y=0
at eye level (where the headset was when the app started). This is
the case on both roomscale and seated-scale tracking.
So basically 'seated' is an opt-in preference for where the app wants
its vertical origin to be.
One advantage of this is that it's possible to consistently get a y=0
eye level coordinate space, which was not possible before. This makes
it easier to design simpler experiences that only need to render a
floating UI and don't want to render a full environment or deal with
offsetting everything relative to a 'floor'. This also makes it easier
to implement hybrid VR+flatscreen experiences, because the camera is at
y=0 when the headset module is disabled.
The opt-in nature of the flag, coupled with the fact that it is
consistent across all types of tracking and hardware, is hopefully a
more useful design.
You can do lovr.headset.getPose('floor') to get the offset of the stage
relative to the local origin if you want to draw something at the center
of the play area.
Also lovr.headset.isTracked('floor') basically tells you if it's roomscale.
- rm Pass:getTallyCount. It's unclear if this reports the current tally
count, or the number of tallies in the last submit. lovr was even
getting this confused internally (fixed).
- rm tally index argument from Pass:beginTally and Pass:finishTally.
The tally index is now an autoincremented value managed internally,
and both :beginTally/:finishTally return it. If someone wants to use
their own indices, a lookup table can be used to do the mapping.
- lovr.headset.getPassthrough returns current passthrough mode
- lovr.headset.setPassthrough sets the passthrough mode
- nil --> uses the default passthrough mode for the headset
- bool --> false = opaque, true = one of the transparent modes
- string --> explicit PassthroughMode
- lovr.headset.getPassthroughModes returns a table of supported modes
Creates a lightweight copy of a Model, for situations where a single
model needs to be rendered with multiple poses in a single frame, which
is currently not possible.
Enables automatic CPU/GPU timing for all passes. Defaults to true
when graphics debugging is active, but can be enabled/disabled manually.
When active, Pass:getStats will return submitTime and gpuTime table
keys, respectively indicating CPU time the Pass took to record and the
time the Pass took to run on the GPU. These have a delay of a few
frames.
This doesn't include a way to get "global" timing info for a submit.
This information would be useful because it doesn't require lovrrs to
sum all the timing info for all the passes and it would include other
work like transfers, synchronization, and CPU waits. However, this is
more challenging to implement under the current architecture and will be
deferred to later. Even if this were added, these per-pass timings will
remain useful.