1# 开始做一个可运行的threejs例子

先运行一段threejs代码,然后再分析。
代码如下:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
    <meta name="format-detection" content="telephone=no">
    <title>three.js</title>
    <script src="./three.min.js"></script>
</head>
<body>
<script>
// 画布的宽度
var cw = 500, ch = 500;

// 1. 建立一个场景
var scene = new THREE.Scene(); 

// 2. 设立相机
var camera = new THREE.PerspectiveCamera( 75, cw / ch, 0.1, 1000 );
camera.position.z = 5;

// 3. 准备渲染器
var renderer = new THREE.WebGLRenderer();
renderer.setSize( cw, ch );
document.body.appendChild( renderer.domElement );

// 4. 演员准备好
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );

// 4.1 演员就位
scene.add( cube );

// 5. 开始表演(渲染)
//renderer.render( scene, camera );

// 动画
let timer = null;
function render() {
    if (timer) {
        clearTimeout(timer);
        timer = null;
    }

    cube.rotation.x += 0.1;
    cube.rotation.y += 0.1;

    renderer.render( scene, camera );

    //requestAnimationFrame( render );
    timer = setTimeout(render,100);
}
render();

</script>
</body>
</html>

对上面的代码进行分析

Three.js使用的是面向对象的方式来构建程序,包含3个基本对象: 场景(scene), 相机(camera), 以及一个渲染器(renderer)。
拿电影来类比的话,场景对应于整个布景空间,相机是拍摄镜头,渲染器用来把拍摄好的场景转换成胶卷(对于网页来讲,是电脑屏幕)。 场景和相机代表了3D观察空间和数据模型,渲染器则包含了WebGL绘图上下文和着色器。

第一步,建立一个场景,这个比较好理解。

var scene = new THREE.Scene();
场景是所有物体的容器,可以理解为canvas画布。

第二步,设立一台相机,这里用的是最常见的远景相机(PerspectiveCamera),或者称为透视投影照相机,它类似于人眼观察的方式。

除了远景相机(透视投影照相机)还有其他很多种相机,平常用的不多,稍后涉及。

var camera = new THREE.PerspectiveCamera( 75, cw / ch, 0.1, 1000 );
PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

PerspectiveCamera是Camera抽象类的一个子类,它的四个参数见下面的图:


视锥体.png

如上图,这四个参数一起定义了摄像机的[viewing frustum](视锥体)。
fov是视角(field of view),即视景体竖直方向上的张角(是角度制而非弧度制),如侧视图所示。
aspect是相机拍摄面的长宽比(aspect ratio),即照相机水平方向和竖直方向长度的比值,通常设为Canvas的横纵比例。我们几乎总是会使用元素的宽除以高,否则会出现挤压变形。
near和far是近裁剪面(near clipping plane)和 远裁剪面(far clipping plane),即照相机到视景体最近、最远的距离,均为正值,且far应大于near。
透视图中,灰色的部分是视景体,即near平面和far平面之间的矩形体,是可能被渲染的物体所在的区域,超出这个范围,物体时渲染不出来的。

第三步,准备渲染器,也比较好理解。

var renderer = new THREE.WebGLRenderer();
除了我们这里使用的WebGLRenderer,three.js还支持一些其它渲染器,基本上只是用来回退处理那些不支持WebGL的旧式用户浏览器。
除了创建renderer实例,我们还需要设置渲染空间的尺寸,一般就使用目标canvas的宽高(cw和ch),也可以给定一个小尺寸。
如果你想保持渲染空间的尺寸,但使用一个较低的分辨率,你可以在调用setSize的时候设置参数updateStyle为false,比如 setSize(cw/2, ch/2, false) 将使用1/2分辨率来绘制你的应用程序,假定<canvas>为100%的宽高。
最后,我们把 renderer 元素添加到HTML文档中。这里是一个 <canvas> 元素,渲染器用来显示场景。

第四步,演员做好准备

var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
我们使用盒子模型(BoxGeometry),这是一个包含立方体所有顶点和填充面的对象。
除了这个几何模型(geometry)外,我们还需要一个材料(material)来对其着色。Three.js支持多种材料,现在我们只使用 网孔基础材料(MeshBasicMaterial)。 所有材料都含有一个属性对象。这里简单起见,我们只提供了颜色值为0x00ff00,表示绿色。这和CSS和Photoshop中16进制颜色值一样。
还有就是我们需要一个网孔(Mesh)。网孔是用来承载几何模型的一个对象,还可以把材料应用到它上面,然后添加到场景中。
默认情况下,当我们调用 scene.add() 时,对象将被添加到原点处,即坐标点(0,0,0)。

第五步,渲染

renderer.render( scene, camera );
页面会渲染出一个绿色的矩形,看不出3D效果,所以代码里面用来动画,让立方体旋转起来,由于requestAnimationFrame动画旋转太快,所以用setTimeout改写了一下,让立方体旋转的慢一点。

参考资料:

  1. https://www.techbrood.com/threejs/docs/
  2. http://www.ituring.com.cn/book/miniarticle/49446
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351