Skip to content
This repository was archived by the owner on Aug 21, 2024. It is now read-only.

Commit 0697005

Browse files
authored
Fixed jank in UVOL (#9189)
1 parent 66554e1 commit 0697005

1 file changed

Lines changed: 36 additions & 24 deletions

File tree

packages/engine/src/scene/components/UVOL2Component.ts

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -717,17 +717,33 @@ function UVOL2Reactor() {
717717
component.canPlay.set(true)
718718
}, [volumetric.paused])
719719

720-
const getAttribute = (name: string, target: string, index: number) => {
721-
const key = createKey(target, index)
720+
const getFrame = (currentTime: number, frameRate: number, integer = true) => {
721+
const frame = currentTime * frameRate
722+
return integer ? Math.round(frame) : frame
723+
}
724+
725+
const getAttribute = (name: 'keyframeA' | 'keyframeB', currentTime: number) => {
726+
const currentGeometryTarget = component.geometryTarget.value
727+
let index = getFrame(currentTime, manifest.current.geometry.targets[currentGeometryTarget].frameRate, false)
728+
if (name === 'keyframeA') {
729+
index = Math.floor(index)
730+
} else {
731+
index = Math.ceil(index)
732+
}
733+
const key = createKey(currentGeometryTarget, index)
722734
if (!geometryBuffer.has(key)) {
723-
const frameRate = manifest.current.geometry.targets[target].frameRate
724735
const targets = Object.keys(manifest.current.geometry.targets)
725736

726737
for (let i = 0; i < targets.length; i++) {
727738
const _target = targets[i]
728739
const _targetData = manifest.current.geometry.targets[_target]
729-
const _frameRate = _targetData.frameRate
730-
const _index = Math.round((index * _frameRate) / frameRate)
740+
let _index = getFrame(currentTime, _targetData.frameRate, false)
741+
if (name === 'keyframeA') {
742+
_index = Math.floor(_index)
743+
} else {
744+
_index = Math.ceil(_index)
745+
}
746+
731747
if (geometryBuffer.has(createKey(_target, _index))) {
732748
const attribute = geometryBuffer.get(createKey(_target, _index))! as InterleavedBufferAttribute
733749
return attribute
@@ -842,16 +858,15 @@ function UVOL2Reactor() {
842858
}
843859
}
844860

845-
const setTexture = (target: string, index: number) => {
861+
const setTexture = (target: string, index: number, currentTime: number) => {
846862
const key = createKey(target, index)
847863
if (!textureBuffer.has(key)) {
848864
const targets = Object.keys(manifest.current.texture.baseColor.targets)
849-
const frameRate = manifest.current.texture.baseColor.targets[target].frameRate
850865
for (let i = 0; i < targets.length; i++) {
851866
const _frameRate = manifest.current.texture.baseColor.targets[targets[i]].frameRate
852-
const _index = Math.round((index * _frameRate) / frameRate)
867+
const _index = getFrame(currentTime, _frameRate)
853868
if (textureBuffer.has(createKey(targets[i], _index))) {
854-
setTexture(targets[i], _index)
869+
setTexture(targets[i], _index, currentTime)
855870
return
856871
}
857872
}
@@ -890,14 +905,8 @@ function UVOL2Reactor() {
890905
}
891906

892907
const updateUniformSolve = (currentTime: number) => {
893-
const geometryTarget = component.geometryTarget.value
894-
const geometryFrame = currentTime * manifest.current.geometry.targets[geometryTarget].frameRate
895-
const keyframeAIndex = Math.floor(geometryFrame)
896-
const keyframeBIndex = Math.ceil(geometryFrame)
897-
let mixRatio = geometryFrame - keyframeAIndex
898-
899-
const keyframeA = getAttribute('position', geometryTarget, keyframeAIndex)
900-
const keyframeB = getAttribute('position', geometryTarget, keyframeBIndex)
908+
const keyframeA = getAttribute('keyframeA', currentTime)
909+
const keyframeB = getAttribute('keyframeB', currentTime)
901910

902911
if (!keyframeA && !keyframeB) {
903912
return
@@ -910,14 +919,17 @@ function UVOL2Reactor() {
910919
;(mesh.material as ShaderMaterial).uniforms.mixRatio.value = 0
911920
return
912921
} else if (keyframeA && keyframeB) {
922+
const keyframeAIndex = parseInt(keyframeA.name.slice(-KEY_PADDING))
913923
const keyframeATarget = keyframeA.name.slice(0, -KEY_PADDING)
924+
const keyframeATime = keyframeAIndex / manifest.current.geometry.targets[keyframeATarget].frameRate
925+
926+
const keyframeBIndex = parseInt(keyframeB.name.slice(-KEY_PADDING))
914927
const keyframeBTarget = keyframeB.name.slice(0, -KEY_PADDING)
915-
if (keyframeATarget === keyframeBTarget && keyframeATarget !== geometryTarget) {
916-
// If both keyframes are of different target, update the mixRatio
917-
const _geometryFrame = currentTime * manifest.current.geometry.targets[keyframeATarget].frameRate
918-
const _keyframeAIndex = Math.floor(_geometryFrame)
919-
mixRatio = _geometryFrame - _keyframeAIndex
920-
}
928+
const keyframeBTime = keyframeBIndex / manifest.current.geometry.targets[keyframeBTarget].frameRate
929+
930+
const d1 = Math.abs(currentTime - keyframeATime)
931+
const d2 = Math.abs(currentTime - keyframeBTime)
932+
const mixRatio = d1 + d2 > 0 ? d1 / (d1 + d2) : 0.5
921933
setAttribute('keyframeA', keyframeA)
922934
setAttribute('keyframeB', keyframeB)
923935
;(mesh.material as ShaderMaterial).uniforms.mixRatio.value = mixRatio
@@ -941,7 +953,7 @@ function UVOL2Reactor() {
941953
const updateTexture = (currentTime: number) => {
942954
const textureTarget = component.textureTarget.value
943955
const textureFrame = Math.round(currentTime * manifest.current.texture.baseColor.targets[textureTarget].frameRate)
944-
setTexture(textureTarget, textureFrame)
956+
setTexture(textureTarget, textureFrame, currentTime)
945957
}
946958

947959
const update = () => {

0 commit comments

Comments
 (0)