zoukankan      html  css  js  c++  java
  • 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入门指南》

     

  • 相关阅读:
    PAT 甲级 1015 Reversible Primes (20 分) (进制转换和素数判断(错因为忘了=))
    『Spring.NET+NHibernate+泛型』框架搭建之DAO(三)★
    (C#)使用队列(Queue)解决简单的并发问题
    VB.NET多线程入门
    Machine Learning With Spark学习笔记(在10万电影数据上训练、使用推荐模型)
    JAVA 并发编程-多个线程之间共享数据(六)
    POJ 3087 Shuffle&#39;m Up(模拟)
    cocos2dx --- 富文本的使用 RichText
    &lt;LeetCode OJ&gt; 217./219. Contains Duplicate (I / II)
    java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
  • 原文地址:https://www.cnblogs.com/xulei1992/p/5740442.html
Copyright © 2011-2022 走看看