threejs入门讲解

355 阅读6分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

学习原因

起因是公司出现新的需求,需要在web端展示3d动画效果,其中会展示环境信息和特定的3D模型以及动画,所以就调研了一下热门的3D技术。在经过对比了一下搜集到的开源工具,包括three.js、Babylon.js、PlayCanvas等,选择three.js的原因是因为它具有非常活跃的社区、大量的使用人群和非常好的学习曲线。

基本概念 官网文档

下面这张图很好的讲述了three.js处于的层次,three.js通过封装webgl实现快速搭建3D页面,减少了学习难度。

编写流程

示例

<html>
    <head> 
        <meta charset="utf-8"> <title>My first three.js app</title>
        <style> body { margin: 0; } </style> 
    </head>
    <body> 
        // https://threejs.org/build/three.js 下载下来
        <script src="js/three.js"></script> 
        <script>
        // 场景
        const scene = new THREE.Scene(); 
        // 摄像机
        const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); 
        // render
        const renderer = new THREE.WebGLRenderer(); 
        // 网页全铺
        renderer.setSize( window.innerWidth, window.innerHeight ); 
        // 将生成的dom添加到body
        document.body.appendChild( renderer.domElement );
        // 立方体
        const geometry = new THREE.BoxGeometry(); 
        // 材质
        const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
        // 几何体网格
        const cube = new THREE.Mesh( geometry, material ); 
        // 添加到场景
        scene.add( cube );
        // 摄像机z轴
        camera.position.z = 5;
        // 帧动画
        function animate() { 
            requestAnimationFrame( animate ); 
            cube.rotation.x += 0.01; 
            cube.rotation.y += 0.01;
            renderer.render( scene, camera ); 
        }; 
        // 运行
        animate();
        </script> 
    </body> 
</html>

场景: (必须)

创建一个容器空间,可以将你想要进行渲染的元素添加进去,所有需要在此场景中展示出来的物体都需要添加到场景中

1.background属性:
// background可以设置颜色、单个图片、图片组(天空盒)
// 设置图片需要使用new TextureLoader('地址')
// 颜色需要new THREE.Color(0xffffff)
// 背景透明new THREE.WebGLRenderer({antialias: true,alpha:true })
// 天空盒示例:
let r = "http://stemkoski.github.io/Three.js/images/dawnmountain-";
let urls = [
    r + "xpos.png",
    r + "xneg.png",
    r + "ypos.png",
    r + "yneg.png",
    r + "zpos.png",
    r + "zneg.png",
];
let textureCube = new THREE.CubeTextureLoader().load(urls);
scene.background = textureCube;
// fog 属性 线性雾 
new THREE.fog(color,near,far)
// 例:new THREE.Fog(0xffffff, 0.015,100)
/ 解释/从最近到最远距离间根据设置的雾气颜色会逐渐变重,最近距离之前不存在雾气,最远距离之后会被雾气遮盖
// FogExp2属性指数雾
FogExp2( color , density )
// 类似Fog,只不过雾气增长速度是指数形式,根据第二个参数来修改,默认是0.00025

相机(必须)

透视相机 PerspectiveCamera(最常用) 物体近大远小

PerspectiveCamera( 视野角度,宽长比,近端点, 远端点 )

正交相机 OrthographicCamera 从各角度看大小相同

const camera = new THREE.OrthographicCamera( 左,右,上,下,近,远);
scene.add( camera );

image.png

网格 Mesh

网格需要两个元素组成 几何体 + 材质

几何体

// 平面PlaneGeometry
PlaneGeometry(长,宽)
// 立方体 BoxGeometry 矩形分段数需要在 wireframe线模式 才能看出来
BoxGeometry(长,宽,高,长分段数,宽分段数,高分段数)
// 圆形 CircleGemtry
CircleGeometry(半径, 拆分三角段数, 起始角度, 绘制角数值)
// 圆锥 ConeGeometry
ConeGeometry( 半径, 高度, 拆分三角段数 )
// 圆柱/圆台 CylinderGeometry
CylinderGeometry(顶部半径,底部半径,高度,侧面分段数,高度分段数,起始角度, 绘制角度值)
// 球体 SphereGeometry
SphereGeometry(半径,水平分段数 垂直分段数,-----)
// 边缘几何体EdgesGeometry 绘制出集合体的边缘
// (对比 线模式 可以看到不同点在哪里)
const edges5 = new THREE.EdgesGeometry( geometry5 );
const line = new THREE.LineSegments( edges5, new THREE.LineBasicMaterial( { color: 0xffffff } ) );
形状几何体(ShapeGeometry)根据给出的一些点坐标连城一个线平面
使用canvas绘制线的方法moveTo()、lineTo()、bezierCurveTo()
八面几何体(OctahedronGeometry)、十二面几何体(DodecahedronGeometry)、二十面几何体(IcosahedronGeometry)
圆环几何体(RingGeometry)(二维) 内外为原型的平面、
圆环集合体(TorusGeometry)(三维)、
挤压几何体(ExtrudeGeometry)根据路径生产几何体、车削几何体(LatheGeometry)生产具有轴对称性的网格、等等

材质

基类属性:
name:材质的名字,id:材质的唯一编号
fog:此材质是否受雾影响
visible:材质是否可见,默认值为true
side:平面材质具备,功能是决定渲染哪一面,默认为THREE.FrontSide(正面)。其他选项有THREE.BackSide(反面)和THREE.DoubleSide(两面)。
.shadowSide :定义投影哪一面,值同上
opacity:透明值0-1
map: 贴图 可设置texture
color:颜色0xffffff
specularMap:高光贴图
wireframe :将集合体渲染成线框
envMap :环境贴图,类似天空盒
lightMap:阴影贴图,使用图片渲染为阴影,

MeshBasicMaterial基础网格材质
特点:不受光照影响普通平面

MeshDepthMaterial深度网格材质 depthCube.js
根据物体和摄像头的远近来展示颜色,黑=》白
可以搭配物体融合方法,来模拟物体逐渐远离的场景

MeshDistanceMaterial
内部出现点光阴影效果 暂未搞清具体用途

MeshLambertMaterial
接受光照显示颜色,没有光照会是黑色,根据光照强度改变显示颜色强度

MeshMatcapMaterial 不对灯光作出反应,但是会投射阴影到接受光的物体上

MeshNormalMaterial 法线网格材质 在不同角度看到的颜色不同

MeshPhongMaterial 镜面高光材质 可以模拟具有镜面高光的光泽表面

MeshStandardMaterial 标准网格 对光的反应比MeshPhongMaterial 和MeshLambertMaterial更为精确和逼真,性能要求也会高一些

MeshToonMaterial 一种实现卡通着色的材质。是MeshPhongMaterial材质的一种扩展。受到光照所有面显示

·MeshPhysicalMaterial 物理网格 标准网格的扩展 表现真实模型最为出色

<https://threejs.org/examples/#webgl_materials_physical_clearcoat>

#### 线材质

实线 new THREE.LineBasicMaterial(颜色)

虚线 newTHREE.LineDashedMaterial(颜色)

灯光

环境光AmbientLight

环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。

new THREE.AmbientLight( 0x404040 )

平行光 DirectionalLight

类似太阳发出的光,平行。不产生阴影。

new THREE.DirectionalLight( 0xffffff, 0.5强度 )

点光源PointLight

从一个点向各个方向发射的光源。模拟一个灯泡发出的光。

平面光光源RectAreaLight

从矩形平面均匀发光 模拟窗户

聚光灯(SpotLight)

光线从一个点沿一个方向射出,随着光线照射的变远,光线圆锥体的尺寸也逐渐增大。

半球光(HemisphereLight)

光线照射到除底面以外的其余部分,不能产生阴影

辅助对象

坐标轴辅助

new THREE.AxesHelper(轴线长度);

灯光辅助

PointLightHelper、SpotLightHelper、HemisphereLightHelper

相机视锥体辅助

CameraHelper

加载器

DRACOLoader drc文件加载

DRACO是一个开源库,可以对模型进行压缩,得到的文件比源文件小的多,但是加载时需要额外的解码时间 使用方式 juejin.cn/post/702437…

GLTFLoader glTF格式的文件,three最推荐的模型格式

加载、传输3D格式文件更为高效 blender编辑器导出模型

FontLoader 文字加载器

加载文字 配合 TextGeometry 文字几何体 生成文字

控制器

OrbitControls 常用

轨道控制器 鼠标控制视角 相机围绕目标进行轨道运动

进阶功能

阴影

光源照射在可展示阴影的材质上时,会根据物体形状和照射角度展示出相应的阴影

开启阴影的步骤有

1. renderer.shadowMap.enabled = true;
2.light.castShadow = true;
3.cube.castShadow = true;
plane.reciveShadow = true;

BufferGeometry 基本几何体

所有的几何体都是经过此基础类进行继承封装的;

可以根据自己特定的需求去使用这个类;

废弃对象

所有经过loader加载的物体,具有dispose方法的都需要可以在不使用的时候进行废弃;

矩阵变换 世界坐标 和相对坐标

1A.add(B) B就是A的子元素,B的position是相对于A的position来计算的

移动A的position,B也会跟随A进行移动,可以通过B.getWorldPosition(new THREE.Vectore3())来进行获取B的世界坐标

着色器

需要着色器语言GLSL进行编写,在GPU上运行

ShaderMetrial和RawShaderMaterial 材质编写

解释 shaderMetrial参数文章 blog.csdn.net/weixin_4119…

教学视频 www.bilibili.com/video/BV1kP…

每一集的案例代码codepen.io/collection/…

codepen

动画系统

例如glTF模型,加载完成之后存在animations属性,其中包含经过保存的animationClips,我们可以调用这个属性中的动画片段来播放

animation 方法 start stop pause

属性

loop 值 LoopOnce LoopPingPong LoopRepeat pause 暂停/继续

相关网站

封装three库
使用用例
Ammo.js 物理引擎库
学习threejs代码