WebGL & Three.js 入门

1、简介

WebGL 是在浏览器中实现三维效果的一套规范,而 Three.js 可以看成是浏览器对 WebGL 规范实现的一套封装, 能够让 Web 开发者使用 JavaScript 语言直接和显卡(GPU)进行通信。其中得 GLSL 是GPU 部分对应的编程语言,可以用 GLSL 编写着色器程序,并配合 JavaScript 共同实现 3D 效果。一个简单的 Three.js 程序包含以下几个部分:


    
        My first Three.js app
        
    
    
        
        
    

2、概念介绍

WebGL & Three.js 入门_第1张图片
ThreeJS-1

WebGL & Three.js 入门_第2张图片
ThreeJS-2
  • 场景

在 Threejs 中场景就只有一种,用THREE.Scene来表示,要构件一个场景也很简单,只要new一个对象就可以了,代码如下:

var scene = new THREE.Scene();

场景是所有物体的容器,如果要显示一个苹果,就需要将苹果对象加入场景中。

  • 相机

相机决定了场景中哪个角度的景色会显示出来,在 Threejs 中有多种相机,这里介绍两种,它们是:
透视相机(THREE.PerspectiveCamera)和正投影相机(THREE.OrthographicCamera),透视相机跟人眼差不多,有近大远小的效果,而正投影相机则没有这个效果,所有东西显示都是一样大

var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
  • 渲染器

渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制。ThreeJS 框架提供了好几种渲染器对象,分别使用不同的底层技术实现,比如:
WebGLRenderer使用 WebGL 技术;CanvasRenderer使用 Canvas 2D 技术;CSS2DRenderer和CSS3DRenderer则是使用 CSS 技术;

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
  • 物体 Mesh
    Mesh 好比一个包装工,它将『可视化的材质』粘合在一个『数学世界里的几何体』上,形成一个『可添加到场景的对象』。
    当然,创建的材质和几何体可以多次使用(若需要)。而且,包装工不止一种,还有 Points(点集)、Line(线/虚线) 等,比如添加一个几何体到场景中:
var geometry = new THREE.CubeGeometry(1,1,1); 
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material); 
scene.add(cube);

CubeGeometry 表示一个几何体

  • 几何体 Geometry
    目前 Three.js 一共提供了 22 个 Geometry,详情参见https://aotu.io/notes/2017/08/28/getting-started-with-threejs/index.html

  • 点 & 线
    创建一个点:

var point1 = new THREE.Vecotr3(4,8,9);
// or
var point1 = new THREE.Vector3();
point1.set(4,8,9)

创建一条线:线由点组成(准确来说由点,材质和颜色组成),所以先创建点,再组合点(通过Geometry组织点),Threejs 中没有提供单独画点的函数,它必须被放到一个THREE.Geometry形状中

// 方式 1
var geometry = new THREE.Geometry();
var material = new THREE.LineBasicMaterial( { vertexColors: true } );
var color1 = new THREE.Color( 0x444444 ), color2 = new THREE.Color( 0xFF0000 );

// 线的材质可以由2点的颜色决定
var p1 = new THREE.Vector3( -100, 0, 100 );
var p2 = new THREE.Vector3(  100, 0, -100 );
// vertices 保存点,colors 保存对应点的颜色
geometry.vertices.push(p1);
geometry.vertices.push(p2);
geometry.colors.push( color1, color2 );

var line = new THREE.Line( geometry, material, THREE.LinePieces );

// 方式 2
var geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );
geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );

for ( var i = 0; i <= 20; i ++ ) {
    var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
    line.position.z = ( i * 50 ) - 500;
    scene.add( line );
}

操作线的某一维坐标本质是做平移

  • 坐标系

Threejs使用的是右手坐标系,x轴正方向向右,y轴正方向向上,z轴由屏幕从里向外

  • 运动原理

要么是摄像机移动(camera.position),要么是物体移动(object.position)

  • 光源

1、环境光
环境光是经过多次反射而来的光,无法确定其最初的方向。环境光是一种无处不在的光。环境光源放出的光线被认为来自任何方向。因此,当你仅为场景指定环境光时,所有的物体无论法向量如何,都将表现为同样的明暗程度。

var light = new THREE.AmbientLight( 0xff0000 );
scene.add( light );

2、点光源
由这种光源放出的光线来自同一点,且方向辐射自四面八方

PointLight( color, intensity, distance )

3、聚光灯
这种光源的光线从一个锥体中射出,在被照射的物体上产生聚光的效果。使用这种光源需要指定光的射出方向以及锥体的顶角α

THREE.SpotLight( hex, intensity, distance, angle, exponent )
  • 材质

材质的本质就是光

  • 纹理

纹理的本质就是图片或者说贴图,纹理主要用于丰富材质,
1、用图片创建一个纹理:

// 创建一个几何平面
var geometry = new THREE.PlaneGeometry( 500, 300, 1, 1 );
// 设置纹理坐标
geometry.vertices[0].uv = new THREE.Vector2(0,0);
geometry.vertices[1].uv = new THREE.Vector2(2,0);
geometry.vertices[2].uv = new THREE.Vector2(2,2);
geometry.vertices[3].uv = new THREE.Vector2(0,2);
// 加载纹理
var texture = THREE.ImageUtils.loadTexture("textures/a.jpg",null,function(t)
{
});
// 将纹理运用到材质
var material = new THREE.MeshBasicMaterial({map:texture});
// 结合几何体和材质
var mesh = new THREE.Mesh( geometry,material );
scene.add( mesh );

2、用 canvas 创建纹理

var geometry = new THREE.CubeGeometry(150, 150, 150);
texture = new THREE.Texture( canvas);
var material = new THREE.MeshBasicMaterial({map:texture});
texture.needsUpdate = true;
mesh = new THREE.Mesh( geometry,material );
scene.add( mesh );

需要注意的是在定义了纹理之后,我们将texture.needsUpdate设置为了true,如果不设置为true,那么纹理就不会更新,很可能你看到的是一个黑色的正方体,原因是纹理没有被载入之前,就开始渲染了,而渲染使用了默认的材质颜色

  • 模型

模型是由面组成,面分为三角形和四边形面。三角形和四边形面组成了网格模型。在Three.js中用THREE.Mesh来表示网格模型。THREE.Mesh可以和THREE.Line相提并论,区别是THREE.Line表示的是线条。THREE.Mesh表示面的集合。

THREE.Mesh = function ( geometry, material )

第一个参数geometry:是一个THREE.Geometry类型的对象,他是一个包含顶点和顶点之间连接关系的对象。

第二个参数Material:就是定义的材质。有了材质就能够让模型更好看,材质会影响光照、纹理对Mesh的作用效果。

// VTK loader 使用示例
var material = new THREE.MeshLambertMaterial( { color:0xffffff, side: THREE.DoubleSide } );
var loader = new THREE.VTKLoader();
loader.addEventListener( 'load', function ( event ) {
     var geometry = event.content;
     var mesh = new THREE.Mesh( geometry, material );
     mesh.position.setY( - 0.09 );
     scene.add( mesh );
});
loader.load( "models/vtk/bunny.vtk" );
  • 相机控制
    通过鼠标控制相机 TrackballControls
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.01, 1e10 );
camera.position.z = 0.2;
controls = new THREE.TrackballControls( camera );

controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;
controls.panSpeed = 2;

controls.noZoom = false;
controls.noPan = false;

controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
  • 阴影

阴影是增强三维场景效果的重要因素,但 Three.js 出于性能考虑,默认关闭阴影

// 启用阴影
renderer.shadowMap.enabled = true
// 并不是所有类型的光源能产生投影,不能产生投影的光源有:环境光(AmbientLight)、半球光(HemisphereLight)
spotLight.castShadow = true
// 平面和立方体都能接受阴影
plane.receiveShadow = true
cube.receiveShadow = true
// 球体的阴影可以投射到平面和球体上
sphere.castShadow = true
// 更改渲染器的投影类型,默认值是 THREE.PCFShadowMap
renderer.shadowMap.type = THREE.PCFSoftShadowMap
// 更改光源的阴影质量,默认值是 512
spotLight.shadow.mapSize.width = 1024 
spotLight.shadow.mapSize.height = 1024
  • 雾化
// Fog( hex, near, far ),线性雾化。
// near 表示哪里开始应用雾化效果(摄像机为 0)
// far 表示哪里的雾化浓度为 1。若某物体在该距离后,则其表现为雾的颜色。当雾的颜色和渲染器的背景色相同时,则表现为消失(实为颜色相同)。
scene.fog = new THREE.Fog( 0xffffff, 0.015, 100 )

// FogExp2( hex, density ),指数雾化
// density 是雾化强度
scene.fog = new THREE.FogExp2( 0xffffff, 0.01 )

// 雾化效果默认是全局影响的,若某个材质不受雾化效果影响,则可为材质的 fog 属性设置为 false(默认值 true)
var material = new THREE.Material({
    fog: false
})
  • 渲染器剔除模式

在 Three.js 中,材质默认只应用在正面(THREE.FrontSide),即当你旋转物体(或摄像机)查看物体的背面时,它会因为未被应用材质而变得透明(即效果与 CSS3 backface-visibility: hidden 一样)。因此,当你想让物体正反两面均应用材质,则需要在创建材质时声明 side 属性为 THREE.DoubleSide:

var material = new THREE.MeshBasicMaterial({
    side: THREE.DoubleSide // 其他值:THREE.FrontSide(默认值)、THREE.BackSide
})

这个模式应用在3D看房时比较好用


WebGL & Three.js 入门_第3张图片
3D看房
  • 声音 Audio

音频也是 3D 的,它会受到摄像机的距离影响:
1、声源离摄像机的距离决定着声音的大小。
2、声源在摄像机左右侧的位置分别决定着左右扬声器声音的大小。

  • http://www.hewebgl.com/paytip
  • Three.js - 走进3D的奇妙世界
  • 现在学习也不晚

你可能感兴趣的:(WebGL & Three.js 入门)