從0到1學習three.js(1)

咱們在這片文章裏不會上來就告訴你Three.js裏面有什麼方法,都該怎麼去使用;咱們想讓你先嚐試去使用Three.js,經過這個小例子但願能夠勾引發你的興趣;而後咱們會在後面的學習中慢慢的深刻Three.js的學習;慢慢來嘛,欲速則不達。javascript


先看看示例

開始前的準備

  • 編輯器
    推薦使用WebStrom或者Atom或者SublimeTextjquery

  • Three.js
    咱們學習Three.js固然要用到three.js,獲取的途徑有兩種;一種是直接在github上的Three.js克隆下載,另外一種方法是使用learning-threejs上的給你準備好的學習資料。我選擇的是第二種方法,由於那裏面還包含了許多咱們將使用到的庫。git

  • Web服務器
    在剛開始的學習中,咱們可能只會在一個頁面上書寫咱們的代碼;可是隨着學習的深刻,咱們可能會加載許多的材料,這時候就須要服務器來幫忙了。固然搭建一個本地的服務器也是十分容易的。若是你使用的編輯器是WebStrom的話,那麼就不須要搭建本地服務器了;由於經過WebStrom打開的頁面就是在WebStrom建立的服務器中運行的。angularjs

第一個示例

  • 引入文件庫github

    <script src="libs/three.js"></script>
    <script src="libs/jquery-1.9.0.js"></script>
    <script src="libs/stats.js"></script>
    <script src="libs/dat.gui.js"></script>

    注意,咱們上面引入的庫在文件夾learning-threejs裏面都有的。服務器

  • 書寫CSS和HTML代碼app

    body {
            margin: 0;
            overflow: hidden;
     }

    這些樣式文件是爲了防止裏面內容的溢出,去除了body的外邊距。dom

    <div id="container"></div>

    添加存放Three.js渲染內容的容器。

  • 添加場景,相機,渲染器

    // 添加場景
     var scene = new THREE.Scene();
     // 添加相機
     var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
     // 添加渲染器
     var renderer = new THREE.WebGLRenderer();

    場景就至關於一個畫板,相機至關於你的眼睛,渲染器至關於一支畫筆;這些是個人理解,若是你對這些概念不是很清楚的話,那也不要緊;學習Three.js還有很長的路要走,隨着學習的深刻,相信你會有本身的理解。

  • 設置場景大小,背景顏色

    // 設置場景的大小
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 設置場景的背景顏色 第一個參數是一個表示顏色的字符串或者16進制的數字
    renderer.setClearColor(0x000000);
  • 將場景元素添加到頁面,渲染場景

    // 選取頁面中的容器,將咱們的場景元素添加進去
    $('#container').append(renderer.domElement);
    // 渲染器渲染咱們的場景
    renderer.render(scene, camera);
  • 效果圖以下:
    圖片描述

    雖然看着十分簡單,可是這是咱們開始下面內容的基礎,繼續前進吧。

  • 添加一個座標軸

    // 新建座標軸
    var axis = new THREE.AxisHelper(20);
    // 在場景中添加座標軸
    scene.add(axis);
    
    /* 在設置了相機的位置以後才能夠看到座標軸 */
    
    // 設置相機的x座標位置
    camera.position.x = -30;
    // 設置相機的y座標位置
    camera.position.y = 40;
    // 設置相機的z座標的位置
    camera.position.z = 30;
    // 設置相機的焦點
    camera.lookAt(scene.position);
  • 效果圖以下:
    圖片描述

    圖二,添加了座標軸的場景。

  • 添加一個平面

    // 建立平面的骨架
    var planeGeometry = new THREE.PlaneBufferGeometry(60, 30, 1, 1);
    // 建立平面的材料
    var planeMaterial = new THREE.MeshBasicMaterial({color: '#aaaaaa'});
    // 合成平面
    var plane = new THREE.Mesh(planeGeometry, planeMaterial);
    // 設置平面的旋轉角度
    plane.rotation.x = -0.5 * Math.PI;
    // 設置平面的位置
    plane.position.x = 15;
    plane.position.y = 0;
    plane.position.z = 0;
    // 在場景中添加平面
    scene.add(plane);
  • 效果圖以下:
    圖片描述

    圖三,添加了座標軸的場景。

  • 添加一個立方體和一個球體

    // 建立立方體骨架
    var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
    // 建立立方體材料
    var cubeMaterial = new THREE.MeshBasicMaterial({color: 'yellow', wireframe: true});
    // 合成立方體
    var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    // 設置立方體位置
    cube.position.x = -8;
    cube.position.y = 4;
    cube.position.z = 0;
    // 在場景中添加立方體
    scene.add(cube);
    
    // 建立並在場景中添加球體
    var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
    var sphereMaterial = new THREE.MeshBasicMaterial({color: 'red', wireframe: true});
    var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
    sphere.position.x = 20;
    sphere.position.y = 10;
    sphere.position.z = 0;
    scene.add(sphere);
  • 效果圖以下:
    圖片描述

    圖四,添加了座標軸的場景。

  • 在場景中添加燈光

    // 建立燈光
    var spotLight = new THREE.SpotLight(0xffffff);
    // 設置燈光位置
    spotLight.position.set(-40, 60, -10);
    // 在場景中添加燈光
    scene.add(spotLight);

    添加燈光以後,你會發現頁面並無什麼變化;那是由於咱們在場景中添加的物體的材料是不會對光源產生任何反應的,因此咱們要改動一些東西,以下所示:

    /* 將構建物體的材料改變 */
    //var planeMaterial = new THREE.MeshBasicMaterial({color: '#aaaaaa'});
    var planeMaterial = new THREE.MeshLambertMaterial({color: '#aaaaaa'});
    
    //var cubeMaterial = new THREE.MeshBasicMaterial({color: 'yellow', wireframe: true});
    var cubeMaterial = new THREE.MeshLambertMaterial({color: 'yellow', wireframe: true});
    
    //var sphereMaterial = new THREE.MeshBasicMaterial({color: 'red', wireframe: true});
    var sphereMaterial = new THREE.MeshLambertMaterial({color: 'red', wireframe: true});
    
    /* 設置渲染器容許陰影映射 */
    renderer.shadowMapEnabled = true;
    
    /* 設置哪些物體投射陰影,那些物體接受陰影 */
    plane.receiveShadow = true;
    cube.castShadow = true;
    sphere.castShadow = true;
    spotLight.castShadow = true;
  • 效果圖以下:
    圖片描述

    圖五,添加了陰影映射的場景。

  • 添加監測動畫運行幀數的輔助庫

    var stats = initStats();
    
        renderScene();
    
        // 重複渲染場景
        function renderScene() {
            // 更新
            stats.update();
            // 使用requestAnimationFrame代替setInterval
            requestAnimationFrame(renderScene);
            // 渲染場景
            renderer.render(scene, camera);
        }
    
        // 初始化監測動畫運行頻幀庫stats
        function initStats() {
            var stats = new Stats();
            stats.setMode(0);
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            // 在頁面上面添加一個div,id爲stats
            $('#stats').append(stats.domElement);
            return stats;
        }
  • 爲立方體和球體添加動畫

    var stats = initStats();
        var step = 0;
        renderScene();
        // 重複渲染場景
        function renderScene() {
            // 更新
            stats.update();
            // 立方體的旋轉
            cube.rotation.x += 0.02;
            cube.rotation.y += 0.02;
            cube.rotation.z += 0.02;
            // 球體的彈跳
            step += 0.03;
            sphere.position.x = 20 + (10 * Math.cos(step));
            sphere.position.y = 0 + (10 * Math.sin(step));
            // 使用requestAnimationFrame代替setInterval
            requestAnimationFrame(renderScene);
            // 渲染場景
            renderer.render(scene, camera);
        }
        // 初始化監測動畫運行頻幀庫stats
        function initStats() {
            var stats = new Stats();
            stats.setMode(0);
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            // 在頁面上面添加一個div,id爲stats
            $('#stats').append(stats.domElement);
            return stats;
        }
  • 效果圖以下:
    圖片描述

    圖六,添加了動畫以及監測動畫運行頻幀場景。

  • 使用dat.GUI簡化測試

    // 定義咱們使用到的測試變量
        var controls = new function() {
            this.rotationSpeed = 0.02;
            this.bouncingSpeed = 0.03;
        };
    
        var gui = new dat.GUI();
        gui.add(controls, 'rotationSpeed', 0, 1);
        gui.add(controls, 'bouncingSpeed', 0, 1);
        
        // 使用上面的變量替換咱們的固定數據
        // 立方體的旋轉
        cube.rotation.x += controls.rotationSpeed;
        cube.rotation.y += controls.rotationSpeed;
        cube.rotation.z += controls.rotationSpeed;
    
        // 球體的彈跳
        step += controls.bouncingSpeed;
        sphere.position.x = 20 + (10 * Math.cos(step));
        sphere.position.y = 0 + (10 * Math.sin(step));
  • 效果圖以下:
    圖片描述

    圖七,最終造成的場景。

總結

  • 最終的javascript代碼部分

    $(function() {
    
        var controls = new function() {
            this.rotationSpeed = 0.02;
            this.bouncingSpeed = 0.03;
        };
    
        var gui = new dat.GUI();
        gui.add(controls, 'rotationSpeed', 0, 1);
        gui.add(controls, 'bouncingSpeed', 0, 1);
    
        // 添加場景
        var scene = new THREE.Scene();
        // 添加相機
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 添加渲染器
        var renderer = new THREE.WebGLRenderer();
        // 設置場景的大小
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 設置場景的背景顏色
        renderer.setClearColor(0x000000);
        // 設置渲染器容許陰影映射
        renderer.shadowMapEnabled = true;
    
        // 新建座標軸
        var axis = new THREE.AxisHelper(20);
        // 在場景中添加座標軸
        scene.add(axis);
    
        // 建立平面的骨架
        var planeGeometry = new THREE.PlaneBufferGeometry(60, 30, 1, 1);
        // 建立平面的材料
    //    var planeMaterial = new THREE.MeshBasicMaterial({color: '#aaaaaa'});
        var planeMaterial = new THREE.MeshLambertMaterial({color: '#aaaaaa'});
        // 合成平面
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);
        plane.receiveShadow = true;
    
        // 設置平面的旋轉角度
        plane.rotation.x = -0.5 * Math.PI;
        // 設置平面的位置
        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;
        // 在場景中添加平面
        scene.add(plane);
    
        // 建立立方體骨架
        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        // 建立立方體材料
    //    var cubeMaterial = new THREE.MeshBasicMaterial({color: 'yellow', wireframe: true});
        var cubeMaterial = new THREE.MeshLambertMaterial({color: 'yellow', wireframe: true});
        // 合成立方體
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.castShadow = true;
        // 設置立方體位置
        cube.position.x = -8;
        cube.position.y = 4;
        cube.position.z = 0;
        // 在場景中添加立方體
        scene.add(cube);
    
        // 建立並在場景中添加球體
        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
    //    var sphereMaterial = new THREE.MeshBasicMaterial({color: 'red', wireframe: true});
        var sphereMaterial = new THREE.MeshLambertMaterial({color: 'red', wireframe: true});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
        sphere.castShadow = true;
        sphere.position.x = 20;
        sphere.position.y = 10;
        sphere.position.z = 0;
        scene.add(sphere);
    
        // 建立燈光
        var spotLight = new THREE.SpotLight(0xffffff);
        // 設置燈光位置
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        // 在場景中添加燈光
        scene.add(spotLight);
    
        // 設置相機的x座標位置
        camera.position.x = -30;
        // 設置相機的y座標位置
        camera.position.y = 40;
        // 設置相機的z座標的位置
        camera.position.z = 30;
        // 設置相機的焦點
        camera.lookAt(scene.position);
    
        // 選取頁面中的容器,將咱們的場景元素添加進去
        $('#container').append(renderer.domElement);
    
    
        var stats = initStats();
        var step = 0;
    
        renderScene();
    
        // 重複渲染場景
        function renderScene() {
            // 更新
            stats.update();
    
            // 立方體的旋轉
            cube.rotation.x += controls.rotationSpeed;
            cube.rotation.y += controls.rotationSpeed;
            cube.rotation.z += controls.rotationSpeed;
    
            // 球體的彈跳
            step += controls.bouncingSpeed;
            sphere.position.x = 20 + (10 * Math.cos(step));
            sphere.position.y = 0 + (10 * Math.sin(step));
    
            // 使用requestAnimationFrame代替setInterval
            requestAnimationFrame(renderScene);
            // 渲染場景
            renderer.render(scene, camera);
        }
    
        // 初始化監測動畫運行頻幀庫stats
        function initStats() {
            var stats = new Stats();
            stats.setMode(0);
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            // 在頁面上面添加一個div,id爲stats
            $('#stats').append(stats.domElement);
            return stats;
        }
    })
  • 若是文中有什麼不足歡迎你們指出,咱們一塊兒進步。

這一系列文章大都參考了《Learning Three.js》

相關文章
相關標籤/搜索