写点什么

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:341781

评论

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

外包学生管理系统架构设计文档

「架构实战营」

外包学生管理系统架构

浪飞

如何更好的使用TypeScript

Tone荣

前端 js ts js 转 ts

互联网应用开发如何搭上AI的快车?来厦门开发者Meetup一探究竟

百度大脑

微服务从代码到k8s部署应有尽有系列(三、鉴权)

万俊峰Kevin

微服务 web开发 鉴权 go-zero Go 语言

java培训:Netty的内存管理

@零度

Java Netty

网易数帆大数据场景下的DataOps实践

网易数帆

大数据 数据治理 DataOps

MongoDB在信息资源共享建设的应用实践

MongoDB中文社区

mongodb

「架构实战营」模块三作业 外包学生管理系统架构设计

hxb

「架构实战营」

web前端开发Nodejs的C++ 拓展开发_前端培训

@零度

node.js 前端开发

原生JavaScript灵魂拷问,你能答上多少(一)

战场小包

JavaScript 前端 2月月更

Flink 新一代流计算和容错——阶段总结和展望

Apache Flink

大数据 flink 开源 编程 实时计算

MongoDB 数据实时同步利器-Tapdata Cloud 免费上手指南

MongoDB中文社区

mongodb

基于Qt设计的学生考勤系统

DS小龙哥

2月月更

中国 PostgreSQL 分会加入龙蜥社区,携手共建基础软件开源新生态

OpenAnolis小助手

postgresql Linux 开源

ESLint-源码分析

Tone荣

前端 eslint

重学架构之外包学生管理系统架构设计文档

陈华英

架构实战营

Go学习笔记——复合数据类型

为自己带盐

Go 学习笔记 2月月更

等保2.0政策之物联网安全扩展要求包括哪四个?

行云管家

云计算 物联网 等保 等保2.0 扩展要求

堡垒机哪家好?贵不贵?作用是什么?

行云管家

堡垒机 等级保护 过等保 等保2.0

掉入成功的深渊

Shinta

我提交了一个 pr,竟然是为了吃

AlwaysBeta

GitHub 开源 程序员 生活 程序员人生

学生管理系统 - 详细设计方案

tom

模块三作业

Leo

云计算架构设计6大原则,你遵循了吗?

博文视点Broadview

震坤行工业超市研发效能提升之路

阿里云云效

云计算 阿里云 DevOps 云原生 研发

全面解析湖仓一体与大数据演进历程|内含技术工具选型策略

云智慧AIOps社区

数据库 大数据 数据湖 Clickhouse 大数据运维

向工程腐化开炮 | manifest治理

阿里巴巴终端技术

App 客户端开发 腐化治理 manifest

G1 面向服务端(多CPU)应用的垃圾回收器

蜜糖的代码注释

Java 垃圾回收器 2月月更

手把手教学电瓶车进电梯检测、多类别车辆追踪、异常行为检测产业级应用

百度大脑

低代码实现探索(三十三)前端脚本公式

零道云-混合式低代码平台

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