初识three.js

Three.js是一款webGL框架,由于其易用性被广泛应用。Three.js在WebGL的api接口基础上,又进行的一层封装,所以不用担心他得性能,和主机游戏一样都是支持硬件加速的。它是由居住在西班牙巴塞罗那的程序员Ricardo Cabbello Miguel(https://ricardocabello.com/) 开发的,Three.js以简单、直观的方式封装了3D图形编程中常用的对象。Three.js在开发中使用了很多图形引擎的高级技巧,极大地提高了性能。Three.js还是完全开源的。
里面有很多图形学的概念,比如坐标变换,光照计算,同样可以创建自己的Shader,调用底层的图形接口,框架具有相当高的灵活性。

Webgl和Three.js的关系

Webgl和Three.js的关系,相当于JavaScript和Jquery的关系

创建一个场景

为了真正能够让你的场景借助three.js来进行显示,我们需要以下几个对象:场景、相机和渲染器,这样我们就能透过摄像机渲染出场景。

//创建场景
 const scene = new THREE.Scene();
 //创建一个立方体
 const geometry = new THREE.BoxGeometry( 1, 1, 1 );    //几何形状
 const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); //材质
 const cube = new THREE.Mesh( geometry, material );
 scene.add( cube );

scene以树结构存放所有可见的和不可见的三维物体,包括光源等等


image.png
 //创建一个摄像机
 const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
 camera.position.z = 5;

摄像机决定了我们从什么位置,什么角度观察三维物体

const renderer = new THREE.WebGLRenderer();
 renderer.setSize( window.innerWidth, window.innerHeight );
 document.body.appendChild( renderer.domElement );

渲染器负责将我们的看到的场景树渲染成二维图像

const animate = ()=> {
   requestAnimationFrame( animate );
   //因为JavaScript是单线程的,所以用requestAnimationFrame来请求浏览器定时回调这里的这个animate()
   cube.rotation.x += 0.01;
   cube.rotation.y += 0.01;
   renderer.render( scene, camera );
   //在循环中调用renderer的render()函数来渲染每一帧图像
 }
 animate();

三角网Mesh

立方体是用Mesh(三角网)表示的


image.png

因为三角形的三个点可以空间中唯一地确定一个平面,所以也是最常见的用于表示三维物体的一种方式

Geometry

Geometry代表几何形状,由下面的一个个三角形和构成他们的所有顶点组成


image.png

three.js里内置了很多几何形状

http://www.webgl3d.cn/threejs/docs/#api/zh/geometries/CircleGeometry
    //创建场景
    const scene = new THREE.Scene();
    var geometry = new THREE.CircleBufferGeometry( 5, 32 );
    var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
    var circle = new THREE.Mesh( geometry, material );
    scene.add( circle );
    //创建一个摄像机
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 50;
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    const animate = () => {
        requestAnimationFrame(animate);
        circle.rotation.x += 0.01;
        circle.rotation.y += 0.01;
        renderer.render(scene, camera);
    }
    animate();

Material

Material代表三维物体几何材质,不同的材质在光照下会呈现不一样的效果,通过材质可以给物体表面设定不同的颜色,光泽度,或者给物体加上贴图


1632492310(1).png

基础网格材质(MeshBasicMaterial) 不参与光照计算,不会产生阴影,使用这种材质三维物体看上不去很不真实。

要想有光照效果可以使用下面的两种材质:

  • Phong网格材质(MeshPhongMaterial)
  • Lambert网格材质(MeshLambertMaterial)
    可以用shininess属性来调节物体表面光泽度
    也可以使用map添加贴图
    const material = new THREE.MeshBasicMaterial({ 
        map:new THREE.TextureLoader().load('1.png'),
    }); //材质

MeshStandardMaterialMeshPhysicalMaterial类是PBR物理材质,可以更好的模拟光照计算,相比较高光网格材质MeshPhongMaterial渲染效果更逼真。

emissive默认黑色,设置为白色 发光颜色

emissiveMap 自发光贴图

roughnessMap 粗糙度贴图 设定表面不同位置的粗糙程度

normalMap 法线贴图 给每个像素点设置不同的法向量 法线会影响光照的计算 可以用它模拟物体表面凹凸不平的效果

displacementMap 高度贴图 它会上下偏移物体表面的顶点坐标,从而做到真正的物体表面的起伏

aoMap 环境光遮罩贴图 他会让被遮蔽的区域看起来更暗,进一步提升场景的真实感

    //创建场景
    const scene = new THREE.Scene();
    var geometry = new THREE.SphereBufferGeometry( 5, 32, 32 );
    var texLoader = new THREE.TextureLoader()
    const material = new THREE.MeshPhongMaterial({ 
        emissive:0xffffff,
        // // 发光贴图
        emissiveMap: texLoader.load("wenli.png"),
        // 法线贴图
        normalMap: texLoader.load("faxian.png"),
        // 粗糙度贴图
        roughnessMap: texLoader.load("cucao.png"),
        // //高度贴图
        displacementMap:texLoader.load("weiyi.png"),
        //光罩贴图,会让深坑得地方更暗,更有真实感
        aoMap:texLoader.load("aoMap.png"),
    }); //材质
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    //创建一个摄像机
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 17;
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    const animate = () => {
        requestAnimationFrame(animate);
        //因为JavaScript是单线程的,所以用requestAnimationFrame来请求浏览器定时回调这里的这个animate()
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
        renderer.render(scene, camera);
        //在循环中调用renderer的render()函数来渲染每一帧图像
    }
    animate();

几何转换

创建Mesh之后,我们可以通过position修改几何物体在空间的位置

    const material = new THREE.MeshPhongMaterial({ 
        emissive:0xffffff,
        // // 发光贴图
        emissiveMap: texLoader.load("wenli.png"),
        // 法线贴图
        normalMap: texLoader.load("faxian.png"),
        // 粗糙度贴图
        roughnessMap: texLoader.load("cucao.png"),
        // //高度贴图
        displacementMap:texLoader.load("weiyi.png"),
        //光罩贴图,会让深坑得地方更暗,更有真实感
        aoMap:texLoader.load("aoMap.png"),
    }); //材质
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    cube.position.set(4,0,0)

scale用来转换物体的大小 rotation旋转物体

       const material = new THREE.MeshPhongMaterial({ 
        emissive:0xffffff,
        // // 发光贴图
        emissiveMap: texLoader.load("wenli.png"),
        // 法线贴图
        normalMap: texLoader.load("faxian.png"),
        // 粗糙度贴图
        roughnessMap: texLoader.load("cucao.png"),
        // //高度贴图
        displacementMap:texLoader.load("weiyi.png"),
        //光罩贴图,会让深坑得地方更暗,更有真实感
        aoMap:texLoader.load("aoMap.png"),
    }); //材质
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    cube.scale.multiplyScalar(2)

摄像机

摄像机决定了我们应当从什么角度观察这个三维场景

three.js中提供了两种不同类型的摄像机

PerspectiveCamera

PerspectiveCamera和我们人眼成像原理类似,看到的物体呈远小近大的透视效果。


1632492626(1).png

创建相机的时候先创建视锥


1632492654(1).png

在渲染的时候,计算机会将视锥中的所有三维物体投影到二维屏幕上
1632492676(1).png
    const camera = new THREE.PerspectiveCamera(
        75, //fov  代表垂直方向上视角的大小
        window.innerWidth / window.innerHeight, //aspect ratio 代表投影平面的纵宽比
        0.1, //near  代表相机能看到的最近的平面
        1000 //far   代表相机能看到的最远的平面,超出这个平面的场景会被自动裁剪掉
    );

OrthographicCamera

OrthographicCamera正交投影相机,会将空间中的所有物体平行投影到投影面上,所以不会呈现近大远小的效果


1632492729(1).png

一般应用在像CAD这种需要精确测量物体尺寸的应用场景中


1632492749(1).png

比如用正交投影可以轻易的渲染出物体的三视图等等

正交相机的视锥(Frustum)是一个长方体,所以定义正交相机要先定义前后左右上下这6个面的位置

    const camera = new THREE.OrthographicCamera(
        -2,//left 
        2,//right 
        1.5,//top
        -1.5,//bottom
        1,//near
        10 //far
    );

一样使用position属性修改相机的位置

//三种修改position的方法
camera.position.set(0,1,5)
camera.position.y += 2
camera.translateZ(2)

camera.updateMatrix()
//更新相机的变换矩阵

参考资料
1.奇乐编程
2.http://www.yanhuangxueyuan.com/threejs/docs/index.html#manual/zh/introduction/Creating-a-scene

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

推荐阅读更多精彩内容

  • What is Three.js 什么是threejs,很简单,你将它理解成three + js就可以了。thre...
    依依玖玥阅读 1,497评论 0 2
  • Threejs 为什么? webGL太难用,太复杂! 但是现代浏览器都支持 WebGL 这样我们就不必使用 Fla...
    强某某阅读 5,990评论 1 21
  • Three.js 1.Three.js 介绍 OpenGL(英语:Open Graphics Library,译名...
    GuitarHusky阅读 2,451评论 0 1
  • three之前的准备 three.js是webGL的一个高级工具集,webGL则是从openGL ES 发展而来的...
    琙灵阅读 1,643评论 0 2
  • Threejs中文文档 郭隆邦技术博客 2018-09-21 20:40:17 关注 Three.js中文文档 今...
    情人波阅读 13,904评论 0 7