写点什么

Three.js - 走进 3D 的奇妙世界(下)

  • 2020-02-06
  • 本文字数:3102 字

    阅读完需:约 10 分钟

Three.js - 走进3D的奇妙世界(下)

接上篇

五、材质

创建几何体时通过指定几何体的顶点和三角形的面确定了几何体的形状,另外还需要给几何体添加皮肤才能实现物体的效果,材质就像物体的皮肤,决定了物体的质感。常见的材质有如下几种:


1574761705093026955.png


  • 基础材质:以简单着色方式来绘制几何体的材质,不受光照影响。

  • 深度材质:按深度绘制几何体的材质。深度基于相机远近端面,离近端面越近就越白,离远端面越近就越黑。

  • 法向量材质:把法向量映射到 RGB 颜色的材质。

  • Lambert 材质:是一种需要光源的材质,非光泽表面的材质,没有镜面高光,适用于石膏等表面粗糙的物体。

  • Phong 材质:也是一种需要光源的材质,具有镜面高光的光泽表面的材质,适用于金属、漆面等反光的物体。

  • 材质捕获:使用存储了光照和反射等信息的贴图,然后利用法线方向进行采样。优点是可以用很低的消耗来实现很多特殊风格的效果;缺点是仅对于固定相机视角的情况较好。


下图是使用不同贴图实现的效果:


1574761711928053548.png

六、光源

前面提到的光敏材质(Lambert 材质和 Phong 材质)需要使用光源来渲染出 3D 效果,在使用时需要将创建的光源添加到场景中,否则无法产生光照效果。下面介绍一下常用的光源及特点。

6.1 点光源

点光源类似蜡烛放出的光,不同的是蜡烛有底座,点光源没有底座,可以把点光源想象成悬浮在空中的火苗,点光源放出的光线来自同一点,且方向辐射向四面八方,点光源在传播过程中有衰弱,如下图所示,点光源在接近地面的位置,物体底部离点光源近,物体顶部离光源远,照到物体顶部的光就弱些,所以顶部会比底部暗些。


1574761719361025496.png

6.2 平行光

平行光模拟的是太阳光,光源发出的所有光线都是相互平行的,平行光没有衰减,被平行光照亮的整个区域接受到的光强是一样的。


1574761726762024810.png

6.3 聚光灯

类似舞台上的聚光灯效果,光源的光线从一个锥体中射出,在被照射的物体上产生聚光的效果。聚光灯在传播过程也是有衰弱的。


1574761740218053917.png

6.4 环境光

环境光是经过多次反射而来的光,环境光源放出的光线被认为来自任何方向,物体无论法向量如何,都将表现为同样的明暗程度。


1574761746944010096.png


环境光通常不会单独使用,通过使用多种光源能够实现更真实的光效,下图是将环境光与点光源混合后实现的效果,物体的背光面不像点光源那样是黑色的,而是呈现出深褐色,更自然。


1574761753866085908.png

七、纹理

在生活中纯色的物体还是比较少的,更多的是有凹凸不平的纹路或图案的物体,要用 Three.JS 实现这些物体的效果,就需要使用到纹理贴图。3D 世界的纹理是由图片组成的,将纹理添加在材质上以一定的规则映射到几何体上,几何体就有了带纹理的皮肤。

7.1 普通纹理贴图

1574761761607084261.png


在这个示例中使用上图左侧的地球纹理,在球形几何体上进行贴图就能制作出一个地球。


代码如下:


/* 创建地球 */function createGeom() {    // 球体    var geom = new THREE.SphereGeometry(1, 64, 64);    // 纹理    var loader = new THREE.TextureLoader();    var texture = loader.load('./earth.jpg');    // 材质    var material = new THREE.MeshLambertMaterial({        map: texture    });    var earth = new THREE.Mesh(geom, material);    return earth;}
复制代码

7.2 反面贴图实现全景视图

1574761770285098104.png


这个例子是通过在球形几何体的反面进行纹理贴图实现的全景视图,实现原理是这样的:创建一个球体构成一个球形的空间,把相机放在球体的中心,相机就像在一个球形的房间中,在球体的里面(也就是反面)贴上图片,通过改变相机拍摄的方向,就能看到全景视图了。


材质默认是在几何体的正面进行贴图的,如果想要在反面贴图,需要在创建材质的时候设置 side 参数的值为 THREE.BackSide,代码如下:


/* 创建反面贴图的球形 */// 球体var geom = new THREE.SphereGeometry(500, 64, 64);// 纹理var loader = new THREE.TextureLoader();var texture = loader.load('./panorama.jpg');// 材质var material = new THREE.MeshBasicMaterial({    map: texture,    side: THREE.BackSide});var panorama = new THREE.Mesh(geom, material);
复制代码

7.3 凹凸纹理贴图

1574761778594091032.png


凹凸纹理利用黑色和白色值映射到与光照相关的感知深度,不会影响对象的几何形状,只影响光照,用于光敏材质(Lambert 材质和 Phong 材质)。


如果只用上图左上角的砖墙图片进行贴图的话,就像一张墙纸贴在上面,视觉效果很差,为了增强立体感,可以使用上图左下角的凹凸纹理,给物体增加凹凸不平的效果。


凹凸纹理贴图使用方式的代码如下:


// 纹理加载器var loader = new THREE.TextureLoader();// 纹理var texture = loader.load( './stone.jpg');// 凹凸纹理var bumpTexture = loader.load( './stone-bump.jpg');// 材质var material =  new THREE.MeshPhongMaterial( {    map: texture,    bumpMap: bumpTexture} );
复制代码

7.4 法线纹理贴图

1574761786800063329.png


法线纹理也是通过影响光照实现凹凸不平视觉效果的,并不会影响物体的几何形状,用于光敏材质(Lambert 材质和 Phong 材质)。上图左下角的法线纹理图片的 RGB 值会影响每个像素片段的曲面法线,从而改变物体的光照效果。


使用方式的代码如下:


// 纹理var texture = loader.load( './metal.jpg');// 法线纹理var normalTexture = loader.load( './metal-normal.jpg');var material =  new THREE.MeshPhongMaterial( {    map: texture,    normalMap: normalTexture} );
复制代码

7.5 环境贴图

1574761795393098937.png


环境贴图是将当前环境作为纹理进行贴图,能够模拟镜面的反光效果。在进行环境贴图时需要使用立方相机在当前场景中进行拍摄,从而获得当前环境的纹理。立方相机在拍摄环境纹理时,为避免反光效果的小球出现在环境纹理的画面上,需要将小球设为不可见。


环境贴图的主要代码如下:


/* 立方相机 */var cubeCamera = new THREE.CubeCamera( 1, 10000, 128 );/* 材质 */var material = new THREE.MeshBasicMaterial( {    envMap: cubeCamera.renderTarget.texture});/* 镜面反光的球体 */var geom = new THREE.SphereBufferGeometry( 10, 32, 16 );var ball = new THREE.Mesh( geom, material );// 将立方相机添加到球体ball.add( cubeCamera );scene.add( ball );
// 立方相机生成环境纹理前将反光小球隐藏ball.visible = false;// 更新立方相机,生成环境纹理cubeCamera.update( renderer, scene );balls.visible = true;
// 渲染renderer.render(scene, camera);
复制代码

八、加载外部 3D 模型

Three.JS 已经内置了很多常用的几何体,如:球体、立方体、圆柱体等等,但是在实际使用中往往需要用到一些特殊形状的几何体,这时可以使用 3D 建模软件制作出 3D 模型,导出 obj、json、gltf 等格式的文件,然后再加载到 Three.JS 渲染出效果。


1574761804228052501.png


上图的椅子是在 3D 制图软件绘制出来的,chair.mtl 是导出的材质文件,chair.obj 是导出的几何体文件,使用材质加载器加载材质文件,加载完成后得到材质对象,给几何体加载器设置材质,加载后得到几何体对象,然后再创建场景、光源、摄像机、渲染器等进行渲染,这样就等得到如图的效果。主要的代码如下:


// .mtl材质文件加载器var mtlLoader = new THREE.MTLLoader();// .obj几何体文件加载器var objLoader = new THREE.OBJLoader();
mtlLoader.load('./chair.mtl', function (materials) { objLoader.setMaterials(materials) .load('./chair.obj', function (obj) { scene.add(obj); });});
复制代码

九、说明

以上内容对 Three.JS 的基本使用进行了介绍,文中涉及到的示例源码已上传到 github,感兴趣的同学可以下载查看,下载地址:https://github.com/liulinsp/three-demo。使用时如果有不清楚的地方可以查看Three.JS的官方文档:https://threejs.org/docs/index.html。


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/328


2020-02-06 10:341758

评论

发布
暂无评论
发现更多内容

为什么不上台?(5/28)

赵新龙

28天写作

JavaScript基础语法之对象的哪些事

你好bk

JavaScript 大前端 js 基础语法 12月日更

终于有了一个人人可以访问的网站了

老表

WordPress 个人网站 跟老表学云服务器

Android 框架解析:深入理解 Retrofit 实现

拭心

android Framework 内容合集 签约计划第二季 shixinzhang

Android 框架解析:EventBus 3.0 的特点与如何使用

拭心

android Framework 内容合集 签约计划第二季

Android 框架解析:Picasso 核心功能实现原理

拭心

android Framework 内容合集 签约计划第二季 shixinzhang

Android 框架解析:热修复框架 Tinker 从使用到 patch 加载、生成、合成原理分析

拭心

android Framework 内容合集 签约计划第二季 shixinzhang

随手记录一下消息队列的一些模型

Android 框架解析:OkHttp 请求原理基本认识

拭心

android Framework 内容合集 签约计划第二季 shixinzhang

【Promise 源码学习】第十二篇 - Promise.race 的实现

Brave

源码 Promise 12月日更

音视频实战(4)- 常见流媒体服务器方案对比分析

liuzhen007

签约计划第二季

Git进阶(八):git stash 与 git add

No Silver Bullet

git 12月日更

极客时间架构实战营 - 模块九及大作业

jjn0703

架构实战营

『腾讯网』腾讯分分彩计划最准软件[手机乐乎]

天马行空

腾讯分分彩计划最准软件

如何有效处理素材

将军-技术演讲力教练

Android 框架解析:Picasso 源码基本架构

拭心

android Framework 内容合集 签约计划第二季 shixinzhang

『腾讯网』1分彩计划软件下载[手机乐乎]

天马行空

1分彩计划软件下载

音视频学习从理论到实战

liuzhen007

内容合集 签约计划第二季 技术专题合集

架构实战营毕业总结

白开水又一杯

#架构实战营

Rust 元宇宙 13 —— 客户端连接

Miracle

rust 元宇宙

『腾讯网』极速飞艇游戏[手机乐乎]

天马行空

极速飞艇游戏

『腾讯网』网贷强制上岸后果[手机乐乎]

天马行空

网贷强制上岸后果

极客时间架构实战营总结

jjn0703

架构实战营

『腾讯网』飞艇技巧图片图解【重点推荐】[手机乐乎]

天马行空

飞艇技巧图片图解

音视频实战(5)- FFmpeg 处理音视频常见问题集锦

liuzhen007

签约计划第二季

音视频理论(3)- 视频中图片和文字渲染坐标问题

liuzhen007

签约计划第二季

Android 框架解析:EventBus 3.0 如何实现事件总线

拭心

android Framework 内容合集 签约计划第二季 shixinzhang

Android 框架解析:从 EventBus 中学到的精华

拭心

android Framework 内容合集 签约计划第二季 shixinzhang

『腾讯网』赛车飞艇平台[手机乐乎]

天马行空

赛车飞艇平台

Android 进阶之路:深入理解常用框架实现原理

拭心

android Framework 内容合集 技术专题合集 shixinzhang

存储引擎漫话

ElvinYang

B-tree LSM-Tree Hash Index MySQL InnoDB

Three.js - 走进3D的奇妙世界(下)_行业深度_刘琳_InfoQ精选文章