这并不是算一个教程,更像是一个笔记,笔者水平有限;如果读起来感觉不对应该广泛查询资料。
关于Three.js
Three.js是一个WebGL的库,可以快速在网页上创建三维效果。
其所用的编程语言是java script,而我平时工作是用的C++,并不是太懂这门语言,特别是其中如何操作网页的部分;不过也是类C语言,可以边做边学嘛。
而WebGL顾名思意就是Web版的OpenGL,查了下资料是OpenGL ES 2.0的规范,新版的似乎是用ES 3.0,不过好像要很新的浏览器才支持。
OpenGL ES和其桌面版的我都用过,所以我并不是想单独学习WebGL。
如何学习
花了几天时间找了下相关教程,不过好像都不太理想,原因有二:
1. Three.js的版本更新很快
2. Three.js的应用好像的确有限。
3. 用来写写随机效果尚可,但是用来写3D应用程序很困难,虽然现在CPU性能过剩,但是js的效率还是差了太多,官方demo里有些例子都卡得不像话(那个化学分子式的三维渲染,demo有2个版本;其中一个用的是vbo,而一个好像没有用,我1080P的分辨率和650M的显卡,没有用vbo的只有10帧不到,用了的有10多帧)。
其次是js似乎语言缺陷方面的原因,代码多了维护不便。
找到的很多教程都普遍落后10+的版本(写文时版本为r88);国内更惨,好像12年~15年有人做,后面就没了。
还是用官方文档和demo来学习吧,three.js是挂在github上的,clone下来,里面的文件夹,build是库文件,docs是文档,examples里全是例子。
打开docs/index.html点击Useful links,再打开Examples分类下Professor Stemkoskis Examples,就有些简单的入门例子了;
不过这些例子版本都是60。
本文是其中Hello World改来的。
0. 本文做了什么
创建了一个渲染框架,并渲染了一个正方体,并且可以操纵相机。
1. 开始
构键html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>canvas { width:100%;height: 100%}</style>
</head>
<body>
</body>
</html>
将canvas画布设置为全页面。
加入js文件
在<body>
下放入
<script src="src/js/three.js"></script>
<script>
</script>
第一个js文件为three.js官方库,从你在github上clone下来的build中可以找到,
你也可以把它改成three.min.js
,文件大小会小很多,内容和three.js
一样;这个是消除了空行的,你没办法查看其中的api,所以推荐用three.js
。
而three.module.js
我不太懂,好像是另一种模组加载库文件的方式?
第二个js文件script
里是空的,接下来我们要在里面添加自己的代码。
全局变量
在空的<script>
下加入
var scene, camera, renderer;
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
scene是场景,渲染的根节点。场景应该是一个树状结构,场景下可以放入很多物体,物体下又可以放入子物体这样。
总的来说就是一个容器。
camera是摄像机,如果你要看到画面的话这是必须的;
它就好比你的眼睛。
renderer是渲染器,负责在Web页面上渲染画面。
后面2个是画面的宽和高。
初始化
接着加入
function init()
{
}
创建场景
在init()
加入
// create scene
{
scene = new THREE.Scene();
}
空的场景。
创建相机
接着在init()
加入
// create camera
{
var VIEW_ANGLE = 75;
var ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT;
var NEAR = 0.1;
var FAR = 10000;
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set(0, 150, 400);
camera.lookAt(scene.position);
scene.add(camera);
}
VIEW_ANGLE是重载可视角度,即FOV,越大就代表你的眼睛会看到越“高”的场景。
人眼的水平视角是188度,一般16比9设75度,4比3则可以设45度看起来比较舒服。
FOV过大会显得离场景变远,过小则像抵近了看一般。
你可以尝试设置不同的值,并改变浏览器窗口的长宽比看看效果。
ASPECT则是宽/长比;上面的FOV决定你看到的宽度,再用这个值就可以算出你看到的高度。
NEAR和FAR则是相机的近/远平面。过近/过远的物体不会被渲染。
THREE.PerspectiveCamera
是指的透视相机。
渲染三维场景用透视,才会有远小近大的效果。
相对的有正交相机,可以用来渲染HUD、地图、二维游戏,远近并不影响大小。
然后设置了相机的位置。
OpenGL的坐标系是Y轴向上的左手坐标系,X向右,Y向上,Z朝屏幕外。
如果地面的高度即Y值是0的话,这里的相机高度就是150,离世界坐标原点400朝屏幕外。
lookAt设置视点,这里视点是scene的位置,我们并没有改变过scene的位置,即默认的xyz都是0。
最后将相机加入场景,请不要忘记这步。
一个场景是可以有多个相机的,多个相机不只可以分屏,还可以渲染地图、阴影贴图,做RTT。
创建渲染器
接着在init()
加入
// create renderer
{
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
document.body.appendChild(renderer.domElement);
}
渲染器负责渲染场景,这里用的是THREE.WebGLRenderer
即WebGL。
注意这里并没有做检查,如果你的浏览器如果不支持WebGL,那就会出错。
正确的做法应该要检查,不支持的话应该用THREE.CanvasRenderer()
的,这里为了简便并没有这么做。
然后设置渲染器输出画面大小为全屏。
你可以改变大小,如果它们的宽长比和前面的相机宽长比ASPECT
不符合,画面就会被拉伸。
请注意这里不论怎么改,画面虽然被拉伸,但是内容是一致的。
最后把渲染器的dom元素加到web页面中,才能在web页面上看到画面。
创建三维物体
接着在init()
加入
// cube
{
var geom = new THREE.CubeGeometry(100, 100, 100, 1, 1, 2);
var mat = new THREE.MeshBasicMaterial({color:0xff0000});
var cube = new THREE.Mesh(geom, mat);
scene.add(cube);
}
首先调用THREE.CubeGeometry()
创建了一个方块几何体。
方块几何体是几何体的一个派生。几何体有三维物体的顶点、法线信息。
然后用THREE.MeshBasicMaterial()
创建了基础的材质,并设置了颜色是红色。
然后用THREE.Mesh()
创建了网格物体cube
。
网格代表这个物体有几何数据,是可以绘制的;相对应的肯定就有非网格物体,是绘制不出来的。
这里创建的时候用了几何体与材质。
最后把cube
加入到场景下。
到这里init()
函数就写完了。
渲染循环
在我们自己的<script>
中接着加入
function allLoop() {
requestAnimationFrame(allLoop);
renderer.render(scene,camera);
}
这是一个会一直重复执行的回调函数。
requestAnimationFrame()
是js的一个函数,参数是函数。
renderer.render()
则是渲染器用一个场景节点和相机渲染一帧画面。
以上2句结合起来就可以不停重复调用渲染了。
启动
在我们自己的<script>
中接着加入
init();
allLoop();
先初始化,再进入渲染循环。
2. 结果
如果你做的都没错,那么你就可以看到这个画面。如果不对,按F12再检查下吧!
3. 改进
是不是觉得这太LOW了……这算什么三维画面。那么我们加2、3行代码,就可以让画面动起来了!
创建操纵器
在three.js文件引用后加入一个新的引用
<script src="src/js/OrbitControls.js"></script>
这个文件的地址是three.js项目/examples/js/controls/OrbitControls.js
。
在上文中全局变量一节中,再加入一个control变量。
var control;
接着在init()
中加入
// create controls
{
controls = new THREE.OrbitControls(camera, renderer.domElement);
}
controls是操纵器,操纵器控制相机的姿态。
常见的有漫游操纵器,你可以在三维世界中行走;这里用的是轨道操纵器,这个操纵器可以控制相机像一个卫星一样围绕目标旋转。
第1个参数是要控制的相机,第2个则是渲染器的dom元素。
4. 改进结果
你可以用鼠标拖动这个方块了,可以绕到方块的不同角度观看。
是不是很棒?