我想使用不同的持续时间和各个顶点的延迟,将顶点从一个3D模型变形到下一个三维模型。
首先,我加载我的两个模型,采用具有更大顶点数的模型并复制它的顶点位置。然后,我采用第二个模型并将其顶点位置指定为targetPosition
属性:
class CustomGeometry extends THREE.BufferGeometry {
constructor (refGeo1, refGeo2) {
super()
let count = refGeo1.attributes.position.count
let targets = new Float32Array(count * 3)
for (let i = 0; i < count; i += 3) {
// if there is no corresponding vertex, simply assign 0
targets[i + 0] = refGeo2.attributes.position.array[i + 0] || 0
targets[i + 1] = refGeo2.attributes.position.array[i + 1] || 0
targets[i + 2] = refGeo2.attributes.position.array[i + 2] || 0
}
this.addAttribute('position', refGeo1.attributes.position)
this.addAttribute('targetPosition', new THREE.BufferAttribute(targets, 3))
}
}
然后我可以传递一个统一变量mixFactor
并在我的顶点着色器中执行此操作:
vec3 newPosition = mix(position, targetPosition, mixFactor)
这是一个实时example
这很好,除了当mixFactor变量改变时顶点均匀地通过空间(具有相同的定时持续时间)。如何为混音添加延迟和不同的时间?
我知道我可以attribute float mixFactor
穿上制服,然后在CPU上补间,但这会导致我的表现失败......我怀疑我必须添加transitionTiming
和{{1将属性浮动到我的顶点,但我失去了如何在着色器中进行数学运算......
答案 0 :(得分:1)
您为每个顶点添加了另一个属性,可以称之为mixAmountOffset
。在着色器中的mixAmount计算中使用它。
attribute float mixAmountOffset;
uniform float mixAmount;
....
float realMixAmount = clamp(mixAmount + mixAmountOffset, 0., 1.);
然后在混合中使用realMixmount
vec4 position = mix(position1, position2, realMixAmount);
您只需在JavaScript中更新mixAmount
为了更清楚你需要realMixAmount
为每个顶点传递0到1之间的值。因此,我们假设您将mixAmountOffset
设置为从顶点
for (let i = 0; i < vertexCount ++i) {
mixAmountOffset[i] = -i / vertexCount;
}
现在mixAmount + mixAmountOffset
的数学需要将所有点从0传递到1. mixAmountOffset
的范围现在为0到-1,这意味着当mixAmount为0时mixAmount + mixAmountOffset
将来自所有顶点都为0到-1。因为clamp
在所有顶点上都是0到0。
当mixAmount
为1
时,mixAmount + mixAmountOffset
将从1变为0.意味着只有第一个顶点使用第二个模型的位置,最后一个顶点仍在使用第一个模特的位置。
你需要将mixAmount
从0变为2.那么当mixAmount
为2时,mixAmount + mixAmountOffset
将在所有顶点之间从2变为1,并且钳位将使1变为1所有顶点都有1个。换句话说,所有顶点都将使用model2
您使用mixAmountOffsets
以及如何计算realMixeAmount
的算法取决于您自己。关键是你需要在事情开始之前进行数学运算所有顶点得到realMixAmount
为0并且事情结束之后所有顶点得到realMixAmount
为1.有无数种方法可以做到这一点。
查看您的代码,您传递了mixAmountOffset
的顶点索引,例如,您可以传递另一个制服vertexCount
并执行scaledMixAmountOffset = mixAmountOffset / vertexCount
。
或者,您可以将mixAmountOffset
缓冲区中的正值从0添加到1,将mixAmount
从-1添加到1.
或......等......
您可能想要做的其他事情:
当你lerp时,你可以在mixAmount
上使用某种平滑功能,但在这种情况下,因为每个顶点都有效地单独渲染你可能想要将平滑函数放在着色器中
示例:
...
float smooth(float pos) {
pos *= 2.;
if (pos < 1.) {
return 0.5 * pow(2., 10. * (pos - 1.));
}
return 0.5 * (-pow(2., -10. * --pos) + 2.);
}
void main () {
float realFactorOffset = clamp(mixFactor + mixFactorOffset, 0.0, 1.0);
realFactorOffset = smooth(realFactorOffset);
vec3 newPosition = mix(position, targetPosition, realFactorOffset);
...