2012-09-18 155 views
0

我用下面的代碼創建了一個3d場景。three.js - webgl和canvas渲染性能問題

<!DOCTYPE html> 
<html lang="en"> 
    <head> 
     <title>3d Model using HTML5 and three.js</title> 
     <meta charset="utf-8"> 
     <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> 
     <style> 
      body { 
       font-family: Monospace; 
       background-color: #f0f0f0; 
       margin: 0px; 
       overflow: hidden; 
      } 
     </style> 
    </head> 
    <body> 

     <script src="three.min.js" type="text/javascript"></script> 
     <script src="Curve.js" type="text/javascript"></script> 
     <script src="TubeGeometry.js" type="text/javascript"></script>  
     <script src="Stats.js" type="text/javascript"></script> 
     <script src="Detector.js" type="text/javascript"></script> 

     <script> 
     // variables 
     var container, stats; 

     var camera, scene, renderer, splineCamera, cameraHelper, cameraEye; 

     var text, plane, tube, tubeMesh, parent; 

     var targetRotation = 0; 
     var targetRotationOnMouseDown = 0; 

     var mouseX = 0; 
     var mouseXOnMouseDown = 0; 

     var windowHalfX = window.innerWidth/2; 
     var windowHalfY = window.innerHeight/2; 

     var binormal = new THREE.Vector3(); 
     var normal = new THREE.Vector3(); 



     init();      
     animate(); 

     function init(){ 

      // container 
      container = document.createElement('div'); 
      document.body.appendChild(container); 

      // info div 
      info = document.createElement('div'); 
      info.style.position = 'absolute'; 
      info.style.top = '10px'; 
      info.style.width = '100%'; 
      info.style.textAlign = 'center'; 
      //info.innerHTML = 'Drag to spin the cylinder<br/> You can identify cylinder face by clicking on it.</br>';   
      container.appendChild(info); 

      // camera 
      camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 1, 10000); 
      camera.position.set(30,10,10); 
      //camera.up = new THREE.Vector3(0, 1, 1); 

      // scene    
      scene = new THREE.Scene(); 
      camera.lookAt(scene.position); 

      // light    
      scene.add(new THREE.AmbientLight(0x404040)); 
      light = new THREE.DirectionalLight(0xffffff); 
      light.position.set(0, 1, 0); 
      scene.add(light); 

      // CONTROLS 
      controls = new THREE.TrackballControls(camera); 

      // Grid 
      geometry = new THREE.Geometry(); 
      geometry.vertices.push(new THREE.Vector3(- 500, 0, 0)); 
      geometry.vertices.push(new THREE.Vector3(500, 0, 0)); 

      for (var i = 0; i <= 20; i ++) { 

       line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0x000000, opacity: 0.2 })); 
       line.position.z = (i * 50) - 500; 
       scene.add(line); 

       line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0x000000, opacity: 0.2 })); 
       line.position.x = (i * 50) - 500; 
       line.rotation.y = 90 * Math.PI/180; 
       scene.add(line); 
      } 

      // extrudePath, Helix Curve 
      extrudePath = new THREE.SplineCurve3([ 
               new THREE.Vector3(0, 10, 10), 
               new THREE.Vector3(10, 0, 10), 
               new THREE.Vector3(10, 0, 0) 
              ]); 

      console.log(extrudePath); 

      // Tube Geometry 
      var segments = 50; 
      var closed = false; 
      var debug = true; 
      var radiusSegments = 12; 

      //alert('hello');      
      var tube = new THREE.TubeGeometry(extrudePath, segments, 2, radiusSegments, closed, debug); 

      // Tube Mesh 
      tubeMesh = THREE.SceneUtils.createMultiMaterialObject(tube, [ 
       new THREE.MeshLambertMaterial({ 
        color: 0xff00ff, 
        opacity: tube.debug ? 0.2 : 0.8, 
        transparent: true 
       }), 
       new THREE.MeshBasicMaterial({ 
        color: 0x000000, 
        opacity: 0.5, 
        wireframe: true 
      })]); 

      parent = new THREE.Object3D(); 
      parent.position.y = 100; 

      if (tube.debug) tubeMesh.add(tube.debug); 
      //parent.add(tubeMesh);     
      scene.add(tubeMesh); 

      // projector 
      projector = new THREE.Projector(); 

      // renderer 
      //renderer = new THREE.CanvasRenderer(); 
      renderer = new THREE.WebGLRenderer({ antialias: true }); 
      renderer.setSize(window.innerWidth, window.innerHeight); 
      container.appendChild(renderer.domElement);    

      // stats 
      stats = new Stats(); 
      stats.domElement.style.position = 'absolute'; 
      stats.domElement.style.top = '0px'; 
      container.appendChild(stats.domElement); 

      document.addEventListener('mousedown', onDocumentMouseDown, false); 
      document.addEventListener('mouseover', onDocumentMouseOver, false); 
      document.addEventListener('touchstart', onDocumentTouchStart, false); 
      document.addEventListener('touchmove', onDocumentTouchMove, false);    

      window.addEventListener('resize', onWindowResize, false); 

     }   

     function onWindowResize() { 

      camera.left = window.innerWidth/- 2; 
      camera.right = window.innerWidth/2; 
      camera.top = window.innerHeight/2; 
      camera.bottom = window.innerHeight/- 2; 
      camera.aspect = window.innerWidth/window.innerHeight; 
      //camera.updateProjectionMatrix(); 
      renderer.setSize(window.innerWidth, window.innerHeight); 

     } 

     function onDocumentMouseDown(event) { 
      event.preventDefault(); 

      document.addEventListener('mousemove', onDocumentMouseMove, false); 
      document.addEventListener('mouseup', onDocumentMouseUp, false); 
      document.addEventListener('mouseout', onDocumentMouseOut, false); 

      mouseXOnMouseDown = event.clientX - windowHalfX; 
      targetRotationOnMouseDown = targetRotation;   
     } 

     function onDocumentMouseMove(event) { 

      mouseX = event.clientX - windowHalfX; 

      targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02; 

     } 

     function onDocumentMouseUp(event) { 

      document.removeEventListener('mousemove', onDocumentMouseMove, false); 
      document.removeEventListener('mouseup', onDocumentMouseUp, false); 
      document.removeEventListener('mouseout', onDocumentMouseOut, false); 

     } 

     function onDocumentMouseOut(event) { 

      document.removeEventListener('mousemove', onDocumentMouseMove, false); 
      document.removeEventListener('mouseup', onDocumentMouseUp, false); 
      document.removeEventListener('mouseout', onDocumentMouseOut, false); 

     } 

     function onDocumentMouseOver(event) { 

      document.removeEventListener('mousemove', onDocumentMouseMove, false); 
      document.removeEventListener('mouseup', onDocumentMouseUp, false); 
      document.removeEventListener('mouseout', onDocumentMouseOut, false); 

     } 

     function onDocumentTouchStart(event) { 

      if (event.touches.length === 1) { 

       event.preventDefault(); 

       mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX; 
       targetRotationOnMouseDown = targetRotation; 

      } 

     } 

     function onDocumentTouchMove(event) { 
      if (event.touches.length === 1) { 
       event.preventDefault(); 
       mouseX = event.touches[ 0 ].pageX - windowHalfX; 
       targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05; 
      } 
     } 

     function animate() { 
      requestAnimationFrame(animate); 
      render(); 
      update(); 
     } 

     function update() 
     { 
      controls.update(); 
      stats.update(); 
     } 

     function render() {    
      tubeMesh.rotation.y += (targetRotation - tubeMesh.rotation.y) * 0.15;   
      camera.updateMatrixWorld(); 
      renderer.render(scene, camera); 
     }   

     </script> 
    </body> 
</html> 

現在,當我改變從WebGL的渲染到畫布中,FPS從56-57 FPS下降到1-2 FPS的手機瀏覽器。本地瀏覽器不會在頁面上顯示任何內容,並且Opera頁面對於操作而言變得太慢。如何通過Canvas渲染使頁面操作更快,或者如何在移動瀏覽器上啓用webgl渲染?

+4

使用的段的數量,因爲畫布渲染器不使用任何硬件加速。 – Neil

回答

2

畫布渲染器只是軟件模式,這意味着沒有GPU加速,CPU必須做所有的辛苦工作,這就是爲什麼你的FPS下降。 AFI不是所有的手機瀏覽器都能夠使用webgl渲染器,但是你可以給Opera手機一個嘗試它的能力的webgl。

1

一個加快畫布渲染的方法是減少我懷疑在TubeGeometry

+0

我可以減少細分的數量,但是細分的數量等於路徑的長度是有道理的。請看看我的另一個[問題](http://stackoverflow.com/questions/13767456/three-js-canvas-texture-on-tube-geometry-for-ipad) - @ zz85 – Valay