WebGL是在浏览器中实现三维效果的一套规范
什么是threejs,很简单,你将它理解成three+js
就能够了。three表示3D的意思
,js表示javascript的意思
。那么合起来,three.js
就是使用javascript
来写3D程序
的意思。
Three.js
也是运行在浏览器
上的。使用Three.js以前,首先在<head>
部分,须要引入外部文件Three.js
。
<head> <script type="text/javascript" src="three.js"></script> </head>
WebGL 的渲染是须要HTML5 中的Canvas
元素的,你能够手动在HTML的<body>
部分中使用canvas标签,或者让Three.js帮你生成。这两种选择,通常没有多大差异。咱们先手动定义一个canvas标签:
<body onload="init();"> <canvas id="canvasId" width="800" height="600"></canvas> </body>
在js里面定义一个函数,将全部执行的代码放在函数里,在html加载完成后,执行该函数
function init{ // 全部须要执行的代码 }
一个典型的Three.js程序,至少应该包括四个部分:渲染器(renderer)
、场景(scene)
、相机(camera)
、以及场景中建立的物体
。javascript
渲染器
决定了渲染的结果
应该画在页面的什么元素上面
,而且以怎样的方式来绘制
。渲染器将会和canvas元素进行绑定,若是以前
<html>
标签中,定义了id为canvasId的canvas标签
,那么renderer能够这样写:html
var renderer = new THREE.WebGLRenderer({ canvas : document.getElementById('canvasId'); });
若是想要
Three.js生成Canvas元素
的时候,在html中就不须要在定义一个canvas标签了,直接在javascript代码中写道:
var renderer = new THREE.WebGLRenderer(); renderer.setSize = (800,600); document.body.appendChild(renderer.domElement);
setSize
是为canvas元素设置宽高,document.body.appendChild(renderer.domElement)
是将渲染器对应的Canvas元素添加到body
中。咱们可使用下面的代码(用于清除画面的颜色)将背景色设置为黑色:
renderer.setClearColor(0x000000);
在Three.js中添加物体
都是添加到场景
中的,所以它至关于一个大容器。通常说,场景里没有很复杂的操做,只要new一个对象就能够了,而后将物体添加到场景中便可。
var scene = new THREE.Scene();
在介绍照相机以前,咱们先来介绍一下坐标系。
这里咱们定义一个
透视相机
(相机也须要添加到场景中):
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000); // 设置相机的位置 camera.position.set(0,0,5); // 将相机添加到场景中 scene.add(camera);
这里咱们先介绍一个长方体,建立一个x、y、z方向长度分别为一、二、3的长方体,并设置为红色。
var geometry = new THREE.CubeGeometry(1,2,3); var material = new THREE.MeshBasicMaterial({ color: 0xff0000; }); var cube = new THREE.Mesh(geometry,material); scene.add(cube);
new THREE.CubeGeometry(); 表示调用一个几何体前端
CubeGeometry
是一个正方体
或者长方体
,到底是什么,由它的3个参数所决定CubeGeometry(width, height, depth, segmentsWidth, segmentsHeight, segmentsDepth, materials, sides)
width:立方体x轴的长度 height:立方体y轴的长度 depth:立方体z轴的深度,也就是长度 想想你们就明白,以上3个参数就可以肯定一个立方体。 剩下的几个参数就要费解和复杂一些了,不事后面咱们会本身来写一个立方体,到时候,你会更明白这些参数的意义,这里你能够将这些参数省略。
new THREE.MeshBasicMaterial(); 表示的是物体的材质java
var material = new THREE.MeshBasicMaterial({ color: 0xff0000; });
必定不要忘了,将物体添加到场景
在定义了场景中的物体,设置好的照相机以后,渲染器就知道如何渲染出二维的结果了。这时候,咱们只须要调用渲染器的渲染函数,就能使其渲染一次了。
renderer.render(scene, camera);
<html lang="en"> <head> <meta charset="UTF-8"> <title>长方体</title> <script src="three.js"></script> </head> <body onload="init();"> <script> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); // canvas元素设置宽高 renderer.setSize = (800, 600); // 渲染器对应的Canvas元素添加到<body>中。 document.body.appendChild(renderer.domElement); // 清除画面的颜色 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); } </script> </body> </html>
canvas元素的默认宽高为300/150python
下面介绍下Three.js官网文档中的一些重要的对象,在你须要寻求帮助时,就可以知道关键词是什么。
Cameras(照相机,控制投影方式)git
Core(核心对象)程序员
Lights(光照)github
Loaders(加载器,用来加载特定文件)web
Materials(材质,控制物体的颜色、纹理等)算法
Math(和数学相关的对象)
Objects(物体)
Renderers(渲染器,能够渲染到不一样对象上)
Renderers / Renderables
Scenes(场景)
Textures(纹理)
Extras
Extras / Animation
Extras / Cameras
Extras / Core
Extras / Geometries(几何形状)
Extras / Helpers
Extras / Objects
Extras / Renderers / Plugins
Extras / Shaders
咱们看到,Three.js功能是十分丰富的,一时间想所有掌握有些困难。在接下来的章节中,咱们将会先详细介绍照相机、几何形状、材质、物体等入门级知识;而后介绍使用动画、模型导入、加入光照等功能;最后,对于学有余力的读者,咱们将介绍着色器,用于更高级的图形渲染。
本章将介绍照相机的概念,以及如何使用Three.js设置相应的参数。
在图形学中,照相机可没有生活中的照相机那么简单
投影方式
的不一样,照相机又分为正交投影照相机
与透视投影照相机
。咱们须要为本身的程序选择合适的照相机。这二者分别是什么,以及二者有何差别,咱们将在下节中做介绍。举个简单的例子来讲明正交投影与透视投影照相机的区别。使用透视投影照相
机得到的结果是相似人眼在真实世界中看到的有“近大远小”
的效果(以下图中的(a));而使用正交投影照相机
得到的结果就像咱们在数学几何学课上老师教咱们画的效果,对于三维空间内平行的线
,投影到二维空间中也必定是平行的
(以下图中的(b))。
通常说来,对于制图、建模软
一般使正交投影
,这样不会由于投影而改变物体比例;而对于其余大多数应用
,一般使用 透视投影
,由于这更接近人眼的观察效果。固然,照相机的选择并无对错之分,你能够更具应用的特性,选择一个效果更佳的照相机。
正交投影照相机(
Orthographic Camera
)
THREE.OrthographicCamera(left, right, top, bottom, near, far)
这六个参数分别表明正交投影照相机拍摄到的空间的六个面的位置,这六个面围成一个长方体,咱们称其
视景体(Frustum)
。只有在视景体内部(下图中的灰色部分)的物体才可能显示在屏幕上,而视景体外的物体会在显示以前被裁减掉。
为了保持照相机的横竖比例,须要保证(right - left)与(top - bottom)
的比例与Canvas宽度与高度的比例(800/600)
一致。
// [2-(-2)] / [1.5-(-1.5)] = canvas.width/canvas.height var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10) // left right top bottom near far
near与far
都是指到照相机位置在深度平面的位置,而照相机不该该拍摄到其后方的物体,所以这两个值应该均为正值
。为了保证场景中的物体不会由于太近或太远而被照相机忽略,通常near的值设置得较小
,far的值设置得较大
,具体值视场景中物体的位置等决定。
下面咱们经过一个具体的例子来了解正交投影照相机的设置
基本设置
var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10); camera.poaition.set(0,0,5); scene.add(camera);
wireframe
而不是实心的材质,以便看到正方体后方的边:var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true }) ); scene.add(cube);
长宽比例
这里,咱们的Canvas宽度是800px,高度是600px,照相机水平方向距离4,垂直方向距离3,所以长宽比例保持不变。为了试验长宽比例变化时的效果,咱们将照相机水平方向的距离减少为2(right-left = 2):
var camera = new THREE.OrthographicCamera(-1, 1, 1.5, -1.5, 1, 10);
照相机位置
接下来,咱们来看看照相机位置对渲染结果的影响。在以前的例子中,咱们将照相机设置在(0, 0, 5)位置,而因为照相机默认是面向z轴负方向
放置的,因此能看到在原点处的正方体。如今,若是咱们将照相机向右移动1个
单位:
var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10); // 向右移动一个单位的位置 camera.position.set(1, 0, 5);
正交投影摄像机在设置时,是否须要保证
left 和 right 互为相反数
呢?
(-2, 2, 1.5, -1.5, 1, 10)
改成(-1, 1, 1.5, -1.5, 1, 10)
,即,将视景体设置得更靠右:var camera = new THREE.OrthographicCamera(-1, 3, 1.5, -1.5, 1, 10); camera.position.set(0, 0, 5);
换个角度
到目前为止,咱们使用照相机,都是沿着Z轴负方向
观察的,所以看到的都是一个正方形,如今咱们尝试一下仰望
这个正方体,改变照相机的位置:
// x轴:4; y轴:-3; z轴:5 camera.position.set(4, -3, 5);
照相机默认是沿着z轴的负方向观察的,所以观察不到正方体,只看到一片黑。咱们能够经过lookAt函数
指定它看着原点方向
:
camera.lookAt(new THREE.Vector3(0, 0, 0));
lookAt函数
接收的是一个THREE.Vector3
的实例千万不能写成camera.lookAt(0,0,0)
。
透视投影照相机(
Perspective Camera
)
THREE.PerspectiveCamera(fov, aspect, near, far)
让咱们经过一张透视照相机投影的图来了解这些参数。
灰色
的部分是视景体
,是可能被渲染
的物体所在的区域。fov
是视景体竖直方向上
的张角
(是角度制而非弧度制),如侧视图所示。aspect
等于width / height
,是照相机水平方向和竖直方向长度的比值
,一般设为Canvas的横纵比例
。near和far
分别是照相机到视景体
最近、最远
的距离,均为正值
,且far应大于near
。下面咱们经过一个例子来学习透视投影照相机
基本设置
800px
,宽600px
,因此aspect
设为800 / 600
:var camera = new THREE.PerspectiveCamera(45, 800 / 600, 1, 10); camera.position.set(0, 0, 5); scene.add(camera);
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true }) ); scene.add(cube);
所有的12条边
,并且有近大远小
的效果,这也就是与正交投影的区别。竖直张角
fov
的改变对渲染效果的影响。咱们将原来的45改成60
:var camera = new THREE.PerspectiveCamera(60, 800 / 600, 1, 10); camera.position.set(0, 0, 5); scene.add(camera);
竖直张角
设置得更大
时,视景体变大了
,于是正方体
相对于整个视景体
的大小就变小
了,看起来正方形就显得变小了。改变fov
并不会
引起画面横竖比例
的变化,而改变aspect
则会
改变横竖比例。在计算机世界里,3D世界由点组成,两个点能组成一条直线,三个不在一条直线上的点,就能组成一个三角面,无数的三角面
就能组成各类各样的物体
,以下图:
网络模型
叫作Mesh模型
。给物体贴上皮肤
,或者专业点就叫作纹理
,那么这个物体就活灵活现了。最后无数的物体就组成了咱们的3D世界。在三维空间中的某一个点能够用一个坐标点来表示。一个坐标点由x
,y
,z
三个份量构成。在three.js中,点能够在右手坐标系中表示:空间几何中,点能够用一个向量来表示,在Three.js中也是用一个
向量
来表示的
THREE.Vector3 = function ( x, y, z ) { this.x = x || 0; this.y = y || 0; this.z = z || 0; };
Vector3
是定义在THREE
下面的一个类
。之后要用Vector3
,就必须要加THREE前缀
。固然Three.js的设计者,也能够不加THREE这个前缀,可是他们预见到,Three.js引擎中会有不少类型,最好给这些类型加一个前缀,以避免与开发者的代码产生冲突。函数
。这个函数有3个参数
,分别表明x坐标
,y坐标
和z坐标
的份量。函数体内的代码将他们分别赋值给成员变量x,y,z
。看看上面的代码,中间使用了一个“||”(或)运算符
,就是当x=null或者undefine
时,this.x
的值应该取0
。在3D世界中点
能够用THREE.Vector3D
来表示。
var point1 = new THREE.Vecotr3(4,8,9);
set
方法,代码以下:var point1 = new THREE.Vector3(); point1.set(4,8,9);
两个不重合的点可以决定一条直线。在three.js中,也能够经过定义两个点,来画一条直线。
vertices变量
,能够用来存放点
var geometry = new THREE.Geometry(); // 几何体里面有个vertices变量,能够用来存放点
THREE.LineBasicMaterial
类型来定义,它接受一个集合做为参数
,其原型以下:THREE.LineBasicMaterial(parameters);
parameters
是定义材质外观的对象,它包含多个属性来定义材质,这些属性是:
颜色
,用16进制表示,默认都是白色宽度
,默认是1个单位宽度两端的外
观,默认是圆角端点
,当线条较粗的时候才能看到效果链接点处的外观
,默认是“round”,表示圆角。线条材质
是否使用顶点颜色
,这是一个boolean值。意思是,线条各部分的颜色会根据顶点的颜色来进行插值。顶点颜色
vertexColors: THREE.VertexColors
,就是线条的颜色
会根据顶点
来计算。var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
WebGLRender
渲染方式是不之持绘制线宽的,要想支持,须要将渲染方式设置为CanvasRenderer
var color1 = new THREE.Color( 0x444444 ), color2 = new THREE.Color( 0xFF0000 );
geometry
中,代码以下:var p1 = new THREE.Vector3(-100,0,100); var p2 = new THREE.Vector3(100,0,-100); geometry.vertices.push(p1); geometry.vertices.push(p2);
geometry.colors.push( color1, color2 );
geometry中colors表示顶点的颜色
,必须材质中vertexColors等于THREE.VertexColors
时,颜色才有效
,若是vertexColors等于THREE.NoColors时,颜色就没有效果了。那么就会去取材质中color的值,这个很重要。THREE.Line类
,代码以下所示:var line = new THREE.Line( geometry, material, THREE.LinePieces );
geometry
,里面包含了2个顶
点和顶点的颜色
。材质
,或者是线条的属性,表示线条以哪一种方式取色。scene.add(line);
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <script type="text/javascript" src="three.js"></script> <script type="text/javascript"> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); // 设定渲染器尺寸 renderer.setSize(800, 600); // 添加到dom document.body.appendChild(renderer.domElement); // 重绘时颜色 renderer.setClearColor(0xffffff); // 场景 var scene = new THREE.Scene(); // 相机 var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100); // 设定相机位置 camera.position.set(0, -25, 0); // 相机看向 camera.lookAt(new THREE.Vector3(0, 0, 0)); scene.add(camera); // 定义一个物体 // new 一个模型 var geometry = new THREE.Geometry(); // 定义模型的类型是线段 而且设置其材质 var material = new THREE.LineBasicMaterial({ // 使用顶点颜色 vertexColors: true }); // 定义两个颜色 var color1 = new THREE.Color(0x444444), color2 = new THREE.Color(0xff0000); // 新建两个点 var p1 = new THREE.Vector3(-1, 0, 1); var p2 = new THREE.Vector3(1, 0, -1); // 将新建的两个点添加到几何体中 geometry.vertices.push(p1); geometry.vertices.push(p2); // 将两个颜色添加到几何体中 geometry.colors.push(color1, color2); // new 一条线 var line = new THREE.Line(geometry, material, THREE.LinePieces); scene.add(line); // 渲染 renderer.render(scene, camera); } </script> </head> <body onload="init()"> </body> </html>
在Threejs中,一条线由点,材质和颜色组成。
THREE.Vector3
表示,Threejs中没有提供单独画点的函数,它必须被放到一个THREE.Geometry
形状中,这个结构中包含一个数组vertices
,这个vertices就是存放无数的点(THREE.Vector3)的数组
。var p1 = new THREE.Vector3( -1, 0, 1 ); var p2 = new THREE.Vector3( 1, 0, -1 );
THREE.Geometry
,并把点加进去var geometry = new THREE.Geometry(); geometry.vertices.push(p1); geometry.vertices.push(p2);
push方法
,是由于geometry.vertices
是一个数组
。这样geometry中就有了2个点了。THREE.LineBasicMaterial
。var material = new THREE.LineBasicMaterial();
THREE.Line
绘制了一条线:var line = new THREE.Line( geometry, material, THREE.LinePieces );
咱们要画一个网格的坐标,那么咱们就应该找到线的点。把网格虚拟成正方形,在正方形边界上找到几个等分点,用这些点两两链接,就可以画出整个网格来。
// 在x轴上定义两个点p1(-500,0,0),p2(500,0,0)。 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 ); var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } )); line.position.x = ( i * 50 ) - 500; line.rotation.y = 90 * Math.PI / 180; // 旋转90度 scene.add( line ); }
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <script type="text/javascript" src="three.js"></script> <script type="text/javascript"> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); // 设定渲染器尺寸 renderer.setSize(800, 600); // 添加到dom document.body.appendChild(renderer.domElement); // 重绘时颜色 renderer.setClearColor(0x000000); // 场景 var scene = new THREE.Scene(); // 相机 var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100); // 设定相机位置 camera.position.set(0, -25, 0); // 相机看向 camera.lookAt(new THREE.Vector3(0, 0, 0)); scene.add(camera); // 定义一个几何体 var geometry = new THREE.Geometry(); geometry.vertices.push(new THREE.Vector3(-2, 0, 0)); geometry.vertices.push(new THREE.Vector3(2, 0, 0)); // for循环出来六条线段 for (var i = 0; i <= 5; i++) { // 定义竖着的线段 var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0xffffff, })); // 每条线段之间的间隔为0.8,-2是为了达到田字格的效果 line.position.z = (i * 0.8) - 2; scene.add(line); // 定义横着的线段 var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0xffffff, opacity: 0.2 })); line.position.x = (i * 0.8) - 2; line.rotation.y = 90 * Math.PI / 180; scene.add(line); // 渲染 renderer.render(scene, camera); } } </script> </head> <body onload="init()"> </body> </html>
在建立物体时,须要传入两个参数,一个是几何形状(Geometry)
,另外一个是材质(Material)
,这一章将着重介绍几何形状的建立,第6章介绍材质,第7章介绍如何使用二者建立网格。
顶点信息
。WebGL须要程序员指定每一个顶点的位置,而在Three.js中,能够经过指定一些特征
来建立几何形状,例如使用半径
建立一个球体
,从而省去程序员一个个指定顶点的工做量。手动定义
顶点位置
和面片信息
组成几何形状。
虽然这形状的名字叫作立方体(
CubeGeometry
),但实际上是长方体,也就是长宽高能够设置不一样的值:
new THREE.CubeGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
width
是x方向
上的长度;height
是y方向
上的长度;depth
是z方向上
的长度;后三个参数分别是在三个方向上的分段数
,如widthSegments为3
的话,表明x方向上水平分为三份
。通常状况下不须要分段的话,能够不设置后三个参数,后三个参数的缺省值为1。其余几何形状中的分段也是相似的,下面不作说明。长宽高
new THREE.CubeGeometry(1, 2, 3);
能够建立一个x方向长度为1
,y方向长度为2
,z方向长度为3
的立方体。// 调用渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0x000000); // 调用场景 var scene = new THREE.Scene(); // 调用相机 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); // 新建一个几何体(长方体) var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true })); scene.add(cube);
长度为3
的红、绿、蓝
线段分别表示x、y、z
三个轴(这里不须要深究,后面会详细介绍):// 封装一个坐标系函数 function drawAxes(scene) { // x-axis var xGeo = new THREE.Geometry(); xGeo.vertices.push(new THREE.Vector3(0, 0, 0)); xGeo.vertices.push(new THREE.Vector3(3, 0, 0)); var xMat = new THREE.LineBasicMaterial({ color: 0xff0000 }); var xAxis = new THREE.Line(xGeo, xMat); scene.add(xAxis); // y-axis var yGeo = new THREE.Geometry(); yGeo.vertices.push(new THREE.Vector3(0, 0, 0)); yGeo.vertices.push(new THREE.Vector3(0, 3, 0)); var yMat = new THREE.LineBasicMaterial({ color: 0x00ff00 }); var yAxis = new THREE.Line(yGeo, yMat); scene.add(yAxis); // z-axis var zGeo = new THREE.Geometry(); zGeo.vertices.push(new THREE.Vector3(0, 0, 0)); zGeo.vertices.push(new THREE.Vector3(0, 0, 3)); var zMat = new THREE.LineBasicMaterial({ color: 0x00ccff }); var zAxis = new THREE.Line(zGeo, zMat); scene.add(zAxis); } // 在init 函数里调用这个函数 便可在屏幕上显示一个坐标系了 drawAxes(scene);
默认位置
是原点
,对于立方体而言,是其几何中心在原点的位置。分段
THREE.CubeGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
,的后三个参数,为这个长方体分段:// x轴分两段 y轴分两段 z轴分三段 new THREE.CubeGeometry(1, 2, 3, 2, 2, 3)
六个面
进行分段,而不是对立方体的体素分段,所以在立方体的中间是不分段
的,只有六个侧面
被分段。
这里的平面(
PlaneGeometry
)实际上是一个长方形,而并不是是数学意义上无限大的平面:
new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
width
是x方向
上的长度;height
是y方向
上的长度;后两个参数一样表示分段
。new THREE.PlaneGeometry(2, 4);
建立的平面在x轴和y轴所在平面内:var plane = new THREE.Mesh( new THREE.PlaneGeometry(2, 4), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(plane);
x轴和z轴
所在的平面内,能够经过物体的旋转
来实现,具体的作法将在下面章节介绍到。
球体(
SphereGeometry
)的构造函数是:
new THREE.SphereGeometry(radius, segmentsWidth, segmentsHeight, phiStart, phiLength, thetaStart, thetaLength)
radius
是半径
;segmentsWidth
表示经度上的切片数
;segmentsHeight
表示纬度上的切片数
;phiStart
表示经度开始的弧度
;phiLength
表示经度跨过的弧度
;thetaStart
表示纬度开始的弧度
;thetaLength
表示纬度跨过的弧度
。分段
segmentsWidth
和segmentsHeight
。使用var sphere = new THREE.SphereGeometry(2, 8, 6)
能够建立一个半径为2
,经度
划分红8
份,纬度
划分红6
份的球体
:var sphere = new THREE.Mesh( new THREE.SphereGeometry(2, 8, 6), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(sphere);
new THREE.SphereGeometry(2, 8, 16)
的效果如图:new THREE.SphereGeometry(3, 18, 12)
的效果如图:segmentsWidth
至关于经度被切成了几瓣
,而segmentsHeight
至关于纬度被切成了几层
。由于在图形底层的实现中,并没有曲线
的概念,曲线都是由多个折线近似
构成的。对于球体而言,当这两个值较大
的时候,造成的多面体
就能够近似
看作是球体了。经度弧度
new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI / 3)
表示起始经度为Math.PI / 6
,经度跨度为Math.PI / 3
。var sphere = new THREE.Mesh( new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI / 3), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(sphere);
SegmentsWidth
为8
意味着对于经度从Math.PI / 2
跨过Math.PI / 3
的区域内
划分为8
块,而不是整个球体的经度划分红8块后再判断在此经度范围内的部分。纬度弧度
new THREE.SphereGeometry(2, 8, 6, 0, Math.PI * 2, Math.PI / 6, Math.PI / 3)
意味着纬度从Math.PI / 6
跨过Math.PI / 3
:var sphere = new THREE.Mesh( // 经度起始弧度为0度,经度跨度为 180*2 new THREE.SphereGeometry(2, 8, 6, 0, Math.PI * 2, Math.PI / 6, Math.PI / 3), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(sphere);
经度纬度
都改变了起始位置和跨度
的例子:new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI, Math.PI / 6, Math.PI / 2)
:var sphere = new THREE.Mesh( new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI, Math.PI / 6, Math.PI / 2), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(sphere);
圆形(CircleGeometry
)能够建立圆形或者扇形
,其构造函数是:
new THREE.CircleGeometry(radius, segments, thetaStart, thetaLength)
radius
是半径;segments
表示切片数;thetaStart
表示纬度开始的弧度
;thetaLength
表示纬度跨过的弧度
。new THREE.CircleGeometry(3, 18, Math.PI / 3, Math.PI / 3 * 4)
能够建立一个在x轴和y轴所在平面的三分之二圆的扇形:var circle = new THREE.Mesh( new THREE.CircleGeometry(2, 18, Math.PI / 3, Math.PI / 3 * 4), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(circle);
圆柱体(
CylinderGeometry
)的构造函数是:
new THREE.CylinderGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded)
radiusTop
与radiusBottom
分别是顶面和底面的半径
,由此可知,当这两个参数设置为不一样的值时,实际上建立的是一个圆台;height
是圆柱体的高度
;radiusSegments
与heightSegments
可类比球体中的分段
,一个表示底面、顶面的分段,另外一个表示环面的分段;openEnded
是一个布尔值,表示是否没有顶面和底面,缺省值为false
,表示有顶面和底面。标准圆柱体
new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3)
建立一个顶面与底面半径都为2,高度为4的圆柱体:var cylinder = new THREE.Mesh( new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(cylinder);
圆台
2
建立一个圆台:new THREE.CylinderGeometry(1.5, 2, 3, 18, 3)
:var cylinder = new THREE.Mesh( new THREE.CylinderGeometry(1.5, 2, 3, 18, 3), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(cylinder);
无底面、顶面
openEnded
为true
的时候,将无底面、顶面。new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3, true)
将建立一个没有顶面与底面的圆柱:var cylinder = new THREE.Mesh( new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3, true), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(cylinder);
正四面体(TetrahedronGeometry
)、正八面体(OctahedronGeometry
)、正二十面体(IcosahedronGeometry
)的构造函数较为相似,分别为:
// 正四面体 new THREE.TetrahedronGeometry(radius, detail) // 正八面体 new THREE.OctahedronGeometry(radius, detail) // 正二十面体 new THREE.IcosahedronGeometry(radius, detail)
radius
是半径;detail
是细节层次(Level of Detail
)的层数,对于大面片数模型,能够控制在视角靠近物体时,显示面片数多的精细模型,而在离物体较远时,显示面片数较少的粗略模型。这里咱们不对detail多做展开,通常能够对这个值缺省。正四面体
new THREE.TetrahedronGeometry(2.5)
建立一个半径
为2.5
的正四面体:var tetrahedron = new THREE.Mesh( new THREE.TetrahedronGeometry(2.5), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(tetrahedron);
正八面体
new THREE.OctahedronGeometry(2.5)
建立一个半径为2.5
的正八面体:var octahedron = new THREE.Mesh( new THREE.OctahedronGeometry(2.5), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(octahedron);
正二十面体
new THREE.IcosahedronGeometry(2.5)
建立一个半径为2.5
的正二十面体:var icosahedron = new THREE.Mesh( new THREE.IcosahedronGeometry(2.5), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(icosahedron);
圆环面(
TorusGeometry
)就是甜甜圈的形状,其构造函数是:
new THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, arc)
radius
是圆环半径;tube
是管道半径;radialSegments
与tubularSegments
分别是两个分段数,详见上图;arc
是圆环面的弧度,缺省值为Math.PI * 2
。粗糙圆环面
new THREE.TorusGeometry(2, 0.7, 4, 8)
建立一个粗糙的圆环面:var torus = new THREE.Mesh( new THREE.TorusGeometry(2, 0.7, 4, 8), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(torus);
精细圆环面
new THREE.TorusGeometry(2, 0.7, 12, 18)
建立一个较为精细的圆环面:var torus = new THREE.Mesh( new THREE.TorusGeometry(2, 0.7, 12, 18), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(torus);
部分圆环面
new THREE.TorusGeometry(2, 0.7, 4, 8, Math.PI / 3 * 2)
建立部分圆环面:var torus = new THREE.Mesh( new THREE.TorusGeometry(2, 0.7, 4, 8, Math.PI / 3 * 2), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(torus);
若是说圆环面是甜甜圈,那么圆环结(
TorusKnotGeometry
)就是打告终的甜甜圈,其构造参数为:
new THREE.TorusKnotGeometry(radius, tube, radialSegments, tubularSegments, p, q, heightScale)
p
和q
是控制其样式
的参数,通常能够缺省,若是须要详细了解,请学习圆环结的相关知识;heightScale
是在z轴
方向上的缩放。new THREE.TorusKnotGeometry(2, 0.5, 32, 8)
默认样式的圆环结:var torus = new THREE.Mesh( new THREE.TorusKnotGeometry(1.6, 0.4, 32, 8), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(torus);
文字形状(
TextGeometry
)能够用来建立三维的文字形状。
使用文字前,须要下载和引用额外的字体库。字体库在
three.js Github master/examples/fonts目录下,下载里面的
json
文件,放在你的目录下,而后加载。
helvetiker字体
为例。咱们在刚刚的字体库目录下,下载helvetiker_regular.typeface.json
文件放在你的目录下,而后用如下方法加载:// 调用一个字体加载函数 var loader = new THREE.FontLoader(); loader.load('helvetiker_regular.typeface.json', function(font) { var mesh = new THREE.Mesh( new THREE.TextGeometry('Hello', { font: font, size: 1, height: 1 }), new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }) ); scene.add(mesh); // 写在loader函数里面 不然不显示 renderer.render(scene,camera); });
注意:
73dev
版本的three.js,执行代码的时候发现报错,多是尚未添加这个功能,因此建议去下载最新版本的three.js。webstorm
编辑器,由于它打开html文件时,就是以本地服务器的方式打开的。或者在cmd命令行中输入live-server
,但须要配置,具体方法请点这里。建立文字形状的流程和以前介绍的基本几何形状是相似的,其构造函数是:
new THREE.TextGeometry(text, parameters)
其中,text
是要显示的文字字符串,parameters
是如下参数组成的对象:
size
:字号大小,通常为大写字母的高度height
:文字的厚度curveSegments
:弧线分段数,使得文字的曲线更加光滑font
:字体,默认是'helvetiker'
,需对应引用的字体文件weight
:值为'normal'
或'bold'
,表示是否加粗style
:值为'normal'
或'italics'
,表示是否斜体bevelEnabled
:布尔值,是否使用倒角,意为在边缘处斜切bevelThickness
:倒角厚度bevelSize
:倒角宽度
建立一个三维文字
new THREE.TextGeometry("hello", {size: 1, height: 1})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>hello</title> <script type="text/javascript" src="js/three.js"></script> </head> <body onload="init()"> <script> function init() { // 调用一个渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0x000000); // 调用场景 var scene = new THREE.Scene(); // 调用相机 var camera = new THREE.OrthographicCamera(-4, 4, 3, -3, 0.1, 100); camera.position.set(5, 5, 20); camera.lookAt(new THREE.Vector3(1.1, 0, 0)); scene.add(camera); // 定义材质 var material = new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true }); // 加载文字模板 var loader = new THREE.FontLoader(); loader.load('helvetiker_regular.typeface.json', function(font) { // 中文字符不能解析 var mesh = new THREE.Mesh(new THREE.TextGeometry('hello', { font: font, size: 1, height: 1 }), material); scene.add(mesh); // 渲染必定要在load函数里面 renderer.render(scene, camera); }) } </script> </body> </html>
// 将材质改成lambert材质 var material = new THREE.MeshLambertMaterial({ color: 0xffff00 }); // 加上一束方向光 var light = new THREE.DirectionalLight(0xffffff, 1); light.position.set(1, 0, 0.5); scene.add(light);
对于Three.js没有提供的形状,能够经过自定义形状来建立。
Geometry
类,它是其余如CubeGeometry、SphereGeometry等几何形状的父类,其构造函数是:new THREE.Geometry()
咱们以建立一个梯台为例,首先,初始化一个几何形状,而后设置顶点位置以及顶点链接状况。
geometry
建立点的时候都是push
到数组vertices
里面的Face3
的方法将3
点连成一个三角面
// 初始化几何形状 var geometry = new THREE.Geometry(); // 设置顶点的位置 // 顶部4个点 geometry.vertices.push(new THREE.Vector3(-1, 2, -1)); geometry.vertices.push(new THREE.Vector3(1, 2, -1)); geometry.vertices.push(new THREE.Vector3(1, 2, 1)); geometry.vertices.push(new THREE.Vector3(-1, 2, 1)); // 底部4顶点 geometry.vertices.push(new THREE.Vector3(-2, 0, -2)); geometry.vertices.push(new THREE.Vector3(2, 0, -2)); geometry.vertices.push(new THREE.Vector3(2, 0, 2)); geometry.vertices.push(new THREE.Vector3(-2, 0, 2)); // 设置顶点链接状况 // 顶面 geometry.faces.push(new THREE.Face3(0, 1, 3)); geometry.faces.push(new THREE.Face3(1, 2, 3)); // 底面 geometry.faces.push(new THREE.Face3(4, 5, 6)); geometry.faces.push(new THREE.Face3(5, 6, 7)); // 四个侧面 geometry.faces.push(new THREE.Face3(1, 5, 6)); geometry.faces.push(new THREE.Face3(6, 2, 1)); geometry.faces.push(new THREE.Face3(2, 6, 7)); geometry.faces.push(new THREE.Face3(7, 3, 2)); geometry.faces.push(new THREE.Face3(3, 7, 0)); geometry.faces.push(new THREE.Face3(7, 4, 0)); geometry.faces.push(new THREE.Face3(0, 4, 5)); geometry.faces.push(new THREE.Face3(0, 5, 1));
总结:
new THREE.Vector3(-1, 2, -1)
建立一个矢量
,做为顶点位置追加到geometry.vertices
数组中。new THREE.Face3(0, 1, 3)
建立一个三个顶点组成的面片
,追加到geometry.faces
数组中。三个参数分别是四个顶点在geometry.vertices
中的序号。
材质(
material
),是独立于物体顶点信息以外的与渲染效果相关的属性。经过设置材质能够改变物体颜色、纹理贴图、光照模式等。
基本材质
、两种基于光照模型材质
、法向量做为材质
、 图像做为材质
。使用基本材质(BasicMaterial
)的物体,渲染后物体的颜色,始终为该材质的颜色
,不会因为光照产生明暗、阴影效果。若是没有指定材质的颜色,则颜色是随机的,构造函数以下:
new THREE.MeshBasicMaterial(opt)
opt
能够缺省,或者为包含各属性的值。如,为一个黄色正方体添加一个1不透明度 (opacity)
:new THREE.MeshBasicMaterial({ color: 0xffff00, opacity: 0.75 });
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>基本材质</title> <script type="text/javascript" src="js/three.js"></script> </head> <body onload="init();"> <script> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0x000000); // 场景 var scene = new THREE.Scene(); // 相机 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); // 光 var light = new THREE.PointLight(0xffffff, 1, 100); light.position.set(10, 15, 5); scene.add(light); // 材质 var material = new THREE.MeshBasicMaterial({ color: 0xffff00, opacity: 0.75 }); // 几何体 var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material); scene.add(cube); // 渲染 renderer.render(scene, camera); } </script> </body> </html>
下面,介绍几个经常使用的属性
visible
:是否可见,默认为trueside
:渲染面片正面或是反面,默认为正面THREE.FrontSide
,可设置为反面THREE.BackSide
,或双面THREE.DoubleSide
wireframe
:是否渲染线而非面,默认为false
color
:十六进制RGB颜色,如红色表示为0xff0000map
:使用纹理贴图(下面会着重讲解)基本材质
,即便改变场景中的光源,使用该材质的物体也始终为颜色到处相同的效果。固然,这不是很具备真实感,所以,接下来咱们将介绍更为真实的光照模型:Lambert光照模型以及Phong光照模型。Lambert材质(MeshLambertMaterial
)是符合Lambert光照模型的材质。Lambert光照模型的主要特色是只考虑漫反射
而不考虑镜面反射
的效果,于是对于金属、镜子等须要镜面反射效果的物体就不适应
,对于其余大部分物体的漫反射效果都是适用的。
Idiffuse = Kd * Id * cos(theta)
Idiffuse
是漫反射光强,Kd
是物体表面的漫反射属性,Id
是光强,theta
是光的入射角弧度。new THREE.MeshLambertMaterial()
示例代码(建立一个黄色并使用光照的立方体):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Lambert材质</title> <script type="text/javascript" src="js/three.js"></script> </head> <body onload="init();"> <script> function init() { // 渲染 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0x000000); // 场景 var scene = new THREE.Scene(); // 相机 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); // 添加光照 var light = new THREE.PointLight(0xffffff, 1, 100); light.position.set(10, 15, 5); scene.add(light); // Lambert材质 var material = new THREE.MeshLambertMaterial({ color: 0xffff00, }); // 几何体 var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material); scene.add(cube); // 渲染 renderer.render(scene, camera); } </script> </body> </html>
下面,介绍几个经常使用的属性:
color
是用来表现材质对散射光的反射能力,也是最经常使用来设置材质颜色的属性。除此以外,还能够用ambient
和emissive
控制材质的颜色。ambient
表示对环境光
的反射能力
,只有当设置了AmbientLight
后,该值才是有效的,材质对环境光的反射能力与环境光强相乘后获得材质实际表现的颜色。emissive
是材质的自发光
颜色,能够用来表现光源的颜色。var material = new THREE.MeshLambertMaterial({ emissive: 0xff0000 })
var material = new THREE.MeshLambertMaterial({ color: 0xffff00, emissive: 0xff0000 })
var material = new THREE.MeshLambertMaterial({ color: 0xffff00, emissive: 0xff0000 }); var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material); scene.add(sphere);
Phong材质(MeshPhongMaterial
)是符合Phong光照模型的材质。和Lambert不一样的是,Phong模型考虑了镜面反射
的效果,所以对于金属、镜面的表现尤其适合。
Ispecular = Ks * Is * (cos(alpha)) ^ n
Ispecular
是镜面反射的光强
,Ks
是材质表面镜面反射系数
,Is
是光源强度
,alpha
是反射光与视线的夹角
,n
是高光指数
,越大则高光光斑越小。new THREE.MeshPhongMaterial({ color: 0xffff00 });
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Phong材质</title> <script type="text/javascript" src="js/three.js"></script> </head> <body onload="init();"> <script> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0x000000); // 场景 var scene = new THREE.Scene(); // 相机 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); // 光照 var light = new THREE.PointLight(0xffffff, 1, 200); light.position.set(10, 15, 25); scene.add(light); // 材质 var material = new THREE.MeshPhongMaterial({ color: 0xffff00, //specular: 0xffff00, //shininess: 1000 }); // 几何体 var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material); scene.add(cube); //var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material); //scene.add(sphere); // 渲染 renderer.render(scene, camera); } </script> </body> </html>
下面,介绍几个经常使用的属性:
emissive
和ambient
值,这里再也不说明。specular
值指定镜面反射系数做说明。specular
),将高光设为红色,应用于一个球体:var material = new THREE.MeshPhongMaterial({ specular: 0xff0000 }); var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material); scene.add(sphere);
shininess
属性控制光照模型中的n值*(高光指数,光斑)
,当shininess
值越大时,高光的光斑越小
,默认值为30
。咱们将其设置为1000
时:var material = new THREE.MeshPhongMaterial({ specular: 0xff0000, shininess: 1000 });
material = new THREE.MeshPhongMaterial({ color: 0xff0000, specular: 0xffff00, shininess: 1000 });
法向材质能够将材质的颜色设置为其
法向量的方向
,有时候对于调试颇有帮助。
new THREE.MeshNormalMaterial()
材质的颜色与照相机与该物体的角度相关,下面咱们只改变照相机位置,观察两个角度的颜色变化:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>法向材质</title> <script type="text/javascript" src="js/three.js"></script> </head> <body onload="init();"> <script> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0x000000); // 场景 var scene = new THREE.Scene(); // 相机 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); // 光照 var light = new THREE.PointLight(0xffffff, 1, 200); light.position.set(10, 15, 25); scene.add(light); // 材质 var material = new THREE.MeshNormalMaterial(); // 几何体 var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material); scene.add(cube); // 渲染 renderer.render(scene, camera); } </script> </body> </html>
camera.position.set(5, 25, 25);
的效果图:camera.position.set(25, 25, 25);
的效果图:在此以前,咱们使用的材质都是单一颜色的,有时候,咱们却但愿使用图像做为材质。这时候,就须要导入图像做为纹理贴图,并添加到相应的材质中。
texture
中:var texture = THREE.ImageUtils.loadTexture('images/01.jpg');
map
属性设置为texture
:var material = new THREE.MeshLambertMaterial({ map: texture });
var texture = THREE.ImageUtils.loadTexture('images/01.jpg', {}, function() { renderer.render(scene, camera); }); var material = new THREE.MeshLambertMaterial({ map: texture });
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>纹理贴图</title> <script type="text/javascript" src="js/three.js"></script> </head> <body onload="init();"> <script> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0x000000); // 场景 var scene = new THREE.Scene(); // 相机 var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 1000); camera.position.set(25, 25, 25); camera.lookAt(new THREE.Vector3(0, 0, 0)); scene.add(camera); // 光照 var light = new THREE.PointLight(0xffffff, 1, 200); light.position.set(10, 15, 25); scene.add(light); // 纹理(须要重绘函数) var texture = THREE.ImageUtils.loadTexture('images/01.jpg', {}, function() { renderer.render(scene, camera); }); // 材质 var material = new THREE.MeshLambertMaterial({ map: texture }); // 几何体 var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material); scene.add(cube); // var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material); // scene.add(sphere); // 渲染 renderer.render(scene, camera); } </script> </body> </html>
有时候,咱们但愿长方体的六面各类的贴图都不一样。所以,咱们首先准备了六张颜色各异的图像,分别写了数字01到06。而后,分别导入图像到六个纹理,并设置到六个材质中:
var materials = []; for (var i = 1; i < 7; ++i) { materials.push(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture('images/0' + i + '.jpg', {}, function() { renderer.render(scene, camera); }), overdraw: true })); } var cube = new THREE.Mesh( new THREE.CubeGeometry(2, 2, 2), new THREE.MeshFaceMaterial(materials)); scene.add(cube);
用黑白相间的图片绘制一副棋盘
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>棋盘</title> <script type="text/javascript" src="js/three.js"></script> </head> <body onload="init();"> <script> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0xffffff); // 场景 var scene = new THREE.Scene(); // 相机 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); // 光照 var light = new THREE.PointLight(0xffffff, 1, 1000); light.position.set(10, 15, 25); scene.add(light); var texture = THREE.ImageUtils.loadTexture('images/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> </body> </html>
但是,棋盘格是8横8纵64
个小方格组成的,那应该怎么办呢?
wrapS
和wrapT
)都重复:texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(4, 4);
在学习了几何形状和材质以后,咱们就能使用他们来建立物体了。最经常使用的一种物体就是网格(Mesh),网格是由顶点、边、面等组成的物体;其余物体包括线段(Line
)、骨骼(Bone
)、粒子系统(ParticleSystem
)等。建立物体须要指定几何形状和材质,其中,几何形状决定了物体的顶点位置
等信息,材质决定了物体的颜色、纹理
等信息。
在上两节中,咱们学习了如何建立几何形状与材质,而网格的建立很是简单,只要把几何形状与材质传入其构造函数。最经常使用的物体是网格(Mesh
),它表明包含点、线、面
的几何体,其构造函数是:
// geometry : 定义的几何体 // material : 材质 new THREE.Mesh(geometry,material)
// 几何体(长方体) var geometry = new THREE.CubeGeometry(0.6, 1.2, 1.8); // 材质 var material = new THREE.MeshLambertMaterial({ color: 0xffff00 }); // 网格 var mesh = new THREE.Mesh(geometry, material); scene.add(mesh);
material
和geometry
以后不会复用
的话,也能够合在一块儿写为:var mesh = new THREE.Mesh(new THREE.CubeGeometry(0.6, 1.2, 1.8), new THREE.MeshLambertMaterial({ color: 0xffff00 }) ); scene.add(mesh);
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>网格</title> <script type="text/javascript" src="js/three.js"></script> </head> <body onload="init();"> <script> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0x000000); // 场景 var scene = new THREE.Scene(); // 相机 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(0, 0, 0)); scene.add(camera); // 光照 var light = new THREE.DirectionalLight(0xffffff); light.position.set(20, 10, 5); scene.add(light); // 材质 var material = new THREE.MeshLambertMaterial({ color: 0xffff00 }); // 几何体 var geometry = new THREE.CubeGeometry(0.6, 1.2, 1.8); // 网格 var mesh = new THREE.Mesh(geometry, material); scene.add(mesh); // render renderer.render(scene, camera); } </script> </body> </html>
除了在构造函数中指定材质,在网格被建立后,也能对材质进行修改:
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 });
位置、缩放、旋转是物体三个经常使用属性。因为THREE.Mesh
基础自THREE.Object3D
,所以包含scale、rotation、position
三个属性。它们都是THREE.Vector3
实例,所以修改其值的方法是相同的,这里以位置
为例。
THREE.Vector3
有x、y、z
三个属性,若是只设置其中一个属性,则能够用如下方法:mesh.position.z = 1;
同时
设置多个
属性,可使用如下两种方法:mesh.position.set(1.5, -0.5, 0);
mesh.position = new THREE.Vector3(1.5, -0.5, 0);
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改位置</title> <script type="text/javascript" src="js/three.js"></script> </head> <body onload="init();"> <script> function init() { // 渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(800, 600); document.body.appendChild(renderer.domElement); renderer.setClearColor(0x000000); // 场景 var scene = new THREE.Scene(); // 相机 var camera = new THREE.OrthographicCamera(-2.5, 2.5, 1.875, -1.875, 0.1, 100); camera.position.set(5, 5, 10); camera.lookAt(new THREE.Vector3(0, 0, 0)); scene.add(camera); var material = new THREE.MeshLambertMaterial({ color: 0xffff00 }); var geometry = new THREE.CubeGeometry(0.6, 1.2, 1.8); var mesh = new THREE.Mesh(geometry, material); scene.add(mesh); // 修改位置属性 mesh.position.set(1, 0, 0); // mesh.position = new THREE.Vector3(1.5, -0.5, 0); // mesh.position.x = 1; var light = new THREE.DirectionalLight(0xffffff); light.position.set(20, 10, 5); scene.add(light); // 坐标轴 drawAxes(scene); // 渲染 renderer.render(scene, camera); function drawAxes(scene) { // x-axis var xGeo = new THREE.Geometry(); xGeo.vertices.push(new THREE.Vector3(0, 0, 0)); xGeo.vertices.push(new THREE.Vector3(3, 0, 0)); var xMat = new THREE.LineBasicMaterial({ color: 0xff0000 }); var xAxis = new THREE.Line(xGeo, xMat); scene.add(xAxis); // y-axis var yGeo = new THREE.Geometry(); yGeo.vertices.push(new THREE.Vector3(0, 0, 0)); yGeo.vertices.push(new THREE.Vector3(0, 3, 0)); var yMat = new THREE.LineBasicMaterial({ color: 0x00ff00 }); var yAxis = new THREE.Line(yGeo, yMat); scene.add(yAxis); // z-axis var zGeo = new THREE.Geometry(); zGeo.vertices.push(new THREE.Vector3(0, 0, 0)); zGeo.vertices.push(new THREE.Vector3(0, 0, 3)); var zMat = new THREE.LineBasicMaterial({ color: 0x00ccff }); var zAxis = new THREE.Line(zGeo, zMat); scene.add(zAxis); } } </script> </body> </html>
缩放
对应的属性是scale
,旋转
对应的属性是rotation
,具体方法与上例相同,分别表示沿x、y、z
三轴缩放或旋转。