diff --git a/android/filament-android/src/main/cpp/RenderableManager.cpp b/android/filament-android/src/main/cpp/RenderableManager.cpp
index 4e586179ba..db0255d414 100644
--- a/android/filament-android/src/main/cpp/RenderableManager.cpp
+++ b/android/filament-android/src/main/cpp/RenderableManager.cpp
@@ -244,13 +244,25 @@ Java_com_google_android_filament_RenderableManager_nBuilderMorphing(JNIEnv*, jcl
builder->morphing(targetCount);
}
+extern "C" JNIEXPORT void JNICALL
+Java_com_google_android_filament_RenderableManager_nBuilderMorphingStandard(JNIEnv*, jclass,
+ jlong nativeBuilder, jlong nativeMorphTargetBuffer) {
+ RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
+ MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer;
+ builder->morphing(morphTargetBuffer);
+}
+
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderSetMorphTargetBufferAt(JNIEnv*, jclass,
jlong nativeBuilder, int level, int primitiveIndex, jlong nativeMorphTargetBuffer,
int offset, int count) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
- MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer;
- builder->morphing(level, primitiveIndex, morphTargetBuffer, offset, count);
+ if (nativeMorphTargetBuffer) {
+ MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer;
+ builder->morphing(level, primitiveIndex, morphTargetBuffer, offset, count);
+ } else {
+ builder->morphing(level, primitiveIndex, offset, count);
+ }
}
extern "C" JNIEXPORT void JNICALL
@@ -326,9 +338,14 @@ Java_com_google_android_filament_RenderableManager_nSetMorphTargetBufferAt(JNIEn
jclass, jlong nativeRenderableManager, jint i, int level, jint primitiveIndex,
jlong nativeMorphTargetBuffer, jint offset, jint count) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
- MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer;
- rm->setMorphTargetBufferAt((RenderableManager::Instance) i, (uint8_t) level,
- (size_t) primitiveIndex, morphTargetBuffer, (size_t) offset, (size_t) count);
+ if (nativeMorphTargetBuffer) {
+ MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer;
+ rm->setMorphTargetBufferAt((RenderableManager::Instance) i, (uint8_t) level,
+ (size_t) primitiveIndex, morphTargetBuffer, (size_t) offset, (size_t) count);
+ } else {
+ rm->setMorphTargetBufferAt((RenderableManager::Instance) i, (uint8_t) level,
+ (size_t) primitiveIndex, (size_t) offset, (size_t) count);
+ }
}
extern "C" JNIEXPORT jint JNICALL
diff --git a/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java b/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java
index f7a6319d7a..dfce1af4a1 100644
--- a/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java
+++ b/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java
@@ -524,14 +524,7 @@ public class RenderableManager {
}
/**
- * Controls if the renderable has vertex morphing targets, zero by default. This is
- * required to enable GPU morphing.
- *
- *
Filament supports two morphing modes: standard (default) and legacy.
- *
- * For standard morphing, A {@link MorphTargetBuffer} must be created and provided via
- * {@link RenderableManager#setMorphTargetBufferAt}. Standard morphing supports up to
- * CONFIG_MAX_MORPH_TARGET_COUNT morph targets.
+ * Controls if the renderable has legacy vertex morphing targets, zero by default.
*
* For legacy morphing, the attached {@link VertexBuffer} must provide data in the
* appropriate {@link VertexBuffer.VertexAttribute} slots (MORPH_POSITION_0 etc).
@@ -549,6 +542,22 @@ public class RenderableManager {
return this;
}
+ /**
+ * Controls if the renderable has vertex morphing targets, zero by default.
+ *
+ * For standard morphing, A {@link MorphTargetBuffer} must be provided.
+ * Standard morphing supports up to
+ * CONFIG_MAX_MORPH_TARGET_COUNT morph targets.
+ *
+ * See also {@link RenderableManager#setMorphWeights}, which can be called on a per-frame basis
+ * to advance the animation.
+ */
+ @NonNull
+ public Builder morphing(@NonNull MorphTargetBuffer morphTargetBuffer) {
+ nBuilderMorphingStandard(mNativeBuilder, morphTargetBuffer.getNativeObject());
+ return this;
+ }
+
/**
* Specifies the morph target buffer for a primitive.
*
@@ -565,6 +574,17 @@ public class RenderableManager {
* @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3)
*/
@NonNull
+ public Builder morphing(@IntRange(from = 0) int level,
+ @IntRange(from = 0) int primitiveIndex,
+ @IntRange(from = 0) int offset,
+ @IntRange(from = 0) int count) {
+ nBuilderSetMorphTargetBufferAt(mNativeBuilder, level, primitiveIndex, 0, offset, count);
+ return this;
+ }
+
+ /** @deprecated */
+ @Deprecated
+ @NonNull
public Builder morphing(@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@NonNull MorphTargetBuffer morphTargetBuffer,
@@ -575,10 +595,8 @@ public class RenderableManager {
return this;
}
- /**
- * Utility method to specify morph target buffer for a primitive.
- * For details, see the {@link RenderableManager.Builder#morphing}.
- */
+ /** @deprecated */
+ @Deprecated
@NonNull
public Builder morphing(@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@@ -687,6 +705,16 @@ public class RenderableManager {
*
* @see Builder#morphing
*/
+ public void setMorphTargetBufferAt(@EntityInstance int i,
+ @IntRange(from = 0) int level,
+ @IntRange(from = 0) int primitiveIndex,
+ @IntRange(from = 0) int offset,
+ @IntRange(from = 0) int count) {
+ nSetMorphTargetBufferAt(mNativeObject, i, level, primitiveIndex, 0, offset, count);
+ }
+
+ /** @deprecated */
+ @Deprecated
public void setMorphTargetBufferAt(@EntityInstance int i,
@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@@ -697,10 +725,8 @@ public class RenderableManager {
morphTargetBuffer.getNativeObject(), offset, count);
}
- /**
- * Utility method to change morph target buffer for the given primitive.
- * For details, see the {@link RenderableManager#setMorphTargetBufferAt}.
- */
+ /** @deprecated */
+ @Deprecated
public void setMorphTargetBufferAt(@EntityInstance int i,
@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@@ -1006,6 +1032,7 @@ public class RenderableManager {
private static native int nBuilderSkinningBones(long nativeBuilder, int boneCount, Buffer bones, int remaining);
private static native void nBuilderSkinningBuffer(long nativeBuilder, long nativeSkinningBuffer, int boneCount, int offset);
private static native void nBuilderMorphing(long nativeBuilder, int targetCount);
+ private static native void nBuilderMorphingStandard(long nativeBuilder, long nativeMorphTargetBuffer);
private static native void nBuilderSetMorphTargetBufferAt(long nativeBuilder, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset, int count);
private static native void nBuilderEnableSkinningBuffers(long nativeBuilder, boolean enabled);
private static native void nBuilderFog(long nativeBuilder, boolean enabled);
diff --git a/filament/include/filament/RenderableManager.h b/filament/include/filament/RenderableManager.h
index bb50b7d1db..363ef2d7c1 100644
--- a/filament/include/filament/RenderableManager.h
+++ b/filament/include/filament/RenderableManager.h
@@ -464,16 +464,11 @@ public:
Builder& boneIndicesAndWeights(size_t primitiveIndex,
utils::FixedCapacityVector<
utils::FixedCapacityVector> indicesAndWeightsVector) noexcept;
+
/**
- * Controls if the renderable has vertex morphing targets, zero by default. This is
+ * Controls if the renderable has legacy vertex morphing targets, zero by default. This is
* required to enable GPU morphing.
*
- * Filament supports two morphing modes: standard (default) and legacy.
- *
- * For standard morphing, A MorphTargetBuffer must be created and provided via
- * RenderableManager::setMorphTargetBufferAt(). Standard morphing supports up to
- * \c CONFIG_MAX_MORPH_TARGET_COUNT morph targets.
- *
* For legacy morphing, the attached VertexBuffer must provide data in the
* appropriate VertexAttribute slots (\c MORPH_POSITION_0 etc). Legacy morphing only
* supports up to 4 morph targets and will be deprecated in the future. Legacy morphing must
@@ -486,26 +481,52 @@ public:
Builder& morphing(size_t targetCount) noexcept;
/**
- * Specifies the morph target buffer for a primitive.
+ * Controls if the renderable has vertex morphing targets, zero by default. This is
+ * required to enable GPU morphing.
*
- * The morph target buffer must have an associated renderable and geometry. Two conditions
- * must be met:
- * 1. The number of morph targets in the buffer must equal the renderable's morph target
- * count.
- * 2. The vertex count of each morph target must equal the geometry's vertex count.
+ * Filament supports two morphing modes: standard (default) and legacy.
*
- * @param level the level of detail (lod), only 0 can be specified
- * @param primitiveIndex zero-based index of the primitive, must be less than the count passed to Builder constructor
- * @param morphTargetBuffer specifies the morph target buffer
- * @param offset specifies where in the morph target buffer to start reading (expressed as a number of vertices)
- * @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3)
+ * For standard morphing, A MorphTargetBuffer must be provided.
+ * Standard morphing supports up to \c CONFIG_MAX_MORPH_TARGET_COUNT morph targets.
+ *
+ * For legacy morphing, the attached VertexBuffer must provide data in the
+ * appropriate VertexAttribute slots (\c MORPH_POSITION_0 etc). Legacy morphing only
+ * supports up to 4 morph targets and will be deprecated in the future. Legacy morphing must
+ * be enabled on the material definition: either via the legacyMorphing material attribute
+ * or by calling filamat::MaterialBuilder::useLegacyMorphing().
+ *
+ * See also RenderableManager::setMorphWeights(), which can be called on a per-frame basis
+ * to advance the animation.
+ */
+ Builder& morphing(MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept;
+
+ /**
+ * @deprecated Use morphing(uint8_t level, size_t primitiveIndex, size_t offset, size_t count) instead
*/
Builder& morphing(uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer,
size_t offset, size_t count) noexcept;
+ /**
+ * @deprecated Use morphing(uint8_t level, size_t primitiveIndex, size_t offset, size_t count) instead
+ */
inline Builder& morphing(uint8_t level, size_t primitiveIndex,
- MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept;
+ MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept {
+ return morphing(level, primitiveIndex, morphTargetBuffer, 0,
+ morphTargetBuffer->getVertexCount());
+ }
+
+ /**
+ * Specifies the the range of the MorphTargetBuffer to use with this primitive.
+ *
+ * @param level the level of detail (lod), only 0 can be specified
+ * @param primitiveIndex zero-based index of the primitive, must be less than the count passed to Builder constructor
+ * @param offset specifies where in the morph target buffer to start reading (expressed as a number of vertices)
+ * @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3)
+ */
+ Builder& morphing(uint8_t level, size_t primitiveIndex,
+ size_t offset, size_t count) noexcept;
+
/**
* Sets the drawing order for blended primitives. The drawing order is either global or
@@ -765,14 +786,19 @@ public:
/**
* Associates a MorphTargetBuffer to the given primitive.
*/
+ void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
+ size_t offset, size_t count);
+
+ /** @deprecated */
void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer, size_t offset, size_t count);
- /**
- * Utility method to change a MorphTargetBuffer to the given primitive
- */
+ /** @deprecated */
inline void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
- MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer);
+ MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) {
+ setMorphTargetBufferAt(instance, level, primitiveIndex, morphTargetBuffer, 0,
+ morphTargetBuffer->getVertexCount());
+ }
/**
* Get a MorphTargetBuffer to the given primitive or null if it doesn't exist.
@@ -906,20 +932,6 @@ protected:
~RenderableManager() = default;
};
-RenderableManager::Builder& RenderableManager::Builder::morphing(
- uint8_t level, size_t primitiveIndex,
- MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept {
- return morphing(level, primitiveIndex, morphTargetBuffer, 0,
- morphTargetBuffer->getVertexCount());
-}
-
-void RenderableManager::setMorphTargetBufferAt(
- Instance instance, uint8_t level, size_t primitiveIndex,
- MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) {
- setMorphTargetBufferAt(instance, level, primitiveIndex, morphTargetBuffer, 0,
- morphTargetBuffer->getVertexCount());
-}
-
template
Box RenderableManager::computeAABB(
VECTOR const* UTILS_NONNULL vertices,
diff --git a/filament/src/RenderPass.cpp b/filament/src/RenderPass.cpp
index 4c949a26bf..e13b5da305 100644
--- a/filament/src/RenderPass.cpp
+++ b/filament/src/RenderPass.cpp
@@ -684,6 +684,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla
cmd.info.indexCount = primitive.getIndexCount();
cmd.info.type = primitive.getPrimitiveType();
cmd.info.morphTargetBuffer = morphTargets.buffer->getHwHandle();
+ cmd.info.morphingOffset = morphTargets.offset;
if constexpr (isColorPass) {
RenderPass::setupColorCommand(cmd, renderableVariant, mi, inverseFrontFaces);
@@ -1029,6 +1030,9 @@ void RenderPass::Executor::execute(FEngine& engine,
rebindPipeline = false;
currentPipeline = pipeline;
driver.bindPipeline(pipeline);
+
+ driver.setPushConstant(ShaderStage::VERTEX,
+ +PushConstantIds::MORPHING_BUFFER_OFFSET, int32_t(info.morphingOffset));
}
if (info.rph != currentPrimitiveHandle) {
diff --git a/filament/src/RenderPass.h b/filament/src/RenderPass.h
index b8810de33b..e1c7b3c181 100644
--- a/filament/src/RenderPass.h
+++ b/filament/src/RenderPass.h
@@ -251,6 +251,7 @@ public:
uint32_t indexCount; // 4 bytes
uint32_t index = 0; // 4 bytes
backend::SamplerGroupHandle morphTargetBuffer; // 4 bytes
+ uint32_t morphingOffset = 0; // 4 bytes
backend::RasterState rasterState; // 4 bytes
@@ -261,7 +262,7 @@ public:
bool hasMorphing : 1; // 1 bit
bool hasHybridInstancing : 1; // 1 bit
- uint32_t rfu[3]; // 16 bytes
+ uint32_t rfu[2]; // 16 bytes
};
static_assert(sizeof(PrimitiveInfo) == 56);
diff --git a/filament/src/RenderableManager.cpp b/filament/src/RenderableManager.cpp
index 133dd817c2..9550197acf 100644
--- a/filament/src/RenderableManager.cpp
+++ b/filament/src/RenderableManager.cpp
@@ -164,6 +164,11 @@ void RenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level,
downcast(morphTargetBuffer), offset, count);
}
+void RenderableManager::setMorphTargetBufferAt(
+ Instance instance, uint8_t level, size_t primitiveIndex, size_t offset, size_t count) {
+ downcast(this)->setMorphTargetBufferAt(instance, level, primitiveIndex, offset, count);
+}
+
MorphTargetBuffer* RenderableManager::getMorphTargetBufferAt(Instance instance, uint8_t level,
size_t primitiveIndex) const noexcept {
return downcast(this)->getMorphTargetBufferAt(instance, level, primitiveIndex);
diff --git a/filament/src/components/RenderableManager.cpp b/filament/src/components/RenderableManager.cpp
index 2cd031059b..c0907ee880 100644
--- a/filament/src/components/RenderableManager.cpp
+++ b/filament/src/components/RenderableManager.cpp
@@ -86,6 +86,7 @@ struct RenderableManager::BuilderDetails {
RenderableManager::Builder::GeometryType mGeometryType : 2;
size_t mSkinningBoneCount = 0;
size_t mMorphTargetCount = 0;
+ FMorphTargetBuffer* mMorphTargetBuffer = nullptr;
Bone const* mUserBones = nullptr;
mat4f const* mUserBoneMatrices = nullptr;
FSkinningBuffer* mSkinningBuffer = nullptr;
@@ -273,6 +274,18 @@ RenderableManager::Builder& RenderableManager::Builder::morphing(size_t targetCo
return *this;
}
+RenderableManager::Builder& RenderableManager::Builder::morphing(
+ MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept {
+ mImpl->mMorphTargetBuffer = downcast(morphTargetBuffer);
+ mImpl->mMorphTargetCount = morphTargetBuffer->getCount();
+ return *this;
+}
+
+RenderableManager::Builder& RenderableManager::Builder::morphing(
+ uint8_t level, size_t primitiveIndex, size_t offset, size_t count) noexcept {
+ return morphing(level, primitiveIndex, mImpl->mMorphTargetBuffer, offset, count);
+}
+
RenderableManager::Builder& RenderableManager::Builder::morphing(uint8_t, size_t primitiveIndex,
MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count) noexcept {
std::vector& entries = mImpl->mEntries;
@@ -646,10 +659,14 @@ void FRenderableManager::create(
// Create and initialize all needed MorphTargets.
// It's required to avoid branches in hot loops.
+ FMorphTargetBuffer* morphTargetBuffer = builder->mMorphTargetBuffer;
+ if (morphTargetBuffer == nullptr) {
+ morphTargetBuffer = mEngine.getDummyMorphTargetBuffer();
+ }
MorphTargets* const morphTargets = new MorphTargets[entryCount];
std::generate_n(morphTargets, entryCount,
- [dummy = mEngine.getDummyMorphTargetBuffer()]() -> MorphTargets {
- return { dummy, 0, 0 };
+ [morphTargetBuffer]() -> MorphTargets {
+ return { morphTargetBuffer, 0, 0 };
});
mManager[ci].morphTargets = { morphTargets, size_type(entryCount) };
@@ -967,6 +984,17 @@ void FRenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level
}
}
+void FRenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level,
+ size_t primitiveIndex, size_t offset, size_t count) {
+ if (instance) {
+ Slice& morphTargets = getMorphTargets(instance, level);
+ if (primitiveIndex < morphTargets.size()) {
+ setMorphTargetBufferAt(instance, level,
+ primitiveIndex, morphTargets[primitiveIndex].buffer, offset, count);
+ }
+ }
+}
+
MorphTargetBuffer* FRenderableManager::getMorphTargetBufferAt(Instance instance, uint8_t level,
size_t primitiveIndex) const noexcept {
if (instance) {
diff --git a/filament/src/components/RenderableManager.h b/filament/src/components/RenderableManager.h
index 70332c63bb..6135ba2d73 100644
--- a/filament/src/components/RenderableManager.h
+++ b/filament/src/components/RenderableManager.h
@@ -157,6 +157,8 @@ public:
void setMorphWeights(Instance instance, float const* weights, size_t count, size_t offset);
void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
FMorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count);
+ void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
+ size_t offset, size_t count);
MorphTargetBuffer* getMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex) const noexcept;
size_t getMorphTargetCount(Instance instance) const noexcept;
diff --git a/filament/src/details/MorphTargetBuffer.cpp b/filament/src/details/MorphTargetBuffer.cpp
index b615e6e705..c2f3d9a138 100644
--- a/filament/src/details/MorphTargetBuffer.cpp
+++ b/filament/src/details/MorphTargetBuffer.cpp
@@ -153,7 +153,7 @@ void FMorphTargetBuffer::setPositionsAt(FEngine& engine, size_t targetIndex,
"MorphTargetBuffer (size=%lu) overflow (count=%u, offset=%u)",
(unsigned)mVertexCount, (unsigned)count, (unsigned)offset);
- auto size = getSize(mVertexCount);
+ auto size = getSize(count);
ASSERT_PRECONDITION(targetIndex < mCount,
"%d target index must be < %d", targetIndex, mCount);
@@ -177,7 +177,7 @@ void FMorphTargetBuffer::setPositionsAt(FEngine& engine, size_t targetIndex,
"MorphTargetBuffer (size=%lu) overflow (count=%u, offset=%u)",
(unsigned)mVertexCount, (unsigned)count, (unsigned)offset);
- auto size = getSize(mVertexCount);
+ auto size = getSize(count);
ASSERT_PRECONDITION(targetIndex < mCount,
"%d target index must be < %d", targetIndex, mCount);
@@ -200,7 +200,7 @@ void FMorphTargetBuffer::setTangentsAt(FEngine& engine, size_t targetIndex,
"MorphTargetBuffer (size=%lu) overflow (count=%u, offset=%u)",
(unsigned)mVertexCount, (unsigned)count, (unsigned)offset);
- const auto size = getSize(mVertexCount);
+ const auto size = getSize(count);
ASSERT_PRECONDITION(targetIndex < mCount,
"%d target index must be < %d", targetIndex, mCount);
@@ -226,8 +226,8 @@ void FMorphTargetBuffer::updateDataAt(backend::DriverApi& driver,
size_t const xoffset = offset % MAX_MORPH_TARGET_BUFFER_WIDTH;
size_t const textureWidth = getWidth(mVertexCount);
size_t const alignment = ((textureWidth - xoffset) % textureWidth);
- size_t const lineCount = (count - alignment) / textureWidth;
- size_t const lastLineCount = (count - alignment) % textureWidth;
+ size_t const lineCount = (count > alignment) ? (count - alignment) / textureWidth : 0;
+ size_t const lastLineCount = (count > alignment) ? (count - alignment) % textureWidth : 0;
// 'out' buffer is going to be used up to 3 times, so for simplicity we use a shared_buffer
// to manage its lifetime. One side effect of this is that the callbacks below will allocate
diff --git a/libs/filabridge/include/private/filament/EngineEnums.h b/libs/filabridge/include/private/filament/EngineEnums.h
index a35a68c793..4a8c042e75 100644
--- a/libs/filabridge/include/private/filament/EngineEnums.h
+++ b/libs/filabridge/include/private/filament/EngineEnums.h
@@ -72,7 +72,7 @@ enum class ReservedSpecializationConstants : uint8_t {
CONFIG_STEREO_EYE_COUNT = 8, // don't change (hardcoded in ShaderCompilerService.cpp)
};
-enum class PushConstantIds {
+enum class PushConstantIds : uint8_t {
MORPHING_BUFFER_OFFSET = 0,
};
@@ -143,6 +143,8 @@ struct utils::EnableIntegerOperators : public st
template<>
struct utils::EnableIntegerOperators : public std::true_type {};
template<>
+struct utils::EnableIntegerOperators : public std::true_type {};
+template<>
struct utils::EnableIntegerOperators : public std::true_type {};
template<>
diff --git a/samples/hellomorphing.cpp b/samples/hellomorphing.cpp
index af5124bf4b..6bd418cf43 100644
--- a/samples/hellomorphing.cpp
+++ b/samples/hellomorphing.cpp
@@ -54,7 +54,6 @@ struct App {
Skybox* skybox;
Entity renderable;
MorphTargetBuffer *mt1;
- MorphTargetBuffer *mt2;
};
struct Vertex {
@@ -174,12 +173,7 @@ int main(int argc, char** argv) {
.build(*engine);
app.mt1 = MorphTargetBuffer::Builder()
- .vertexCount(9)
- .count(3)
- .build(*engine);
-
- app.mt2 = MorphTargetBuffer::Builder()
- .vertexCount(9)
+ .vertexCount(9 * 2)
.count(3)
.build(*engine);
@@ -190,12 +184,12 @@ int main(int argc, char** argv) {
app.mt1->setTangentsAt(*engine,1, targets_tan+3, 3, 0);
app.mt1->setTangentsAt(*engine,2, targets_tan+6, 3, 0);
- app.mt2->setPositionsAt(*engine,0, targets_pos2, 3, 0);
- app.mt2->setPositionsAt(*engine,1, targets_pos2+3, 3, 0);
- app.mt2->setPositionsAt(*engine,2, targets_pos2+6, 3, 0);
- app.mt2->setTangentsAt(*engine,0, targets_tan, 3, 0);
- app.mt2->setTangentsAt(*engine,1, targets_tan+3, 3, 0);
- app.mt2->setTangentsAt(*engine,2, targets_tan+6, 3, 0);
+ app.mt1->setPositionsAt(*engine,0, targets_pos2, 3, 9);
+ app.mt1->setPositionsAt(*engine,1, targets_pos2+3, 3, 9);
+ app.mt1->setPositionsAt(*engine,2, targets_pos2+6, 3, 9);
+ app.mt1->setTangentsAt(*engine,0, targets_tan, 3, 9);
+ app.mt1->setTangentsAt(*engine,1, targets_tan+3, 3, 9);
+ app.mt1->setTangentsAt(*engine,2, targets_tan+6, 3, 9);
app.renderable = EntityManager::get().create();
@@ -209,8 +203,8 @@ int main(int argc, char** argv) {
.receiveShadows(false)
.castShadows(false)
.morphing(3)
- .morphing(0,0,app.mt1)
- .morphing(0,1,app.mt2)
+ .morphing(0,0,app.mt1, 0, app.mt1->getCount())
+ .morphing(0,1,app.mt1, 9, app.mt1->getCount())
.build(*engine, app.renderable);
scene->addEntity(app.renderable);
@@ -226,7 +220,6 @@ int main(int argc, char** argv) {
engine->destroy(app.vb);
engine->destroy(app.ib);
engine->destroy(app.mt1);
- engine->destroy(app.mt2);
engine->destroyCameraComponent(app.camera);
utils::EntityManager::get().destroy(app.camera);
};
diff --git a/shaders/src/getters.vs b/shaders/src/getters.vs
index 4b5efda574..cccc08319c 100644
--- a/shaders/src/getters.vs
+++ b/shaders/src/getters.vs
@@ -146,7 +146,8 @@ void skinNormalTangent(inout vec3 n, inout vec3 t, const uvec4 ids, const vec4 w
#define MAX_MORPH_TARGET_BUFFER_WIDTH 2048
void morphPosition(inout vec4 p) {
- ivec3 texcoord = ivec3(getVertexIndex() % MAX_MORPH_TARGET_BUFFER_WIDTH, getVertexIndex() / MAX_MORPH_TARGET_BUFFER_WIDTH, 0);
+ int index = getVertexIndex() + pushConstants.morphingBufferOffset;
+ ivec3 texcoord = ivec3(index % MAX_MORPH_TARGET_BUFFER_WIDTH, index / MAX_MORPH_TARGET_BUFFER_WIDTH, 0);
int c = object_uniforms_morphTargetCount;
for (int i = 0; i < c; ++i) {
float w = morphingUniforms.weights[i][0];
@@ -159,7 +160,8 @@ void morphPosition(inout vec4 p) {
void morphNormal(inout vec3 n) {
vec3 baseNormal = n;
- ivec3 texcoord = ivec3(getVertexIndex() % MAX_MORPH_TARGET_BUFFER_WIDTH, getVertexIndex() / MAX_MORPH_TARGET_BUFFER_WIDTH, 0);
+ int index = getVertexIndex() + pushConstants.morphingBufferOffset;
+ ivec3 texcoord = ivec3(index % MAX_MORPH_TARGET_BUFFER_WIDTH, index / MAX_MORPH_TARGET_BUFFER_WIDTH, 0);
int c = object_uniforms_morphTargetCount;
for (int i = 0; i < c; ++i) {
float w = morphingUniforms.weights[i][0];