diff --git a/.gitignore b/.gitignore index 146c9fa..a6d5a5d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ data/ a2f_venv/ external/ -nul \ No newline at end of file +nul +examples \ No newline at end of file diff --git a/examples/3d/babylonAdapter.js b/examples/3d/babylonAdapter.js index b2bf58a..86b9b5e 100644 --- a/examples/3d/babylonAdapter.js +++ b/examples/3d/babylonAdapter.js @@ -31,82 +31,6 @@ class BabylonMorphTargetAdapter { return totalTargets; } - async warmupInvisible(scene) { - console.log('开始预热...'); - const startTime = performance.now(); - - const allTargets = Object.values(this.morphTargetCache).flat(); - const totalTargets = allTargets.length; - console.log(`预热 ${totalTargets} 个 morph targets`); - - // 多轮预热,用不同值组合 - const rounds = 10; - for (let r = 0; r < rounds; r++) { - const val = (r % 2 === 0) ? 1.0 : 0; - allTargets.forEach(mt => mt.influence = val); - scene.render(); - await new Promise(r => requestAnimationFrame(r)); - } - - // 重置 - allTargets.forEach(mt => mt.influence = 0); - scene.render(); - - // 等待几帧让 GPU 完全稳定 - for (let i = 0; i < 5; i++) { - await new Promise(r => requestAnimationFrame(r)); - } - - console.log(`预热完成,耗时 ${(performance.now() - startTime).toFixed(2)}ms`); - } - - warmupShaders(scene) { - console.log('开始shader预热...'); - const startTime = performance.now(); - - // 强制同步更新所有 morph target managers - this.meshes?.forEach(mesh => { - const mtm = mesh.morphTargetManager; - if (mtm) { - mtm.enableNormalMorphing = true; - mtm.enableTangentMorphing = true; - } - }); - - // 预热:强制触发着色器编译 - // 使用多种值组合来触发所有可能的shader变体 - const testValues = [0, 0.2, 0.4, 0.6, 0.8, 1.0]; - - for (let pass = 0; pass < testValues.length; pass++) { - const value = testValues[pass]; - for (const targets of Object.values(this.morphTargetCache)) { - targets.forEach(mt => { - mt.influence = value; - }); - } - - // 每次设置后都渲染,确保shader编译 - if (scene) { - scene.render(); - } - } - - // 重置所有影响值 - for (const targets of Object.values(this.morphTargetCache)) { - targets.forEach(mt => { - mt.influence = 0; - }); - } - - // 最后渲染一次确保重置生效 - if (scene) { - scene.render(); - } - - const elapsed = performance.now() - startTime; - console.log(`shader预热完成,耗时 ${elapsed.toFixed(2)}ms`); - } - setInfluence(name, value) { const lowerName = name.toLowerCase(); const targets = this.morphTargetCache[lowerName]; diff --git a/examples/3d/blendshapeAnimator.js b/examples/3d/blendshapeAnimator.js index 05e2e75..d534cda 100644 --- a/examples/3d/blendshapeAnimator.js +++ b/examples/3d/blendshapeAnimator.js @@ -24,11 +24,7 @@ class BlendShapeAnimator { this.deltaThreshold = typeof config.deltaThreshold === 'number' ? config.deltaThreshold : 0.002; // Skip re-applying nearly identical values - this.prewarmFrameCount = typeof config.prewarmFrameCount === 'number' - ? config.prewarmFrameCount - : 30; this.lastFrameBlendShapes = {}; - this._hasPrewarmed = false; // 空闲动画参数 this.blinkParams = config.blinkParams || { @@ -97,7 +93,6 @@ class BlendShapeAnimator { this.animationFrames = frames || []; this.animationShapeNames = this._collectAnimationShapeNames(this.animationFrames); this.lastFrameBlendShapes = {}; - // 不重置 _hasPrewarmed,因为全局预热只需要做一次 } appendAnimationFrames(frames) { @@ -107,7 +102,6 @@ class BlendShapeAnimator { this.animationFrames.push(...frames); const newNames = this._collectAnimationShapeNames(frames); - // 不重置 _hasPrewarmed if (newNames.length === 0) { return; @@ -227,49 +221,6 @@ class BlendShapeAnimator { this.lastFrameBlendShapes = {}; } - _prewarmAnimation() { - // 同步预热已移除,改用异步预热 - this._hasPrewarmed = true; - } - - // 异步分帧预热 - 预热所有 morph targets,确保 GPU 真正渲染 - async prewarmAsync(scene) { - if (!this.morphTargetAdapter) { - return; - } - - // 获取所有可用的 morph targets,而不只是当前动画用到的 - const allShapes = this.morphTargetAdapter.morphTargetCache - ? Object.keys(this.morphTargetAdapter.morphTargetCache) - : this.animationShapeNames; - - const shapes = allShapes.filter( - name => !this.disabledShapesInAnimation.includes(name.toLowerCase()) - ); - - if (shapes.length === 0) return; - - console.log(`异步预热 ${shapes.length} 个 morph targets...`); - - // 用不同的值组合预热,触发所有可能的 shader 变体 - const testValues = [0.2, 0.5, 0.8, 1.0]; - for (const val of testValues) { - shapes.forEach(name => this.morphTargetAdapter.setInfluence(name, val)); - if (scene) scene.render(); - await new Promise(r => requestAnimationFrame(r)); - } - - // 重置并等待几帧确保稳定 - shapes.forEach(name => this.morphTargetAdapter.setInfluence(name, 0)); - for (let i = 0; i < 5; i++) { - if (scene) scene.render(); - await new Promise(r => requestAnimationFrame(r)); - } - - this._hasPrewarmed = true; - console.log('异步预热完成'); - } - _primeFirstFrame() { if (!this.morphTargetAdapter || this.animationFrames.length === 0) { return; @@ -297,24 +248,6 @@ class BlendShapeAnimator { } } - _touchAnimationShapes() { - if (!this.morphTargetAdapter || !Array.isArray(this.animationShapeNames) || this.animationShapeNames.length === 0) { - return; - } - - const touchValue = Math.max(this.minBlendShapeValue * 1.2, 0.05); - const touched = []; - - this.animationShapeNames.forEach(name => { - this.morphTargetAdapter.setInfluence(name, touchValue); - touched.push(name); - }); - - touched.forEach(name => { - this.morphTargetAdapter.setInfluence(name, 0); - }); - } - _scheduleAnimationStart() { // 只设置开始时间,动画由统一的 RAF 循环驱动 this.animationStartTime = performance.now(); diff --git a/examples/3d/index.html b/examples/3d/index.html index b127791..b28f866 100644 --- a/examples/3d/index.html +++ b/examples/3d/index.html @@ -17,54 +17,62 @@