2017-07-17 501 views
1

我是一個初學者,通常使用three.js和3d圖形。這對我來說主要是一個學習練習。在three.js中使用MeshStandardMaterial的黑色未反射面孔

我試圖展示一個金屬外觀的十二面體,但是大約一半的面是黑色的並且沒有反映出來。其他面貌看起來是正確的。

我知道有一個內置的函數生成一個十二面體,並且還計算法線,但我想這樣做手工來檢查我的理解。

起初我以爲頂點法線可能會有問題,但使用VertexNormalsHelper,看起來法線都指向正確的方向。

任何人都可以告訴我我要去哪裏錯了嗎?非常感謝!

代碼:

<!DOCTYPE html> 
<html lang="en"> 
    <head> 
     <title>shiny dodecahedron</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 { 
       background:#000; 
       color:#fff; 
       padding:0; 
       margin:0; 
       font-weight: bold; 
       overflow:hidden; 
      } 
      a { color: #ffffff; } 
      #info { 
       position: absolute; 
       top: 0px; width: 100%; 
       color: #ffffff; 
       padding: 5px; 
       font-family:Monospace; 
       font-size:13px; 
       text-align:center; 
      } 
      #vt { display:none } 
      #vt, #vt a { color:orange; } 
     </style> 
    </head> 

    <body> 

     <div id="info"> 
      <span id="description">Dodecahedron standard material demo.</span> 
     </div> 

     <script src="js/three.js"></script> 
     <script src="js/controls/OrbitControls.js"></script> 

     <script src="js/Detector.js"></script> 
     <script src="js/libs/stats.min.js"></script> 
     <script src='js/libs/dat.gui.min.js'></script> 

     <script> 
      if (! Detector.webgl) Detector.addGetWebGLMessage(); 
      var stats; 
      var camera, scene, renderer; 
      var settings = { 
       metalness: 1.0, 
       roughness: 0.4, 
       ambientIntensity: 0.2 
      }; 
      var mesh, material; 
      var directionalLight, ambientLight; 
      var mouseX = 0; 
      var mouseY = 0; 
      var windowHalfX = window.innerWidth/2; 
      var windowHalfY = window.innerHeight/2; 
      var height = 500; // of camera frustum 
      var r = 0.0; 

      var GOLDEN_RATIO = (1 + Math.sqrt(5))/2; 

      var scaleFactor = 1/(1+GOLDEN_RATIO); 

      var explicitDodecahedronVertices = new Float32Array([ 
       (2*Math.cos(2*0*Math.PI/5)), (2*Math.sin(2*0*Math.PI/5)), GOLDEN_RATIO+1, // 0 
       (2*Math.cos(2*1*Math.PI/5)), (2*Math.sin(2*1*Math.PI/5)), GOLDEN_RATIO+1, // 1 
       (2*Math.cos(2*2*Math.PI/5)), (2*Math.sin(2*2*Math.PI/5)), GOLDEN_RATIO+1, // 2 
       (2*Math.cos(2*3*Math.PI/5)), (2*Math.sin(2*3*Math.PI/5)), GOLDEN_RATIO+1, // 3 
       (2*Math.cos(2*4*Math.PI/5)), (2*Math.sin(2*4*Math.PI/5)), GOLDEN_RATIO+1, // 4 

       (2*GOLDEN_RATIO*Math.cos(2*0*Math.PI/5)), (2*GOLDEN_RATIO*Math.sin(2*0*Math.PI/5)), GOLDEN_RATIO-1, // 5 
       (2*GOLDEN_RATIO*Math.cos(2*1*Math.PI/5)), (2*GOLDEN_RATIO*Math.sin(2*1*Math.PI/5)), GOLDEN_RATIO-1, // 6 
       (2*GOLDEN_RATIO*Math.cos(2*2*Math.PI/5)), (2*GOLDEN_RATIO*Math.sin(2*2*Math.PI/5)), GOLDEN_RATIO-1, // 7 
       (2*GOLDEN_RATIO*Math.cos(2*3*Math.PI/5)), (2*GOLDEN_RATIO*Math.sin(2*3*Math.PI/5)), GOLDEN_RATIO-1, // 8 
       (2*GOLDEN_RATIO*Math.cos(2*4*Math.PI/5)), (2*GOLDEN_RATIO*Math.sin(2*4*Math.PI/5)), GOLDEN_RATIO-1, // 9 

       (-2*GOLDEN_RATIO*Math.cos(2*0*Math.PI/5)), (-2*GOLDEN_RATIO*Math.sin(2*0*Math.PI/5)), -(GOLDEN_RATIO-1), // 10 
       (-2*GOLDEN_RATIO*Math.cos(2*1*Math.PI/5)), (-2*GOLDEN_RATIO*Math.sin(2*1*Math.PI/5)), -(GOLDEN_RATIO-1), // 11 
       (-2*GOLDEN_RATIO*Math.cos(2*2*Math.PI/5)), (-2*GOLDEN_RATIO*Math.sin(2*2*Math.PI/5)), -(GOLDEN_RATIO-1), // 12 
       (-2*GOLDEN_RATIO*Math.cos(2*3*Math.PI/5)), (-2*GOLDEN_RATIO*Math.sin(2*3*Math.PI/5)), -(GOLDEN_RATIO-1), // 13 
       (-2*GOLDEN_RATIO*Math.cos(2*4*Math.PI/5)), (-2*GOLDEN_RATIO*Math.sin(2*4*Math.PI/5)), -(GOLDEN_RATIO-1), // 14 

       (-2*Math.cos(2*0*Math.PI/5)), (-2*Math.sin(2*0*Math.PI/5)), -(GOLDEN_RATIO+1), // 15 
       (-2*Math.cos(2*1*Math.PI/5)), (-2*Math.sin(2*1*Math.PI/5)), -(GOLDEN_RATIO+1), // 16 
       (-2*Math.cos(2*2*Math.PI/5)), (-2*Math.sin(2*2*Math.PI/5)), -(GOLDEN_RATIO+1), // 17 
       (-2*Math.cos(2*3*Math.PI/5)), (-2*Math.sin(2*3*Math.PI/5)), -(GOLDEN_RATIO+1), // 18 
       (-2*Math.cos(2*4*Math.PI/5)), (-2*Math.sin(2*4*Math.PI/5)), -(GOLDEN_RATIO+1), // 19 
      ]); 

      var dodecahedronFaceIndexes = new Uint8Array([ 
       // one of pair of opposite pentagons parallel to xy plane 
       // 0, 1, 2, 3, 4 
       1, 3, 0, 
       1, 2, 3, 
       0, 3, 4, 

       // 0, 4, 5, 9, 12 
       4, 12, 0, 
       12, 5, 0, 
       12, 4, 9, 

       // 3, 4, 8, 9, 11 
       3, 11, 4, 
       3, 8, 11, 
       4, 11, 9, 

       // 2, 3, 7, 8, 10 
       2, 10, 3, 
       2, 7, 10, 
       3, 10, 8, 

       // 1, 2, 6, 7, 14 
       1, 14, 2, 
       1, 6, 14, 
       2, 14, 7, 

       // 0, 1, 5, 6, 13 
       0, 13, 1, 
       0, 5, 13, 
       1, 13, 6, 


       // 15, 16, 17, 18, 19 
       15, 18, 16, 
       15, 19, 18, 
       16, 18, 17, 

       // 15, 19, 10, 14, 7 
       15, 7, 19, 
       15, 10, 7, 
       19, 7, 14, 

       // 18, 19, 13, 14, 6 
       19, 6, 18, 
       6, 13, 18, 
       6, 19, 14, 

       // 17, 18, 12, 13, 5 
       18, 5, 17, 
       5, 12, 17, 
       5, 18, 13, 

       // 16, 17, 11, 12, 9 
       17, 9, 16, 
       9, 11, 16, 
       9, 17, 12, 

       // 15, 16, 10, 11, 8 
       16, 8, 15, 
       8, 10, 15, 
       8, 16, 11 
      ]); 



      var vertices; 
      var normals; 

      function ComputeVerticesNormals(){ 
       localVertices = []; 
       localNormals = []; 

       for (var i = 0; i < dodecahedronFaceIndexes.length; i += 3) 
       { 
        var i1 = dodecahedronFaceIndexes[i] * 3; 
        var i2 = dodecahedronFaceIndexes[i + 1] * 3; 
        var i3 = dodecahedronFaceIndexes[i + 2] * 3; 

        // get the vertices for this triangular pentagon segement 
        var ax = explicitDodecahedronVertices[i1]; 
        var ay = explicitDodecahedronVertices[i1 + 1]; 
        var az = explicitDodecahedronVertices[i1 + 2]; 

        var bx = explicitDodecahedronVertices[i2]; 
        var by = explicitDodecahedronVertices[i2 + 1]; 
        var bz = explicitDodecahedronVertices[i2 + 2]; 

        var cx = explicitDodecahedronVertices[i3]; 
        var cy = explicitDodecahedronVertices[i3 + 1]; 
        var cz = explicitDodecahedronVertices[i3 + 2]; 

        // calc normals 
        var ux = bx - ax; 
        var uy = by - ay; 
        var uz = bz - az; 

        var vx = bx - cx; 
        var vy = by - cy; 
        var vz = bz - cz; 

        var nx = (uz * vy) - (uy * vz); 
        var ny = (ux * vz) - (uz * vx); 
        var nz = (uy * vx) - (ux * vy); 

        // append vertices, normals to list 
        localVertices.push(ax, ay, az, bx, by, bz, cx, cy, cz); 
        localNormals.push(nx, ny, nz, nx, ny, nz, nx, ny, nz) 
       } 

       vertices = Float32Array.from(localVertices); 
       normals = Float32Array.from(localNormals); 
      } 



      init(); 
      animate(); 

      function init() { 
       var container = document.createElement('div'); 
       document.body.appendChild(container); 
       renderer = new THREE.WebGLRenderer(); 
       renderer.setPixelRatio(window.devicePixelRatio); 
       renderer.setSize(window.innerWidth, window.innerHeight); 
       container.appendChild(renderer.domElement); 
       renderer.gammaInput = true; 
       renderer.gammaOutput = true; 
       // 
       scene = new THREE.Scene(); 
       var aspect = window.innerWidth/window.innerHeight; 
       camera = new THREE.OrthographicCamera(- height * aspect, height * aspect, height, - height, 1, 10000); 
       camera.position.z = 400; 
       scene.add(camera); 
       controls = new THREE.OrbitControls(camera, renderer.domElement); 
       controls.enableZoom = false; 
       controls.enableDamping = true; 

       // lights 
       ambientLight = new THREE.AmbientLight(0xffffff, settings.ambientIntensity); 
       scene.add(ambientLight); 

       directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); 
       directionalLight.position.set(-50*32,0,0); 

       scene.add(directionalLight); 

       var path = "https://threejs.org/examples/textures/cube/SwedishRoyalCastle/"; 
       var format = '.jpg'; 
       var urls = [ 
         path + 'px' + format, path + 'nx' + format, 
         path + 'py' + format, path + 'ny' + format, 
         path + 'pz' + format, path + 'nz' + format 
        ]; 


       var loader = new THREE.CubeTextureLoader(); 
       loader.setCrossOrigin('anonymous'); 
       var reflectionCube = loader.load(urls); 
       reflectionCube.format = THREE.RGBFormat; 

       scene.background = reflectionCube; 


       material = new THREE.MeshStandardMaterial({ 
        color: 0x888888, 
        roughness: settings.roughness, 
        metalness: settings.metalness, 
        side: THREE.FrontSide, 
        envMap: reflectionCube 
       }); 

       var geometry = new THREE.BufferGeometry(); 
       ComputeVerticesNormals(); 

       geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3)); 
       geometry.addAttribute('normal', new THREE.BufferAttribute(normals, 3)); 

       geometry.center(); 
       mesh = new THREE.Mesh(geometry, material); 
       mesh.scale.multiplyScalar(100); 

       scene.add(mesh); 

       var vnh = new THREE.VertexNormalsHelper(mesh, 100, 0x00ff00, 1); 

       scene.add (vnh); 


       stats = new Stats(); 
       container.appendChild(stats.dom); 
       // 
       window.addEventListener('resize', onWindowResize, false); 
      } 
      function onWindowResize() { 
       var aspect = window.innerWidth/window.innerHeight; 
       camera.left = - height * aspect; 
       camera.right = height * aspect; 
       camera.top = height; 
       camera.bottom = - height; 
       camera.updateProjectionMatrix(); 
       renderer.setSize(window.innerWidth, window.innerHeight); 
      } 
      // 
      function animate() { 
       requestAnimationFrame(animate); 
       controls.update(); 
       stats.begin(); 
       render(); 
       stats.end(); 
      } 
      function render() { 
       renderer.render(scene, camera); 
      } 
     </script> 

    </body> 

</html> 
+0

爲了正確渲染 - 尤其是對金屬 - 'MeshStandardMaterial'需要一個環境地圖('material.envMap'),所以有什麼反映。看看這是否是你的問題。 – WestLangley

+0

感謝您的評論 - 我添加了一張環境地圖,看起來好多了。環境地圖現在可以正確反映所有人臉。但是,光似乎只反映了大約一半的面孔,所以東西似乎仍然是錯誤的... – Zakalwe

+0

的定向光只會liluminate模型的一側。 – WestLangley

回答

0

由於WestLangley的評論,我意識到錯誤是在我的理解THREE.OrbitControls。我錯誤地認爲攝像機是靜態的,模型是旋轉的,而實際上卻是相反的 - 模型是靜態的,攝像機在模型中移動。