- Undeprecate ShaderType (it's good actually, kinda like a pipeline bind
point and more specific than having lovr trying to make sense of a
random set of stages).
- Use a default uniform block instead of push constants. The Constants
macro now maps to a uniform block declaration.
- It is no longer possible to create a shader by giving a single
DefaultShader string (you can still give a per-stage DefaultShader
though).
- lovr.graphics.compileShader now takes all stages instead of a single
stage. In general we need all stages when compiling GLSL because
default uniforms require linking across stages.
Goal is to support more combinations of shader stages, both for
vertex-only shaders and mesh/raytracing shaders in the future. In
general most of the logic that conflated "stage count" with "shader
type" has been changed to look at individual shader stages.
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.
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.
- Add Buffer:newReadback
- Add Buffer:getData
- Buffer:getPointer works with permanent buffers
- Buffer:setData works with permanent buffers
- Buffer:clear works with permanent buffers
- Add Texture:newReadback
- Add Texture:getPixels
- Add Texture:setPixels
- Add Texture:clear
- Add Texture:generateMipmaps
- Buffer readbacks can now return tables in addition to Blobs using Readback:getData
Tally is coming back soon with an improved API, it's temporarily removed
since it made the transfer rework a bit easier.
Note that synchronous readbacks (Buffer:getData, Texture:getPixels)
internally call lovr.graphics.submit, so they invalidate existing Pass
objects. This will be improved soon.
- Pass:mesh accepts tables for vertices/indices
- Add Pass:setVertexFormat to set format used for table-based meshes
- Pass:send accepts tables for buffers
- Pass:send supports arbitrarily nested structs/arrays for push constants
- Buffer formats support arbitrarily nested structs/arrays
- Zero-length buffers are valid and represent structs
- Fields can have names using 'name'
- Field types can be tables of other fields (structs)
- Fields can have 'length' key
- newBuffer syntax has been changed to put format first (old version
still works)
- Buffers can be created from shader variables, avoiding need to declare
matching format.
- Pass:clear/Pass:read use byte offsets instead of indices
- Pass:copy uses byte offsets when copying a Buffer to a Buffer
- Deprecate lovr.graphics.getBuffer (tables can be used instead)
- Add helper functions for creating shapes to avoid duplication between
newShape and newShapeCollider.
- Add lovr.physics.newMeshShape and lovr.physics.newTerrainShape
- Register TerrainShape so it has all the base Shape methods
- Smooth out a few TerrainShape warnings
- They no longer live in temporary memory, but in a dedicated pool.
- There are error checks for using a temporary buffer after it's invalid
- However, these are imperfect, and could be improved. One idea is to
avoid recycling a temporary buffer until its refcount decays (i.e.
Lua finally decides to garbage collect it). This would explode
memory usage sometimes, so it could only be enabled when
t.graphics.debug is true.
A lot of clean up can happen now that C doesn't push delayed errors to
Lua. This was happening for Pico and WebVR, neither of which are used
anymore.
Also default vsync to true but force it off if VR is active.
They are now destroyed explicitly after tearing down the Lua state
instead of relying on finalizers. It's definitely annoying to make it
coordinated in a centralized way like this instead of being distributed,
but there's not really any reliabel way to ensure that graphics objects
are destroyed before the graphics module/device is destroyed, which is a
problem.