Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend skinning for >4 bones per vertex #6772

Merged
merged 31 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5e50a8f
Add skinning and morphing samples to check functionality
Apr 13, 2023
9f01fab
Implement skinning for more than four bones pair vertex
Apr 13, 2023
3afccd4
Change std::vector to utils::FixedCapacityVector
Apr 26, 2023
7a54399
Minor changes according to the PR revision process
Apr 27, 2023
8e3e04b
Fix setting of bone indices and weights for skinning
May 3, 2023
c5263f1
Simplify API and fix memory operations
May 4, 2023
1d171ea
Fix formatting and small changes according reviews
May 9, 2023
f5900e2
Clean the code
May 11, 2023
a7f2482
Fix memory operations
May 12, 2023
c95ef89
Update advanced skinning API
May 25, 2023
ae9c951
Change ushort to uint16_t
May 30, 2023
9185de5
Fix memory allocation
Jun 6, 2023
7faf016
Fix memory management
Aug 9, 2023
9f1c40c
Fix memory allocation for skinning data
Aug 28, 2023
08b56aa
Small fix: replace transform to memcpy
Aug 29, 2023
4098bbb
Small corrections based on reviews
Aug 30, 2023
0ca2928
Commit after rebase
fvbj Sep 4, 2023
3b86828
Merge branch 'main' into skinning
fvbj Sep 8, 2023
682479d
Merge branch 'main' into skinning
fvbj Sep 18, 2023
bc600d4
Fix size of reserved bytes in RenderPass::PrimitiveInfo
fvbj Sep 18, 2023
37d5622
attempt to fix build breakage
pixelflinger Sep 19, 2023
658378f
Merge branch 'main' into skinning
pixelflinger Sep 19, 2023
fe6b55d
add missing header
pixelflinger Sep 19, 2023
3d43cfe
Fix build-windows
fvbj Sep 19, 2023
0b7dfee
Fix build-windows, type conversion
fvbj Sep 19, 2023
0e4b5c2
attempt to fix windows build
pixelflinger Sep 19, 2023
cab989c
Merge branch 'main' into skinning
fvbj Sep 19, 2023
db5f0ff
attempt to fix windows build, uint removal
fvbj Sep 19, 2023
380d550
Merge branch 'main' into skinning
pixelflinger Sep 19, 2023
81a5b54
Merge branch 'main' into skinning
fvbj Sep 21, 2023
41cb6dd
Merge remote-tracking branch 'origin/skinning' into skinning
fvbj Sep 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEW_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).

## Release notes for next branch cut

- engine: add support for skinning with more than four bones per vertex.
- engine: remove `BloomOptions::anamorphism` which wasn't working well in most cases [**API CHANGE**]
- engine: new API to return a Material's supported variants, C++ only (b/297456590)
53 changes: 53 additions & 0 deletions filament/include/filament/RenderableManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <utils/compiler.h>
#include <utils/EntityInstance.h>
#include <utils/FixedCapacityVector.h>

#include <math/mathfwd.h>

Expand Down Expand Up @@ -349,6 +350,58 @@ class UTILS_PUBLIC RenderableManager : public FilamentAPI {
Builder& skinning(size_t boneCount, Bone const* bones) noexcept; //!< \overload
Builder& skinning(size_t boneCount) noexcept; //!< \overload

/**
* Define bone indices and weights "pairs" for vertex skinning as a float2.
* The unsigned int(pair.x) defines index of the bone and pair.y is the bone weight.
* The pairs substitute \c BONE_INDICES and the \c BONE_WEIGHTS defined in the VertexBuffer.
* Both ways of indices and weights definition must not be combined in one primitive.
* Number of pairs per vertex bonesPerVertex is not limited to 4 bones.
* Vertex buffer used for \c primitiveIndex must be set for advance skinning.
* All bone weights of one vertex should sum to one. Otherwise they will be normalized.
* Data must be rectangular and number of bone pairs must be same for all vertices of this
* primitive.
* The data is arranged sequentially, all bone pairs for the first vertex, then for the
* second vertex, and so on.
*
* @param primitiveIndex zero-based index of the primitive, must be less than the primitive
* count passed to Builder constructor
* @param indicesAndWeights pairs of bone index and bone weight for all vertices
* sequentially
* @param count number of all pairs, must be a multiple of vertexCount of the primitive
* count = vertexCount * bonesPerVertex
* @param bonesPerVertex number of bone pairs, same for all vertices of the primitive
*
* @return Builder reference for chaining calls.
*
* @see VertexBuffer:Builder:advancedSkinning
*/
Builder& boneIndicesAndWeights(size_t primitiveIndex,
math::float2 const* indicesAndWeights, size_t count, size_t bonesPerVertex) noexcept;

/**
* Define bone indices and weights "pairs" for vertex skinning as a float2.
* The unsigned int(pair.x) defines index of the bone and pair.y is the bone weight.
* The pairs substitute \c BONE_INDICES and the \c BONE_WEIGHTS defined in the VertexBuffer.
* Both ways of indices and weights definition must not be combined in one primitive.
* Number of pairs is not limited to 4 bones per vertex.
* Vertex buffer used for \c primitiveIndex must be set for advance skinning.
* All bone weights of one vertex should sum to one. Otherwise they will be normalized.
* Data doesn't have to be rectangular and number of pairs per vertices of primitive can be
* variable.
* The vector of the vertices contains the vectors of the pairs
*
* @param primitiveIndex zero-based index of the primitive, must be less than the primitive
* count passed to Builder constructor
* @param indicesAndWeightsVectors pairs of bone index and bone weight for all vertices of
* the primitive sequentially
*
* @return Builder reference for chaining calls.
*
* @see VertexBuffer:Builder:advancedSkinning
*/
Builder& boneIndicesAndWeights(size_t primitiveIndex,
utils::FixedCapacityVector<
utils::FixedCapacityVector<math::float2>> indicesAndWeightsVector) noexcept;
/**
* Controls if the renderable has vertex morphing targets, zero by default. This is
* required to enable GPU morphing.
Expand Down
13 changes: 13 additions & 0 deletions filament/include/filament/VertexBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,19 @@ class UTILS_PUBLIC VertexBuffer : public FilamentAPI {
*/
Builder& normalized(VertexAttribute attribute, bool normalize = true) noexcept;

/**
* Sets advanced skinning mode. Bone data, indices and weights will be
* set in RenderableManager:Builder:boneIndicesAndWeights methods.
* Works with or without buffer objects.
*
* @param enabled If true, enables advanced skinning mode. False by default.
*
* @return A reference to this Builder for chaining calls.
*
* @see RenderableManager:Builder:boneIndicesAndWeights
*/
Builder& advancedSkinning(bool enabled) noexcept;

/**
* Creates the VertexBuffer object and returns a pointer to it.
*
Expand Down
14 changes: 12 additions & 2 deletions filament/src/RenderPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@ void RenderPass::instanceify(FEngine& engine) noexcept {
lhs.primitive.skinningHandle == rhs.primitive.skinningHandle &&
lhs.primitive.skinningOffset == rhs.primitive.skinningOffset &&
lhs.primitive.morphWeightBuffer == rhs.primitive.morphWeightBuffer &&
lhs.primitive.morphTargetBuffer == rhs.primitive.morphTargetBuffer;
lhs.primitive.morphTargetBuffer == rhs.primitive.morphTargetBuffer &&
lhs.primitive.skinningTexture == rhs.primitive.skinningTexture ;
});

uint32_t const instanceCount = e - curr;
Expand Down Expand Up @@ -585,6 +586,8 @@ RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags,

cmdColor.primitive.skinningHandle = skinning.handle;
cmdColor.primitive.skinningOffset = skinning.offset;
cmdColor.primitive.skinningTexture = skinning.handleSampler;

cmdColor.primitive.morphWeightBuffer = morphing.handle;
cmdColor.primitive.morphTargetBuffer = morphTargets.buffer->getHwHandle();

Expand Down Expand Up @@ -689,6 +692,8 @@ RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags,

cmdDepth.primitive.skinningHandle = skinning.handle;
cmdDepth.primitive.skinningOffset = skinning.offset;
cmdDepth.primitive.skinningTexture = skinning.handleSampler;

cmdDepth.primitive.morphWeightBuffer = morphing.handle;
cmdDepth.primitive.morphTargetBuffer = morphTargets.buffer->getHwHandle();

Expand Down Expand Up @@ -873,7 +878,12 @@ void RenderPass::Executor::execute(backend::DriverApi& driver,
// note: even if only skinning is enabled, binding morphTargetBuffer is needed.
driver.bindSamplers(+SamplerBindingPoints::PER_RENDERABLE_MORPHING,
info.morphTargetBuffer);
}

if (UTILS_UNLIKELY(info.skinningTexture)) {
driver.bindSamplers(+SamplerBindingPoints::PER_RENDERABLE_SKINNING,
info.skinningTexture);
}
}

if (UTILS_UNLIKELY(info.morphWeightBuffer)) {
// Instead of using a UBO per primitive, we could also have a single UBO for all
Expand Down
3 changes: 2 additions & 1 deletion filament/src/RenderPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,15 @@ class RenderPass {
backend::RasterState rasterState; // 4 bytes
backend::Handle<backend::HwRenderPrimitive> primitiveHandle; // 4 bytes
backend::Handle<backend::HwBufferObject> skinningHandle; // 4 bytes
backend::Handle<backend::HwSamplerGroup> skinningTexture; // 4 bytes
backend::Handle<backend::HwBufferObject> morphWeightBuffer; // 4 bytes
backend::Handle<backend::HwSamplerGroup> morphTargetBuffer; // 4 bytes
backend::Handle<backend::HwBufferObject> instanceBufferHandle; // 4 bytes
uint32_t index = 0; // 4 bytes
uint32_t skinningOffset = 0; // 4 bytes
uint16_t instanceCount; // 2 bytes [MSb: user]
Variant materialVariant; // 1 byte
uint8_t reserved[4] = {}; // 4 bytes
// uint8_t reserved[0] = {}; // 0 bytes

static const uint16_t USER_INSTANCE_MASK = 0x8000u;
static const uint16_t INSTANCE_COUNT_MASK = 0x7fffu;
Expand Down
Loading