繁体   English   中英

为什么我的 Three.js animation 在 Vue.js 中较慢?

[英]Why is my Three.js animation slower in Vue.js?

我正在尝试在 Vue.js 中重新创建这个很棒的波浪模拟: https: //codepen.io/cheekymonkey/pen/vMvYNV。 但是,当我在 Vue.js 中重新创建 animation 时,它真的很慢

我尝试制作与 Vue.js 方法相同的所有功能,并将变量包含在组件的数据属性中。

<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>

它可以工作,就像它应该在波浪动画中一样,但它要慢得多。 不确定这是否是由于 Vue.js 或者我是如何设置的。 非常感谢任何建议!

发生这种情况是因为 Vue 在后台使每个附加到实例的组件都具有反应性。 深度反应 打开开发工具并查看您的 memory 足迹,当我在我的机器上运行您的代码片段时,它约为 300mb,而 codepen 示例约为 20mb。

当您使用console.log(this.scene)时,您看到的是允许 Vue 跟踪对象的 getter/setter。

this.scene 的控制台输出

下面的代码片段将 three.js 对象从 Vue 数据 object 中提取出来,并将它们附加到vue 静态object 中。 此插件允许您将某些变量设置为非反应性。

<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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM