javascript我爱编程

Three.js

2017-09-16  本文已影响957人  就想叫菜鸟

Three.js

1. 概述

1.1 什么是Three.js

1.2 使用Three.js

<script type = "text/javascript" src = "three.js"></script>
//这样就可以通过全局变量THREE访问到所有的属性和方法。
var renderer = new THREE.WebGLRenderer({
    canvas: document.getElementById('mainCanvas')
});
var renderer = new THREE.WebGLRenderer();
renderer.setSize(400, 300);
document.getElementByTagName('body')[0].appendChild(renderer.domElement);
//document.body.appendChild(renderer.domElement);
//这里是将canvas元素添加到body中
renderer.setClearColor(0x000000);
var scene = new Three.Scene();
var camera = new THREE.PerspectiveCamera(45, 4/3, 1, 1000);
camera.position.set(0, 0, 5);
scene.add(camera);
//这里的照相机也需要被添加到场景中。
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
    new THREE.MeshBasicMaterial({
        color: 0xff0000
    });
);
 scene.add(cube);
renderer.render(scene, camera);

2. 照相机

2.1 什么是照相机

2.2 正交投影和透视投影

2.3 正交投影照相机

THREE.OrthographicCamera(left, right, top, bottom, near, far);
//这六个面围成一个长方体,我们将其称为视景体(Frustum)。

效果图为:


此处输入图片的描述此处输入图片的描述
var camera = THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera);

1. 为了试验长度比例变化时的效果,我们将照相机水平方向的距离减小为2:

var camera = new THREE.OrthographicCamera(-1, 1, 1.5, -1.5, 1, 10);
//这样的结果是水平方向被拉长了。

2. 若是改变照相机的位置,将照相机像右移动1个单位:

camera.position.set(1, 0, 5);
//得到的效果是物体看上去向左移动了

3. 那么正交投影照相机在设置时,是否需要保证left和right是相反数呢,如果不是,那么会产生什么效果呢:

var camera = new THREE.Orthographic(-1, 3, 1.5, -1.5, 1, 10);
camera.position.set(0, 0, 5);
//这里和把照相机右移得到的效果相同
camera.position.set(4, -3, -5);
camera.lookAt(new THREE.Vactor3(0, 0, 0));
//这里是指将照相机的视角拉到原点
window.onload = init;

function init() {
    //初始化一个renderer;
    var renderer = new THREE.WebGLRenderer({
        canvas: document.getElementById("mainCanvas")
        //这里是相当于对象的形式存储的,所以不要分号
    });
    
    renderer.setSize(400, 300);
    renderer.setClearColor("black");
    
    //要将renderer添加进body里面
    document.getElementsByTagName('body')[0].appendChild(renderer.domElement);
    
    //初始化一个scene
    var scene = new THREE.Scene();
    
    //初始化一个camera
    //var camera = new THREE.PerspectiveCamera(45, 3/4, 1, 1000);
    var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
    
    //定义camera的位置
    camera.position.set(4, -3, 5);
    camera.lookAt(new THREE.Vector3(0, 0, 0));
    //这里的lookAt函数是将视角指定为看原点
    //将camera添加到scene中
    scene.add(camera);
    
    //这里是创建一个长方形
    var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1),
        new THREE.MeshBasicMaterial({
            color: "green", 
            wireframe: true
            //这里指不使用实心材料,所以为true
        })
        
    );
    //这里要将这个长方形加入这个scene中
    scene.add(cube);
    
    renderer.render(scene, camera);
}

2.4 透视照相机

var camera = new PerspectiveCamera(fov, aspect, near, far);
  1. fov是视景图竖直方向上的张角(是角度制而非弧度制)
  2. aspect等于width/height,是照相机水平方向和竖直方向长度的比例,通常设为canvas的横纵比例。
  3. near和far分别是照相机最近最远的距离。均为正值。
var camera = new THREE.PerspectiveCamera(45, 4/3, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera);
//得到的结果是一个近大远小的图, 可以看到正方体12条边。

第三章 几何形状

3.1 基本几何形状

 new THREE.CubeGeometry(width, height, depth, widthSegments, heightSegments, depthSegments);
 new THREE.PlaneGeometry(width, height, widthSegments, heightSegments);
//后面两个参数也可以不要
 new THREE.SphereGeometry(radius, segmentWidth, segmentHeight, phiStart, phiLength, thetaStart, thetaLehgth);
 //radius是半径,segmentsWidth表示经度上的切片数,segmentsHeight表示纬度上的切片数,phiStart表示经度上开始的弧度,phiLength表示经度跨越的弧度,thetrStart表示纬度开始的弧度,thetaLength表示纬度跨越的弧度。
 new THREE.SphereGeometry(3, 8,6);
//可以创建一个半径为3,经度划分为8份,纬度划分为6份的球体。
new CircleGeometry(radius, segment, thetaStart, thetaLength);
//这四个参数与球体中的意义一样。
var sphere = new THREE.Mesh(new THREE.SphereGeometry(1, 8, 6), 
    new THREE.MeshBasicMaterial({
        color: "green",
        wireframe: true
    })
);
//完整代码
THREE.CylinderGeometry(radiusTop, radiusBottom, height, raiusSegments, heightSegments, openEnded);
THREE.TetrahedronGeometry(radius, detail);
THREE.OctahedronGeometry(radius, detail);
THREE.IcosahedronGeometry(radius, detail);
//radius是半径,detail是细节层次的层数。
THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, arc) 
new THREE.TorusGeometry(3, 1, 4, 8);//一个粗糙的圆面
new THREE.TorusGeometry(3, 1, 12, 18);//一个精细的圆面
new THREE.TorusGeometry(3, 1, 4, 8, Math.PI/3*2);
//创建部分圆环
THREE.TorusKnotGeometry(radius, tube, radialSegments, tubularSegments, p, q, heightScale) ;

3.2 文字形状

new THREE.TextGeometry(text, parameter);
 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(-2.5, 2.5, 1.875, -1.875, 0.1, 100);
    camera.position.set(5, 5, 20);
    camera.lookAt(new THREE.Vector3(1, 0, 0));
    scene.add(camera); 
         
//  var material = new THREE.MeshBasicMaterial({
//      color: 0xffff00,
//       wireframe: true
//  });
    //金属发亮物体
    var material = new THREE.MeshPhongMaterial({  
        color: 0xffff00,
        specular:0xffff00,  
        //指定该材质的光亮程度及其高光部分的颜色,如果设置成和color属性相同的颜色,则会得到另一个更加类似金属的材质,如果设置成grey灰色,则看起来像塑料
        shininess:0    
        //指定高光部分的亮度,默认值为30
    });
         
    //方向光
    var light = new THREE.DirectionalLight(0xffffff);
    light.position.set(-5, 10, 5);
    scene.add(light);
   
    // load font
    var loader = new THREE.FontLoader();
    loader.load('js/helvetiker_regular.typeface.js',              function(font) {
        var mesh = new THREE.Mesh(newTHREE.TextGeometry('Hello', {
            font: font,
            size: 1,
            height: 1
        }), material);
        scene.add(mesh);
           
        // render
        renderer.render(scene, camera);
    });
}

3.3 自定义形状:

var geometry = new THREE.Geometry();

第四章: 材质

4.1 基本材质

new THREE.MeshBasicMaterial(opt);
new THREE.MeshBasicMaterial({
    color: 0xffff00, 
    opacity: 0.75
})
  1. visible: 是否可见, 默认为true
  2. side:渲染面片正面或者反面,默认为正面
  3. wireframe: 渲染成线而非面,即物体为空心的,默认为false
  4. color:十六进制颜色
  5. map: 设置纹理贴图

4.2 Lambert材质

new THREE.MeshLamberMaterial({
    color: 0xffff00
});

4.3 Phong材质

new THREE.MeshPhongMaterial({
    color: 0xffff00
});
var material = new THREE.MeshPhongMaterial({
    specular: 0xff0000    
});

var mesh = new THREE.Mesh(new THREE.SphereGeometry(3, 10, 8), material);
new THREE.MeshPhongMaterial({
    specular: 0xff0000,
    shininess: 1000
}); 

4.4 法向材质

new THREE.MeshNorthMaterial();

4.5 材质的纹理贴图

var texture = THREE.ImageUtils.loadTexture('../img/0.png');
var material = new THREE.MeshLamberMaterial({
    map: texture;
});
var texture = THREE.ImageUtils.loadTextures('../img/0.png', {}, function(){
    renderer.render(scene, camera);
});
var material = new THREE.MeshLamberMaterial({
    map: texture
});
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);
}
var materials = [];
for(var i=0; i<6; ++i) {
    material.push(new THREE.MeshBasicMaterial({
        map: THREE.ImageUtils.loadTexture('img/'+i+'.png', {}, function(){
            renderer.render(scene, camera);
        }),
        
        overdraw: true
    }));
}
var cube = new THREE.Mesh(new CubeGeometry(5, 5, 5), 
    new THREE.MeshFaceMaterial(materials));
scene.add(cube);
var texture = THREE.ImageUtils.loadTexture('img/0.png', {}, function(){
    renderer.render(scene, camera);
});
texture.wrapS = texture.wrapT = THREE.RepeatsWrapping;
texture.repeat.set(4, 4);
window.onload = init;

function init() {
    var renderer = new THREE.WebGLRenderer({
        canvas: document.getElementById("mainCanvas")
    });
    renderer.setClearColor(0x000000);
    renderer.setSize(400, 300);
    document.getElementsByTagName('body')[0].appendChild(renderer.domElement);
    
    //scene
    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);
    
    // 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);
    
    var light = new THREE.PointLight(0xffffff, 1, 1000);
    light.position.set(10, 15, 20);
    scene.add(light);
    
    
    var texture = THREE.ImageUtils.loadTexture('img/1.png', {}, function(){
        renderer.render(scene, camera);
    });
    
    var material = new THREE.MeshLambertMaterial({
        map: texture
    });
    
    texture.wrapS = texture.wrapT = texture.RepeatWrapping;
    texture.repeat.set(4, 4);
    
//  var sphere = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5), material);
//  scene.add(sphere);

    var plane = new THREE.Mesh(new THREE.PlaneGeometry(12, 12), material);
    scene.add(plane);
    
    renderer.render(scene, camera);
}

第五章:网格

5.1 创建网格

Mesh(geometry, material);
var material = new THREE.MeshLambertMaterial({
    color: 0xff0000
});
var geometry = new THREE.CubeGeometry(1, 2, 3);
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
//如果之后这些不复用,则可以直接写在一起
var mesh = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
    new THREE.MeshLambertMaterial({
        color: 0xff0000
    })
);
scene.add(mesh);

5.2 修改属性

var material = new THREE.MeshLambertMaterial({
    color: 0xffff00
});
var geometry = new THREE.CubeGeometry(1, 2, 3);
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

mesh.material = new THREE.MeshLambertMaterial({
    color: 0xff0000
});
mesh.position.z = 1;
mesh.position.set(1.5, -0.5, 0);
mesh.position = new THREE.Vector(1.5, -0.5, 0);

第六章: 动画

6.1 实现动画原理

setInterval(func, mesc);
//其中,func每通过mesc毫秒执行的函数,如果将func定义为重绘画面的函数,就能实现动画效果。setInterval函数返回一个id,如果需要停止重绘,需要使用clearInterval方法,并传入该id
id = setInterval(draw, 20);
function draw() {
    mesh.rotation.y = (mesh.rotation.y+0.01)%(Math.PI*2);
    renderer.render(camera, scene);
}
<button id = 'stopBtn' onclick = 'stop()'>Stop</button>
function stop() {
    if(id!=null) {
        clearInterval(id);
        id == null;
    }
}
window.onload = init;

var mesh = null;                                         
var scene = null;
var camera = null;
var renderer = null;

//      var mesh = null;
var id = null;
        
function init() {
    renderer = new THREE.WebGLRenderer({
        canvas: document.getElementById('mainCanvas')
    })
    
    renderer.setClearColor(0x000000);
    renderer.setSize(400, 300);
    
    document.getElementsByTagName('body')[0].appendChild(renderer.domElement);
    
    //scene
    scene = new THREE.Scene();
    
    camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
    camera.position.set(5, 5, 20);
    camera.lookAt(new THREE.Vector3(0, 0, 0));
    scene.add(camera);
    
    light = new THREE.DirectionalLight(0xffffff);
    light.position.set(20, 10, 5);
    scene.add(light);
    //mesh
    mesh = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
        new THREE.MeshLambertMaterial({
            color: 0xffff00
        })
    );
    
    scene.add(mesh);
    
    id = setInterval(draw, 20);
}

function draw() {
    mesh.rotation.y = (mesh.rotation.y + 0.01) % (Math.PI * 2);
    renderer.render(scene, camera);
}
function stop() {
    if(id!=null) {
        clearAnimationFrame(id);
        id=null;
    }
}
function draw() {
    mesh.rotation.y = (mesh.rotation.y+0.01)%(Math.PI*2);
    renderer.render(scene, camera);
    id = requestAnimationFrame(draw);
}
var requestAnimationFrame = window.requestAnimationFrame 
        || window.mozRequestAnimationFrame
        || window.webkitRequestAnimationFrame
        || window.msRequestAnimationFrame
        || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame; 

6.2 使用stat.js记录FPS

<script type = 'text/javascript' src = 'stat.js'></script>
var stat = null;
function init() {
    stat = new Stats();
    stat.domElement.style.position = 'absolute';
    stat.domElement.style.right = '0px';
    stat.domElement.style.top = '0px';
    document.body.appendChild(stat.domElement);

    // Three.js init ...
} 
function draw() {
    stat.begin();
    mesh.rotation.y = (mesh.rotation.y+0.01)%(Math.PI*2);
    renderer.render(scene, camera);
    stat.end();
}

第七章 外部模型

7.1 支持格式

7.2 无材质的模型

<script type = 'text/javascript' src = 'OBJLoader.js'></script>
var loader = new THREE.OBJLoader();
loader.load('../obj/port.obj', function(obj) {
    mesh=obj;//存储在全局变量中。
    scene.add(obj);
});
function draw() {
    renderer.render(scene, camera);
    mesh.rotation.y += 0.01;
    if(mesh.rotation.y>Math.PI*2) {
        mesh.rotation.y -= Math.PI*2;
    }
}
//这里出现的画面只有正面的面片被绘制,所以会看见背面的画面有缺口。
var loader = new THREE.OBJLoader();
loader.load('../lib/port.obj', function(obj){
    obj.traverse(function(child) {
        if(child instanceof THREE.Mesh) {
            child.material.side = THREE.DoubleSide;
        }
    });
    mesh = obj;
    scene.add(obj);
})

7.3 有材质的模型

var loader = new THREE.OBJLoader();
loader.load('../lib/port.obj', function(obj){
    obj.traverse(function(child){
    //如果obj文件代表的三维对象是由多个子模型构成的模型组合,我们可以调用object.traverse(function(child){})来对每个子模型进行处理。
        if(child instanceof THREE.Mesh) {
            child.material = new THREE.MeshLambertMaterial({
                color: 0xffff00,
                side:THREE.DoubleSide
            });
        }
    });
    mesh = obj;
    scene.add(obj);
})
<script src = "MTLLoader.js"></script>
<script src = "OBJMTLLoader.js"></script>
var loader = new THREE.OBJMTLLoader(); 
loader.addEventListener("load", function(event){
    var obj = event.content;
    mesh = obj;
    scene.add(obj);
});
loader.load('../lib/port.obj', '../lib/port.mtl');
上一篇下一篇

猜你喜欢

热点阅读