To make room for two more 16-bit skinning-related values in the
PhongDrawUniform -- joint offset for multidraw and per-instance joint
count for instancing.
Originally I made those full 32 bits because I wanted to provide an
option to have a 64-bit light mask there instead of an offset + count.
But the mask is not really driver-friendly as going over the bits and
skipping zeros was behaving like if each pixel was affected by 64 lights
-- an absolute perf nightmare. I might reconsider this again later, but
for now that doesn't seem to make sense, and I need to put the
skinning-related info somewhere without inflating the per-draw uniform
by another 16-byte vector.
The main property of this feature is that it prints the bounds *in a
canonical type*, not of the actual type that's used. Yet however that
wasn't ever tested. Now it is, and it's also testing behavior for custom
attributes, which don't get their bounds printed (because the canonical
type isn't known for those).
To be clear -- it would work even without, as it'd fall back to
calculating the range of the weights attribute and choosing an epsilon
based on that, but now it takes a shortcut as Weights are known to be in
a [0, 1] range.
This is the first builtin array attribute, with one of the objectives
being an ability to support an arbitrary count of per-vertex weights in
a single contiguous attribute without the complexity of having to go
through several four-component attributes.
On the shader side it still needs to get cut into at most four
components per attribute, but there's no reason for such limitation to
get propagated here as well.
Co-authored-by: Vladimír Vondruš <mosra@centrum.cz>
Note that the order is *reversed* compared to the originally reserved
attribute IDs. This is because the "joint <id> has <weight>" order
feels more natural and consistent than "<weight> is assigned to joint
<id>".
Co-authored-by: Vladimír Vondruš <mosra@centrum.cz>
Finally got an idea how to provide various options store these
efficiently, so it's implemented now. Five different storage variants
times four different type sizes.
With the upcoming string field support, field<UnsignedShort>() will be
allowed to peek into SceneFieldType::UnsignedShort, but also
SceneFieldType::StringOffset16 or
SceneFieldType::StringRangeNullTerminated16. Most types still have a 1:1
mapping, which is why this delegates to the existing
SceneFieldTypeFor<T> trait (which is also still needed to autodetect the
SceneFieldType in a SceneFieldData constructor), but certain type will
be able to provide a specialized handling.
These APIs are mostly just for debugging purposes, not widely used, so
it doesn't make sense to have them as constexpr in the header. (Plus the
returned void view is useless in a constexpr context anyway.)
This header size is getting out of hand, so every stripped bit counts.
Also now that they're no longer constexpr, I can go back to using
regular assertions. The reinterpret_cast<> wasn't needed either.
Those were originally named set*Buffer(), but in the process of
finishing up ef9da0ec96 got changed to
bind*Buffer() to avoid a false impression that the buffer stays bound to
the shader instance forever (which it doesn't, same as with textures).
However the documentation didn't get updated, apparently.
A considerable chunk of the docs mentioned that there has to be one
ProjectionUniform3D per draw. Probably a copypaste error from the case
where there's a combined TrannsformationProjectionUniform3D, which *is*
one per draw. Sorry for the confusion.
There was also quite a lot of documentation content referencing the old
deprecated constructors. Fixed now.
I'm not sure why this restriction was there as nothing was preventing
them from being used. The attribute is only accessible through the
typeless attribute(), which gives back
`Containers::StridedArrayView2D<const char>` with second dimension size
being set to the full stride. And there it doesn't matter if the format
is an array or not.
This will be useful for joint IDs and weights, for example doing crazy
things like packing the IDs into an array of 8 4-bit numbers, saving
half the memory compared to the smallest builtin representation using
UnsignedByte[8].
A lot of pain went into creating owned mesh data even though it was
completely unnecessary in retrospect. Originally I thought "let's not
use any advanced feature" but the verbosity is just not worth it.
In the recent-ish SceneData tests I went with non-owned data already,
and it was much simpler. It's a learning process even for using my own
APIs, huh.
What's especially nice is that the code snippets no longer need to
describe that there's "2 lights, 3 materials and 5 draws" because now
it's self-documenting.
Because it was no longer bearable with three UnsignedInt arguments in a
row, especially when some of them are only available on a subset of
platforms. And it would get even worse with introduction of planned
features such as multiview or skinning.
Backwards compatibility is in place, as always. To ensure nothing
breaks, this commit still has all tests and snippets using the old API.