为什么我的 Three.js 动画在 Vue.js 中变慢了? [英] Why is my Three.js animation slower in Vue.js?
问题描述
我正在尝试重新创建这个很棒的波浪模拟:
下面的代码片段从 Vue 数据对象中提取了三个.js 对象并将它们附加到一个 vue-静态 对象.此插件允许您将某些变量设置为非反应性.
<div id="container" style="width:100%; height:100vh;"></div>模板><脚本>import * as Three from 'three'从'simplex-noise'导入SimplexNoise导出默认{name: '三测',静止的(){返回 {场景:new Three.Scene(),相机:空,渲染器:三个.WebGLRenderer,网:新的三网,噪音:SimplexNoise,系数:0}},安装(){this.init();},方法: {初始化:函数(){this.createScene();this.createCamera();this.createShape();this.addSpotlight('#fdffab');this.addAmbientLight();this.animate();window.addEventListener('resize', this.onResize())},onResize:函数(){let container = document.getElementById('container');this.renderer.setSize(container.clientWidth, container.clientHeight);this.camera.aspect = container.clientWidth/container.clientHeight;this.camera.updateProjectionMatrix();},创建场景:函数(){console.log("TCL: this.$options.bigHairyHorseNuts ",this.bigHairyHorseNuts)this.renderer = new Three.WebGLRenderer({抗锯齿:真实,阿尔法:真实});let container = document.getElementById('container');this.renderer.setSize(container.clientWidth, container.clientHeight);this.renderer.setPixelRatio(window.devicePixelRatio);this.renderer.setClearColor(new Three.Color('#fff'));//this.render.shadowMap.type = Three.PCFSoftShadowMap;this.noise = new SimplexNoise()container.appendChild(this.renderer.domElement);},创建相机:函数(){this.camera = new Three.PerspectiveCamera(20, container.clientWidth/container.clientHeight, 1, 1000);this.camera.position.set(0, 0, 20);},创建形状:函数(){常量段 = 100this.geometry = new Three.PlaneGeometry(5, 8, seg, seg)const material = new Three.MeshPhysicalMaterial({颜色:'#da0463',金属度:0.6,自发光:'#000',侧面:三.DoubleSide,线框:真实})this.mesh = new Three.Mesh(this.geometry, material)this.mesh.receiveShadow = truethis.mesh.castShadow = 真this.mesh.position.set(0, 0, 0)this.mesh.rotation.x = -Math.PI/3this.mesh.rotation.z = -Math.PI/4this.scene.add(this.mesh)},addSpotlight:功能(颜色){const light = new Three.SpotLight(color, 2, 1000)light.position.set(0, 0, 30)this.scene.add(light)},添加环境光:函数(){const light = new Three.AmbientLight('#fff', 0.5)this.scene.add(light)},addjustVertices:函数(){for (让 i = 0; i < this.geometry.vertices.length; i++) {const 顶点 = this.geometry.vertices[i]const x = vertex.x/4const y = vertex.y/6vertex.z = this.noise.noise2D(x, y + this.factor)}this.factor += 0.007this.geometry.verticesNeedUpdate = truethis.geometry.computeVertexNormals()},动画:函数(){requestAnimationFrame(this.animate);this.addjustVertices();this.camera.updateProjectionMatrix();this.renderer.render(this.scene, this.camera);}}}
I'm trying to recreate this awesome wave simulation: https://codepen.io/cheekymonkey/pen/vMvYNV, in Vue.js. However the animation is really slow when I've recreated it in Vue.js
I've tried making all of the same functions as Vue.js methods and including the variables in the component's data property.
<template>
<div id="container" style="width:100%; height:100vh;"></div>
</template>
<script>
import * as Three from 'three'
import SimplexNoise from'simplex-noise'
export default {
name: 'ThreeTest',
data() {
return {
camera: Three.PerspectiveCamera,
scene: Three.Scene,
renderer: Three.WebGLRenderer,
mesh: Three.Mesh,
noise: SimplexNoise,
geometry: null,
factor: 0
}
},
methods: {
init: function() {
this.createScene();
this.createCamera();
this.createShape();
this.addSpotlight('#fdffab');
this.addAmbientLight();
this.animate();
window.addEventListener('resize', this.onResize())
},
onResize: function() {
let container = document.getElementById('container');
this.renderer.setSize(container.clientWidth, container.clientHeight);
this.camera.aspect = container.clientWidth / container.clientHeight;
this.camera.updateProjectionMatrix();
},
createScene: function() {
this.scene = new Three.Scene();
this.renderer = new Three.WebGLRenderer({
antialias: true,
alpha: true
});
let container = document.getElementById('container');
this.renderer.setSize(container.clientWidth, container.clientHeight);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setClearColor(new Three.Color('#fff'));
//this.render.shadowMap.type = Three.PCFSoftShadowMap;
this.noise = new SimplexNoise()
container.appendChild(this.renderer.domElement);
},
createCamera: function() {
this.camera = new Three.PerspectiveCamera(20, container.clientWidth/container.clientHeight, 1, 1000);
this.camera.position.set(0, 0, 20);
},
createShape: function() {
const seg = 100
this.geometry = new Three.PlaneGeometry(5, 8, seg, seg)
const material = new Three.MeshPhysicalMaterial({
color: '#da0463',
metalness: 0.6,
emissive: '#000',
side: Three.DoubleSide,
wireframe: true
})
this.mesh = new Three.Mesh(this.geometry, material)
this.mesh.receiveShadow = true
this.mesh.castShadow = true
this.mesh.position.set(0, 0, 0)
this.mesh.rotation.x = -Math.PI / 3
this.mesh.rotation.z = -Math.PI / 4
this.scene.add(this.mesh)
},
addSpotlight: function(color) {
const light = new Three.SpotLight(color, 2, 1000)
light.position.set(0, 0, 30)
this.scene.add(light)
},
addAmbientLight: function() {
const light = new Three.AmbientLight('#fff', 0.5)
this.scene.add(light)
},
addjustVertices: function() {
for (let i = 0; i < this.geometry.vertices.length; i++) {
const vertex = this.geometry.vertices[i]
const x = vertex.x / 4
const y = vertex.y / 6
vertex.z = this.noise.noise2D(x, y + this.factor)
}
this.factor += 0.007
this.geometry.verticesNeedUpdate = true
this.geometry.computeVertexNormals()
},
animate: function() {
requestAnimationFrame(this.animate);
this.addjustVertices();
this.camera.updateProjectionMatrix();
this.renderer.render(this.scene, this.camera);
}
},
mounted() {
this.init();
}
}
</script>
It works, as in the wave animates like it should, but it's much slower. Not sure if this is due to Vue.js or just how I've set it up. Any advice much appreciated!
This is occurring because Vue under the hood makes each component attached to the instance reactive. Reactivity in Depth. Open up the dev tools and look at your memory footprint, when I ran your snippet on my machine it is ~300mb as opposed to the codepen example which is ~20mb.
When you console.log(this.scene)
what you see are the getters/setters that allow Vue to track objects.
The below snippet pulls the three.js objects out of the Vue data object and attaches them to a vue-static object. This plugin allows you to set certain variables as non-reactive.
<template>
<div id="container" style="width:100%; height:100vh;"></div>
</template>
<script>
import * as Three from 'three'
import SimplexNoise from'simplex-noise'
export default {
name: 'ThreeTest',
static(){
return {
scene: new Three.Scene(),
camera: null,
renderer: Three.WebGLRenderer,
mesh: new Three.Mesh,
noise: SimplexNoise,
factor:0
}
},
mounted() {
this.init();
},
methods: {
init: function() {
this.createScene();
this.createCamera();
this.createShape();
this.addSpotlight('#fdffab');
this.addAmbientLight();
this.animate();
window.addEventListener('resize', this.onResize())
},
onResize: function() {
let container = document.getElementById('container');
this.renderer.setSize(container.clientWidth, container.clientHeight);
this.camera.aspect = container.clientWidth / container.clientHeight;
this.camera.updateProjectionMatrix();
},
createScene: function() {
console.log("TCL: this.$options.bigHairyHorseNuts ",this.bigHairyHorseNuts)
this.renderer = new Three.WebGLRenderer({
antialias: true,
alpha: true
});
let container = document.getElementById('container');
this.renderer.setSize(container.clientWidth, container.clientHeight);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setClearColor(new Three.Color('#fff'));
//this.render.shadowMap.type = Three.PCFSoftShadowMap;
this.noise = new SimplexNoise()
container.appendChild(this.renderer.domElement);
},
createCamera: function() {
this.camera = new Three.PerspectiveCamera(20, container.clientWidth/container.clientHeight, 1, 1000);
this.camera.position.set(0, 0, 20);
},
createShape: function() {
const seg = 100
this.geometry = new Three.PlaneGeometry(5, 8, seg, seg)
const material = new Three.MeshPhysicalMaterial({
color: '#da0463',
metalness: 0.6,
emissive: '#000',
side: Three.DoubleSide,
wireframe: true
})
this.mesh = new Three.Mesh(this.geometry, material)
this.mesh.receiveShadow = true
this.mesh.castShadow = true
this.mesh.position.set(0, 0, 0)
this.mesh.rotation.x = -Math.PI / 3
this.mesh.rotation.z = -Math.PI / 4
this.scene.add(this.mesh)
},
addSpotlight: function(color) {
const light = new Three.SpotLight(color, 2, 1000)
light.position.set(0, 0, 30)
this.scene.add(light)
},
addAmbientLight: function() {
const light = new Three.AmbientLight('#fff', 0.5)
this.scene.add(light)
},
addjustVertices: function() {
for (let i = 0; i < this.geometry.vertices.length; i++) {
const vertex = this.geometry.vertices[i]
const x = vertex.x / 4
const y = vertex.y / 6
vertex.z = this.noise.noise2D(x, y + this.factor)
}
this.factor += 0.007
this.geometry.verticesNeedUpdate = true
this.geometry.computeVertexNormals()
},
animate: function() {
requestAnimationFrame(this.animate);
this.addjustVertices();
this.camera.updateProjectionMatrix();
this.renderer.render(this.scene, this.camera);
}
}
}
</script>
这篇关于为什么我的 Three.js 动画在 Vue.js 中变慢了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!