Fix skinning bugs

- We were not setting the bones ubo staging buffer size correctly
- The bones UBO was never bound to the shader
- The default values for the bones ubo wasn’t identity
This commit is contained in:
Romain Guy
2018-08-03 12:03:36 -07:00
parent a48522aab9
commit 5147ded051
8 changed files with 26 additions and 5 deletions

View File

@@ -54,8 +54,9 @@ public:
Instance getInstance(utils::Entity e) const noexcept;
struct Bone {
math::quatf unitQuaternion;
math::float3 translation = {};
math::quatf unitQuaternion = { 1, 0, 0, 0 };
math::float3 translation = { 0, 0, 0 };
float reserved = 0;
};
class Builder : public BuilderBase<BuilderDetails> {

View File

@@ -305,6 +305,10 @@ Handle<HwProgram> FMaterial::getProgramSlow(uint8_t variantKey) const noexcept {
.addSamplerBlock(BindingPoints::PER_VIEW, &SibGenerator::getPerViewSib())
.addSamplerBlock(BindingPoints::PER_MATERIAL_INSTANCE, &mSamplerInterfaceBlock);
if (Variant(variantKey).hasSkinning()) {
pb.addUniformBlock(BindingPoints::PER_RENDERABLE_BONES, &UibGenerator::getPerRenderableBonesUib());
}
auto program = mEngine.getDriverApi().createProgram(std::move(pb));
assert(program);

View File

@@ -132,6 +132,9 @@ void RenderPass::recordDriverCommands(
// per-renderable uniform
PrimitiveInfo const& UTILS_RESTRICT info = c->primitive;
driver.bindUniforms(BindingPoints::PER_RENDERABLE, info.perRenderableUniforms);
if (info.perRenderableBones) {
driver.bindUniforms(BindingPoints::PER_RENDERABLE_BONES, info.perRenderableBones);
}
FMaterialInstance const* const UTILS_RESTRICT mi = info.mi;
if (UTILS_UNLIKELY(mi != previousMi)) {
@@ -271,6 +274,7 @@ void RenderPass::generateCommandsImpl(uint32_t,
auto const* const UTILS_RESTRICT soaVisibility = soa.data<FScene::VISIBILITY_STATE>();
auto const* const UTILS_RESTRICT soaPrimitives = soa.data<FScene::PRIMITIVES>();
auto const* const UTILS_RESTRICT soaUbh = soa.data<FScene::UBH>();
auto const* const UTILS_RESTRICT soaBonesUbh = soa.data<FScene::BONES_UBH>();
const bool hasShadowing = view->hasShadowing();
Variant materialVariant;
@@ -321,6 +325,7 @@ void RenderPass::generateCommandsImpl(uint32_t,
cmdColor.key = makeField(soaVisibility[i].priority, PRIORITY_MASK, PRIORITY_SHIFT);
cmdColor.primitive.perRenderableUniforms = soaUbh[i];
cmdColor.primitive.perRenderableBones = soaBonesUbh[i];
materialVariant.setShadowReceiver(soaVisibility[i].receiveShadows & hasShadowing);
materialVariant.setSkinning(soaVisibility[i].skinning);
@@ -330,6 +335,7 @@ void RenderPass::generateCommandsImpl(uint32_t,
cmdDepth.key |= makeField(soaVisibility[i].priority, PRIORITY_MASK, PRIORITY_SHIFT);
cmdDepth.key |= makeField(distanceBits, DISTANCE_BITS_MASK, DISTANCE_BITS_SHIFT);
cmdDepth.primitive.perRenderableUniforms = soaUbh[i];
cmdDepth.primitive.perRenderableBones = soaBonesUbh[i];
cmdDepth.primitive.materialVariant.setSkinning(soaVisibility[i].skinning);
const bool shadowCaster = soaVisibility[i].castShadows & hasShadowing;

View File

@@ -171,10 +171,11 @@ public:
return boolish ? -1llu : 0llu;
}
struct PrimitiveInfo { // 24 bytes (20)
struct PrimitiveInfo { // 28 bytes
FMaterialInstance const* mi = nullptr; // 8 bytes (4)
Handle<HwRenderPrimitive> primitiveHandle; // 4 bytes
Handle<HwUniformBuffer> perRenderableUniforms; // 4 bytes
Handle<HwUniformBuffer> perRenderableBones; // 4 bytes
Driver::RasterState rasterState; // 4 bytes
Variant materialVariant; // 1 byte
uint8_t reserved[3] = { }; // 3 bytes (that helps the compiler)

View File

@@ -120,6 +120,7 @@ void FScene::prepare(FEngine& engine, mat4f const& worldOriginTansform) {
worldTransform,
rcm.getVisibility(ri),
rcm.getUbh(ri),
rcm.getBonesUbh(ri),
worldAABB.center,
0,
rcm.getLayerMask(ri),

View File

@@ -288,8 +288,8 @@ void FRenderableManager::create(const RenderableManager::Builder& UTILS_RESTRICT
std::unique_ptr<Bones>& bones = manager[ci].bones;
bones.reset(new Bones); // FIXME: maybe use a pool allocator
bones->bones = UniformBuffer(CONFIG_MAX_BONE_COUNT * 2);
bones->handle = driver.createUniformBuffer(CONFIG_MAX_BONE_COUNT * 2);
bones->bones = UniformBuffer(CONFIG_MAX_BONE_COUNT * sizeof(Bone));
bones->handle = driver.createUniformBuffer(CONFIG_MAX_BONE_COUNT * sizeof(Bone));
}
}
if (builder->mSkinningBoneCount) {

View File

@@ -122,6 +122,7 @@ public:
inline UniformBuffer& getUniformBuffer(Instance instance) noexcept;
inline Handle<HwUniformBuffer> getUbh(Instance instance) const noexcept;
inline Handle<HwUniformBuffer> getBonesUbh(Instance instance) const noexcept;
inline size_t getLevelCount(Instance instance) const noexcept { return 1; }
@@ -310,6 +311,11 @@ Handle<HwUniformBuffer> FRenderableManager::getUbh(Instance instance) const noex
return mManager[instance].uniformsHandle;
}
Handle<HwUniformBuffer> FRenderableManager::getBonesUbh(Instance instance) const noexcept {
std::unique_ptr<Bones> const& bones = mManager[instance].bones;
return bones ? bones->handle : Handle<HwUniformBuffer>{};
}
utils::Slice<FRenderPrimitive> const& FRenderableManager::getRenderPrimitives(
Instance instance, uint8_t level) const noexcept {
return mManager[instance].primitives;

View File

@@ -92,6 +92,7 @@ public:
WORLD_TRANSFORM, // 16 instance of the Transform component
VISIBILITY_STATE, // 1 visibility data of the component
UBH, // 4 uniform buffer handle
BONES_UBH, // 4 bones uniform buffer handle
WORLD_AABB_CENTER, // 12 world-space bounding box center of the renderable
VISIBLE_MASK, // 1 each bit represents a visibility in a pass
@@ -109,6 +110,7 @@ public:
math::mat4f,
FRenderableManager::Visibility,
Handle<HwUniformBuffer>,
Handle<HwUniformBuffer>,
math::float3,
Culler::result_type,
uint8_t,