Three.js基礎探尋八——法向材質與材質的紋理貼圖


4.法向材質

  法向材質可以將材質的顏色設置為其法向量的方向,有時候對於調試很有幫助。

  法向材質的設定很簡單,甚至不用設置任何參數:

new THREE.MeshNormalMaterial()

  材質的顏色與照相機與該物體的角度相關,下面我們只改變照相機位置,觀察兩個角度的顏色變化:

  camera.position.set(5, 25, 25);的效果:

  camera.position.set(25, 25, 25);的效果:

  我們觀察的是同樣的三個面,但是由於觀察的角度不同,物體的顏色就不同了。因此,在調試時,要知道物體的法向量,使用法向材質就很有效。

  源碼:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>3.js測試8.1</title>
    </head>
    <body onload="init()">
        <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
    </body>
    <script type="text/javascript" src="js/three.min.js"></script>
    <script type="text/javascript">
        function init() {
            var renderer = new THREE.WebGLRenderer({
                canvas: document.getElementById('mainCanvas')
            });
            renderer.setClearColor(0x000000);
            var scene = new THREE.Scene();
            
            // camera
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);
            
            // light
            var light = new THREE.PointLight(0xffffff, 1, 100);
            light.position.set(10, 15, 5);
            scene.add(light);
            
            var material = new THREE.MeshNormalMaterial();
            
            var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5), material);
            scene.add(cube);
            
            renderer.render(scene, camera);
        }
    </script>
</html>

 

5.材質的紋理貼圖

  在此之前,我們使用的材質都是單一顏色的,有時候,我們卻希望使用圖像作為材質。這時候,就需要導入圖像作為紋理貼圖,並添加到相應的材質中。下面,我們介紹具體的做法。

  5.1 單張圖像應用於長方體

  首先,我們選擇一張長寬均為128像素的圖像:

  將其導入紋理中:

 

var texture = THREE.ImageUtils.loadTexture('img/0.png');

 

  然后,將材質的map屬性設置為texture:

var material = new THREE.MeshLambertMaterial({

    map: texture

});

  這樣就完成了將圖片應用於材質的基本步驟。但是由於現在我們還沒使用動畫,畫面只被渲染了一次,而在導入紋理之前,已經完成了這次渲染,因此看到的只是一片黑。所以,如果沒有重繪函數(將在下一篇介紹),就需要在完成導入紋理的步驟后,重新繪制畫面,這是在回調函數中實現的:

var texture = THREE.ImageUtils.loadTexture('img/0.png', {}, function() {

    renderer.render(scene, camera);

});

var material = new THREE.MeshLambertMaterial({

    map: texture

});

  現在,就能看到這樣的效果了:

  類似地,如果將其應用於球體,將會把整個球體應用該圖像:

  源碼:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>3.js測試8.2</title>
    </head>
    <body onload="init()">
        <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
    </body>
    <script type="text/javascript" src="js/three.min.js"></script> 
    <script type="text/javascript">
        function init() {
            var renderer = new THREE.WebGLRenderer({
                canvas: document.getElementById('mainCanvas')
            });
            renderer.setClearColor(0x000000);
            var scene = new THREE.Scene();
            
            // camera
            var camera = new THREE.OrthographicCamera(-10, 10, 7.5, -7.5, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);
            
            // light
            var light = new THREE.PointLight(0xffffff, 1, 1000);
            light.position.set(10, 15, 20);
            scene.add(light);
            
            var texture = THREE.ImageUtils.loadTexture('img/0.png', {}, function() {
                renderer.render(scene, camera);
            });
            var material = new THREE.MeshLambertMaterial({
                map: texture
            });
            
//          var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5), material);
//          scene.add(cube);
            var sphere = new THREE.Mesh(new THREE.SphereGeometry(5, 25, 15), material);
            scene.add(sphere);
            
            renderer.render(scene, camera);
        }
    </script>
</html>

 

  5.2 六張圖像應用於長方體

  有時候,我們希望長方體的六面各種的貼圖都不同。因此,我們首先准備了六張顏色各異的圖像,分別寫了數字0到5。然后,分別導入圖像到六個紋理,並設置到六個材質中:

var materials = [];

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

  materials.push(new THREE.MeshBasicMaterial({

    map: THREE.ImageUtils.loadTexture('img/' + i + '.png',

      {}, function() {

        renderer.render(scene, camera);

      }),

    overdraw: true

  }));

}

var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5),

  new THREE.MeshFaceMaterial(materials));

scene.add(cube);

  效果為:

  源碼:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>3.js測試8.3</title>
    </head>
    <body onload="init()">
        <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
    </body>
    <script type="text/javascript" src="js/three.min.js"></script>   
    <script type="text/javascript">
        function init() {
            var renderer = new THREE.WebGLRenderer({
                canvas: document.getElementById('mainCanvas')
            });
            renderer.setClearColor(0x000000);
            var scene = new THREE.Scene();
            
            // camera
            var camera = new THREE.OrthographicCamera(-10, 10, 7.5, -7.5, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);
            
            // light
            var light = new THREE.PointLight(0xffffff, 1, 1000);
            light.position.set(10, 15, 20);
            scene.add(light);
            
            var materials = [];
            for (var i = 0; i < 6; ++i) {
                materials.push(new THREE.MeshBasicMaterial({
                    map: THREE.ImageUtils.loadTexture('img/' + i + '.png', {}, function() {
                        renderer.render(scene, camera);
                    }),
                    overdraw: true
                }));
            }
            
            var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5),
                    new THREE.MeshFaceMaterial(materials));
            scene.add(cube);
            
            renderer.render(scene, camera);
        }
    </script>
</html>

 

  5.3 棋盤格

  現在,我們有一個黑白相間的圖像:

  我們希望用它填滿一個屏幕。按照之前的做法依法炮制:

var texture = THREE.ImageUtils.loadTexture('img/chess.png', {}, function() {

  renderer.render(scene, camera);

});

  效果是:

  可是,棋盤格是8橫8縱64個小方格組成的,那應該怎么辦呢?

  首先,我們需要指定重復方式為兩個方向(wrapS和wrapT)都重復:

texture.wrapS = texture.wrapT = THREE.RepeatWrapping;

  然后,設置兩個方向上都重復4次,由於我們的圖像本來是有2行2列,所以重復4次即為8行8列:

texture.repeat.set(4, 4);

  最終就得到了棋盤格:

  源碼:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>3.js測試8.4</title>
    </head>
    <body onload="init()">
        <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
    </body>
    <script type="text/javascript" src="js/three.min.js"></script>
    <script type="text/javascript">
        function init() {
            var renderer = new THREE.WebGLRenderer({
                canvas: document.getElementById('mainCanvas')
            });
            //renderer.setClearColor(0x666666);
            var scene = new THREE.Scene();
            
            // camera
            var camera = new THREE.OrthographicCamera(-10, 10, 7.5, -7.5, 0.1, 100);
            camera.position.set(0, 0, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);
            
            // light
            var light = new THREE.PointLight(0xffffff, 1, 1000);
            light.position.set(10, 15, 20);
            scene.add(light);
            
            var texture = THREE.ImageUtils.loadTexture('img/chess.png', {}, function() {
                renderer.render(scene, camera);
            });
            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            texture.repeat.set(4, 4);
            var material = new THREE.MeshLambertMaterial({
                map: texture
            });
            
            var plane = new THREE.Mesh(new THREE.PlaneGeometry(12, 12), material);
            scene.add(plane);
            
            renderer.render(scene, camera);
        }
    </script>
</html>

 

 

整理自張雯莉《Three.js入門指南》

 


免責聲明!

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



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