Three.js入門


  

  什么是WebGL。WebGL是在瀏覽器中實現三維效果的一套規范。使用WebGL原生的API來寫3D程序是一件非常痛苦的事情,幸好,有很多同行花業余時間寫了一些WebGL開源框架,其中three.js就是非常優秀的一個。

  什么是threejs,很簡單,你將它理解成three + js就可以了。three表示3D的意思,js表示javascript的意思。那么合起來,three.js就是使用javascript 來寫3D程序的意思。

   three.js官網地址:https://threejs.org/

記錄兩個git地址:

https://github.com/josdirksen/learning-threejs  Three.js開發指南一書對應的源碼

https://github.com/mrdoob/three.js      對three.js的封裝,更加強大。

 

1.入門程序

  1 <!DOCTYPE html>
  2 
  3 <html>
  4 
  5 <head>
  6     <title>Example 01.02 - First Scene</title>
  7     <script type="text/javascript" src="../libs/three.js"></script>
  8     <style>
  9         body {
 10             /* set margin to 0 and overflow to hidden, to go fullscreen */
 11             margin: 0;
 12             overflow: hidden;
 13         }
 14     </style>
 15 </head>
 16 <body>
 17 
 18 <!-- Div which will hold the Output -->
 19 <div id="WebGL-output">
 20 </div>
 21 
 22 <!-- Javascript code that runs our Three.js examples -->
 23 <script type="text/javascript">
 24 
 25     // once everything is loaded, we run our Three.js stuff.
 26     function init() {
 27 
 28         // create a scene, that will hold all our elements such as objects, cameras and lights.
 29         var scene = new THREE.Scene();
 30 
 31         // create a camera, which defines where we're looking at.
 32         var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
 33 
 34         // create a render and set the size
 35         var renderer = new THREE.WebGLRenderer();
 36         renderer.setClearColorHex();
 37         renderer.setClearColor(new THREE.Color(0xEEEEEE));
 38         renderer.setSize(window.innerWidth, window.innerHeight);
 39 
 40         // show axes in the screen
 41         var axes = new THREE.AxisHelper(20);
 42         scene.add(axes);
 43 
 44         // create the ground plane
 45         var planeGeometry = new THREE.PlaneGeometry(60, 20);
 46         var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc});
 47         var plane = new THREE.Mesh(planeGeometry, planeMaterial);
 48 
 49         // rotate and position the plane
 50         plane.rotation.x = -0.5 * Math.PI;
 51         plane.position.x = 15;
 52         plane.position.y = 0;
 53         plane.position.z = 0;
 54 
 55         // add the plane to the scene
 56         scene.add(plane);
 57 
 58         // create a cube
 59         var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
 60         var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
 61         var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
 62 
 63         // position the cube
 64         cube.position.x = -4;
 65         cube.position.y = 3;
 66         cube.position.z = 0;
 67 
 68         // add the cube to the scene
 69         scene.add(cube);
 70 
 71         // create a sphere
 72         var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
 73         var sphereMaterial = new THREE.MeshBasicMaterial({color: 0x7777ff, wireframe: true});
 74         var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
 75 
 76         // position the sphere
 77         sphere.position.x = 20;
 78         sphere.position.y = 4;
 79         sphere.position.z = 2;
 80 
 81         // add the sphere to the scene
 82         scene.add(sphere);
 83 
 84         // position and point the camera to the center of the scene
 85         camera.position.x = -30;
 86         camera.position.y = 40;
 87         camera.position.z = 30;
 88         camera.lookAt(scene.position);
 89 
 90         // add the output of the renderer to the html element
 91         document.getElementById("WebGL-output").appendChild(renderer.domElement);
 92 
 93         // render the scene
 94         renderer.render(scene, camera);
 95     }
 96     window.onload = init;
 97 
 98 </script>
 99 </body>
100 </html>

結果:

上面包含的物體:

 

 解釋:

    28-38行代碼:

  首先定義了場景(Scene)、攝像機(camera)和渲染器(renderer)對象。場景是一個容器,主要用於保存、跟蹤所要渲染的物體和使用的光源,如果沒有THEE.Scene對象,那么Three.js無法渲染任何對象。攝像機決定了能夠在場景中看到什么。渲染器會基於攝像機的角度來計算場景對象在瀏覽器中會渲染成什么樣子。最后WebGLRendere將會使用電腦顯卡來渲染場景。(除了基於WebGL的渲染器還有基於畫板和SVG的渲染器,不推薦使用,因為太消耗CPU)。

  上面代碼,renderer.setClearColorHex(); renderer.setClearColor(new THREE.Color(0xEEEEEE)); 將場景的背景顏色設置為接近白色,renderer.setSize(window.innerWidth, window.innerHeight);設置場景的大小。如果將上面代碼修改為下面代碼再次查看效果:

      renderer.setClearColor(new THREE.Color(0xEEEE00));
        renderer.setSize(500, 500);

 

 40行-56行:

  到上面已經創建了空白的場景、渲染器和攝像機,但是沒有渲染任何東西,40-56行的代碼會添加軸和平面。

  var axes = new THREE.AxisHelper(20);創建了軸(axes)對象,參數指定了線條的長度,並調用scene.add方法將軸添加到場景中。

  接下來創建了平面plane,平面的創建分為兩步。首先是要  new THREE.PlaneGeometry(60, 20); 來定義平面的大小,寬度指定為60、高度設置為20,除了設置寬度和高度,我們還需要設置平面的外觀(比如顏色和透明度),在three.js中通過創建材質對象來設置平面的外觀,例子中用  new THREE.MeshBasicMaterial({color: 0xcccccc});  創建了顏色為 0xcccccc 的基本材質(THREE.MeshBasicMaterial) ,然后 new THREE.Mesh(planeGeometry, planeMaterial);  將平面和材質合並到名為plane的網格對象中。在平面添加到場景之前,還需要設置平面的位置:先將平面繞x軸旋轉90度,然后使用  position  屬性指定在場景中位置。最后將平面添加到場景中。

 

    58-82行:

     使用同樣的方式將方塊和球體添加到平面。但是需要將線框(wireframe)屬性設置為true,這樣物體就不會被渲染為實體。如果 wireframe 設置為false,渲染為實體效果如下:

    

 

     84-94行:

     現在,所以物體都已經加載到場景中。之前也說了攝像機將決定看到哪些物體。在這段代碼中,我們使用x,y,z屬性來設置攝像機的位置。為了確保所要渲染的物體能夠被攝像機拍到,我們使用lookAt方法指向場景的中心,默認狀態下攝像機是指向(0,0,0)位置的。最后要做的就是將渲染結果添加到HTML的div元素中。最后告訴渲染器使用指定的攝像機來渲染場景。

  如果我們將攝像機的x軸的位置改為0,  camera.position.x = 0;  效果如下:

 

補充:攝像機的位置決定了看到哪些物體,也就決定了角度。也可以通過set方法設置其位置,如下:

camera.position.set(-30,48,30);

其有很多方法,如下: (我們用webstorm編輯器的時候會自動提示)

 

2.添加材質、光源和陰影效果

<!DOCTYPE html>

<html>

<head>
    <title>Example 01.03 - Materials and light</title>
    <script type="text/javascript" src="../libs/three.js"></script>
    <script type="text/javascript" src="../libs/stats.js"></script>
    <script type="text/javascript" src="../libs/dat.gui.js"></script>
    <style>
        body {
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

    // once everything is loaded, we run our Three.js stuff.
    function init() {

        // create a scene, that will hold all our elements such as objects, cameras and lights.
        var scene = new THREE.Scene();

        // create a camera, which defines where we're looking at.
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        // create a render and set the size
        var renderer = new THREE.WebGLRenderer();

        renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;

        // create the ground plane
        var planeGeometry = new THREE.PlaneGeometry(60, 20);
        var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);
        plane.receiveShadow = true;

        // rotate and position the plane
        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;

        // add the plane to the scene
        scene.add(plane);

        // create a cube
        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.castShadow = true;

        // position the cube
        cube.position.x = -4;
        cube.position.y = 3;
        cube.position.z = 0;

        // add the cube to the scene
        scene.add(cube);

        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
        var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

        // position the sphere
        sphere.position.x = 20;
        sphere.position.y = 4;
        sphere.position.z = 2;
        sphere.castShadow = true;

        // add the sphere to the scene
        scene.add(sphere);

        // position and point the camera to the center of the scene
        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);

        // add the output of the renderer to the html element
        document.getElementById("WebGL-output").appendChild(renderer.domElement);

        // call the render function
        renderer.render(scene, camera);
    }
    window.onload = init;


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

結果:

 

 2.1添加光源

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);

 

   通過THREE.SpotLight定義光源並從其位置( spotLight.position.set(-40, 60, -10);) 照射場景。如果這時候渲染場景我們看到的結果和沒光源是一樣的。因為不同的材質對光源的反應是不一樣的。我們使用的基本材質(THREE.MeshBasicMaterial)不會對光源產生任何反應,基本材質只會使用指定的顏色來渲染物體。所以需要改變平面、球體、和立方體的材質為  THREE.MeshLambertMaterial  即可。Three.js中的材質THREE.MeshLambertMaterial 和  THREE.MeshPhongMaterial在渲染時會對光源產生反應。

2.2  渲染陰影

  由於渲染陰影需要消耗大量的計算資源,默認情況Three.js不會渲染陰影,為了渲染陰影效果,我們需要作如下:

renderer.shadowMapEnabled = true;   首先渲染器的此屬性設為true告訴渲染器需要陰影效果。

另外還要指定哪個物體投射陰影、哪個物體接受陰影。如下平面接受陰影,小球和方體發出陰影:

plane.receiveShadow = true;
cube.castShadow = true;
sphere.castShadow = true;

 

最后還要指定光源產生陰影,因為並不是所有的光源都能產生陰影,THREE.SpotLight是能產生陰影的,我們只需要將castShadow屬性設置為true就可以將陰影渲染出來。

 

 

3.場景動起來

   如果希望場景動起來,首先需要解決的問題是如何在特定的時間間隔重新渲染場景。原生的JS是通過setInterval(fun,interval)來實現的,這個方法的缺點是不管瀏覽器正在發生什么都會執行定時作業。

1.引入  requestAnimationFrame(render);

  在這個方法中可以定義所有的繪畫操作,瀏覽器會盡可能平滑、高效地進行繪制。使用這個  requestAnimationFrame(); 的方法很簡單,只需要創建一個處理渲染的方法即可:

        function render() {
            ...
            // render using requestAnimationFrame
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

  在render()方法中  requestAnimationFrame() 方法又一次被調用了,這樣做的目的是保證會話能持續運行。接下來需要做的就是:場景創建完畢之后不再調用render.render()方法,而是調用render()方法來啟動動畫,代碼如下:

 document.getElementById("Stats-output").appendChild(stats.domElement);
 render();

 

 

  這時候運行代碼和之前是一樣的,因為還沒有為物體添加任何動畫效果。在添加動畫之前,我們先來介紹一個輔助庫,這個庫也是Three.js作者開發的,主要用於檢測動畫運行時的幀數。在動畫運行時,該庫可以在一個圖片中顯示畫面每秒傳輸幀數。

  輔助庫:

<script type="text/javascript" src="../libs/stats.js"></script>

  界面添加元素:

<div id="Stats-output"></div>

 

   初始化統計對象,並將該對象添加到<div>元素中:

        function initStats() {

            var stats = new Stats();

            stats.setMode(0); // 0: fps, 1: ms

            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';

            document.getElementById("Stats-output").appendChild(stats.domElement);

            return stats;
        }

  這里需要注意setMode()方法。如果參數設置為 0 ,那么我們檢測的是畫面每秒傳輸幀數(fps); 如果參數設置為1,那么我們檢測的是畫面渲染時間。一般統計fps(Frames Per Second)。為了使具有統計功能,需要在一開始調用initStats()方法。

var stats = initStats();

  為了能夠通知stats對象畫面何時被重新渲染,我們在render()方法需要調用stats.update()方法:

        function render() {
            stats.update();
            // render using requestAnimationFrame
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

 2.  旋轉立方體和彈跳的小球

<!DOCTYPE html>

<html>

<head>
    <title>Example 01.04 - Materials, light and animation</title>
    <script type="text/javascript" src="../libs/three.js"></script>

    <script type="text/javascript" src="../libs/stats.js"></script>
    <style>
        body {
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

    // once everything is loaded, we run our Three.js stuff.
    function init() {

        var stats = initStats();

        // create a scene, that will hold all our elements such as objects, cameras and lights.
        var scene = new THREE.Scene();

        // create a camera, which defines where we're looking at.
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        // create a render and set the size
        var renderer = new THREE.WebGLRenderer();

        renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;

        // create the ground plane
        var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);
        var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);
        plane.receiveShadow = true;

        // rotate and position the plane
        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;

        // add the plane to the scene
        scene.add(plane);

        // create a cube
        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.castShadow = true;

        // position the cube
        cube.position.x = -4;
        cube.position.y = 3;
        cube.position.z = 0;

        // add the cube to the scene
        scene.add(cube);

        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
        var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

        // position the sphere
        sphere.position.x = 20;
        sphere.position.y = 0;
        sphere.position.z = 2;
        sphere.castShadow = true;

        // add the sphere to the scene
        scene.add(sphere);

        // position and point the camera to the center of the scene
        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

        // add subtle ambient lighting
        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);

        // add the output of the renderer to the html element
        document.getElementById("WebGL-output").appendChild(renderer.domElement);

        // call the render function
        var step = 0;
        renderScene();

        function renderScene() {
            stats.update();
            // rotate the cube around its axes
            cube.rotation.x += 0.02;
            cube.rotation.y += 0.02;
            cube.rotation.z += 0.02;

            // bounce the sphere up and down
            step += 0.04;
            sphere.position.x = 20 + ( 10 * (Math.cos(step)));
            sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));

            // render using requestAnimationFrame
            requestAnimationFrame(renderScene);
            renderer.render(scene, camera);
        }

        function initStats() {

            var stats = new Stats();

            stats.setMode(0); // 0: fps, 1: ms

            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';

            document.getElementById("Stats-output").appendChild(stats.domElement);

            return stats;
        }
    }
    window.onload = init;
</script>
</body>
</html>

 

解釋:

  立方體旋轉:在每次調用 renderScene() 方法的時候使得每個坐標軸的ration屬性加0.2,其效果就是立方體將圍繞它的軸進行緩慢的旋轉。

  旋轉立方體改變的是rotation屬性;而讓小球彈跳起來,我們所要做的是修改球體在場景中的位置(position)屬性,我們的目的是讓小球依照一條好看的、光滑的曲線從一個地方跳到另一個地方,如下:

  實現上面效果需要同時改變球體的x軸和y軸的位置,Math.cos()和Math.sin()方法使用step變量就可以創建出球體的運行軌跡。step+=0.4定義了球體的彈跳速度。

 

3.使用dat.GUI簡化實驗流程

  這個庫可以很容易地創建出能夠改變代碼變量的界面組件。

  像引入統計對象一樣,我們需要引入類庫:

<script type="text/javascript" src="../libs/dat.gui.js"></script>

  接下來定義一個JS對象,該對象希望通過dat.GUI改變的屬性。在JS代碼中添加如下JS對象:

        var controls = new function () {
            this.rotationSpeed = 0.02;
            this.bouncingSpeed = 0.03;
        };

 

  在上面對象中定義了兩個屬性---rotationSpeed、bouncingSpeed以及它們的默認值,接下來需要將這個JS對象傳遞給data.GUI對象,並設置這兩個屬性的取值范圍:

        var gui = new dat.GUI();
        gui.add(controls, 'rotationSpeed', 0, 0.5);
        gui.add(controls, 'bouncingSpeed', 0, 0.5);

  立方體旋轉速度和球體彈跳速度的取值范圍為0-0.5。現在需要在 render  中直接引用這兩個屬性,這樣當我們在dat.GUI中修改這兩個屬性的值時就可以影響到相應的物體的旋轉速度和彈跳速度,如下:

        function render() {
            stats.update();
            // rotate the cube around its axes
            cube.rotation.x += controls.rotationSpeed;
            cube.rotation.y += controls.rotationSpeed;
            cube.rotation.z += controls.rotationSpeed;

            // bounce the sphere up and down
            step += controls.bouncingSpeed;
            sphere.position.x = 20 + ( 10 * (Math.cos(step)));
            sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));

            // render using requestAnimationFrame
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

運行效果如下:

4.場景對瀏覽器的自適應

   當瀏覽器大小改變時改變攝像機很容易實現。首先需要為瀏覽器注冊一個事件監聽器,如下:

    // listen to the resize events
    window.addEventListener('resize', onResize, false);

  這樣,當瀏覽器尺寸改變時onResize()會被執行。在onResize()方法中需要更新攝像機和渲染器,如下:

    function onResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }

  對於攝像機,需要更新它的aspect屬性,這個屬性表示屏幕的長寬比;對於渲染器,需要改變它的尺寸。

例如:

<!DOCTYPE html>

<html>

<head>
    <title>Example 01.06 - Screen size change</title>
    <script type="text/javascript" src="../libs/three.js"></script>
    <script type="text/javascript" src="../libs/stats.js"></script>
    <script type="text/javascript" src="../libs/dat.gui.js"></script>
    <style>
        body {
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

    var camera;
    var scene;
    var renderer;

    // once everything is loaded, we run our Three.js stuff.
    function init() {

        var stats = initStats();

        // create a scene, that will hold all our elements such as objects, cameras and lights.
        scene = new THREE.Scene();

        // create a camera, which defines where we're looking at.
        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        // create a render and set the size
        renderer = new THREE.WebGLRenderer();

        renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;

        // create the ground plane
        var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);
        var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);
        plane.receiveShadow = true;

        // rotate and position the plane
        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;

        // add the plane to the scene
        scene.add(plane);

        // create a cube
        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.castShadow = true;

        // position the cube
        cube.position.x = -4;
        cube.position.y = 3;
        cube.position.z = 0;

        // add the cube to the scene
        scene.add(cube);

        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
        var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

        // position the sphere
        sphere.position.x = 20;
        sphere.position.y = 0;
        sphere.position.z = 2;
        sphere.castShadow = true;

        // add the sphere to the scene
        scene.add(sphere);

        // position and point the camera to the center of the scene
        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

        // add subtle ambient lighting
        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);

        // add the output of the renderer to the html element
        document.getElementById("WebGL-output").appendChild(renderer.domElement);

        // call the render function
        var step = 0;

        var controls = new function () {
            this.rotationSpeed = 0.02;
            this.bouncingSpeed = 0.03;
        };

        var gui = new dat.GUI();
        gui.add(controls, 'rotationSpeed', 0, 0.5);
        gui.add(controls, 'bouncingSpeed', 0, 0.5);

        render();

        function render() {
            stats.update();
            // rotate the cube around its axes
            cube.rotation.x += controls.rotationSpeed;
            cube.rotation.y += controls.rotationSpeed;
            cube.rotation.z += controls.rotationSpeed;

            // bounce the sphere up and down
            step += controls.bouncingSpeed;
            sphere.position.x = 20 + ( 10 * (Math.cos(step)));
            sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));

            // render using requestAnimationFrame
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

        function initStats() {

            var stats = new Stats();

            stats.setMode(0); // 0: fps, 1: ms

            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';

            document.getElementById("Stats-output").appendChild(stats.domElement);

            return stats;
        }
    }
    function onResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }


    window.onload = init;

    // listen to the resize events
    window.addEventListener('resize', onResize, false);

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

 

補充:Three.js用的是右手坐標系,看起來是這樣的:

 

總結:

  了解到three.js的3個基本組件:場景(scene)、相機(camera)、渲染器(render),以及其基本使用。場景是一個容器,主要用於保存、跟蹤所要渲染的物體和使用的光源,如果沒有THEE.Scene對象,那么Three.js無法渲染任何對象。攝像機決定了能夠在場景中看到什么,其位置也決定了渲染的角度。渲染器會基於攝像機的角度來計算場景對象在瀏覽器中會渲染成什么樣子。

  也學習了兩個調試組件:stats監控幀數和dat.GUI創建能夠改變代碼變量的界面組件。GUI界面顯示與隱藏的快捷鍵是H。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM