Three.js Tutorial for Absolute Beginners
源项目仓库:
npm安装
- parcel.js 程序打包工具
- three.js 图表库
- threejs尽量安装稳定版本,最新版本可能存在各种问题
1 | npm install three@0.133.0 |
parcel将多个源文件打包成一个dist,
支持开发时热更新。
文件结构如下时:
- root
- src
- js
- main.js
- index.html 主页面入口
- js
- package.json
- src
在项目根目录路径root\下使用parcel命令:
1 | parcel index.html |
parcel会在项目根目录root\下创建一个dist文件夹,
即真正运行的文件
渲染器Renderer/场景Scene/摄像机Camera
1 | const scene = new THREE.Scene() |
1 | const camera = new THREE.PerspectiveCamera( |
1 | const renderer = new THREE.WebGLRenderer() |
坐标系辅助线AxesHelper/物体Object/动画Animate/轨道控制器OrbitControls
1 | const axesHelper = new THREE.AxesHelper(15) |
1 | const boxGeometry = new THREE.BoxGeometry(3,3,3) |
记得每次调用animate时都要调用render进行重绘
1 | renderer.setAnimationLoop(animate) |
每次对相机进行修改后,都需要调用orbit.update()进行更新
1 | import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls' |
Geometry几何构造/Material材质/GridHelper网格辅助器
1 | // plane geometry |
GridHelper:
- param1: size
- param2: divisions
1
2const gridHelper = new THREE.GridHelper(30, 30)
scene.add(gridHelper)
dat.gui交互界面
npm安装dat.gui
1 | npm install dat.gui |
1 | import { GUI } from 'dat.gui' |
1 | function animate(time) { |
AmbientLight环境光/DirectionalLight直射光/SpotLight聚光灯/Shadow阴影
将之前创建的物体材质改成受光照影响的MeshStandardMaterial
1 | const ambientLight = new THREE.AmbientLight(0xffffff) |
1 | const directionalLight = new THREE.DirectionalLight(0xffffff) |
DirectionalLight的阴影底部范围默认为5,
需要通过改变light.shadow.camera.bottom来控制底部范围
1 | directionalLight.shadow.camera.bottom = -10 |
要投射阴影,首先要将renderer的shadowMap属性打开
1 | renderer.shadowMap.enabled = true |
然后需要将光源的castShadow属性打开,
需要投射阴影物体的castShadow设为true,
被投射阴影的面的receiveShadow设为true
1 | directionalLight.castShadow = true |
1 | const spotLight = new THREE.SpotLight(0xffffff) |
Fog雾/SceneBackground场景背景/Texture纹理
方式1:指定雾的范围
1 | scene.fog = new THREE.Fog(0xffffff,20, 200) |
方式2:指定雾的密度
1 | scene.fog = new THREE.FogExp2(0xffffff,0.01) |
单个textureLoader:
1 | import nebula from '../img/nebula.jpg' |
cubeTextureLoader:
1 | import starts from '../img/stars.jpg' |
物体添加纹理:
1 | import nebula from '../img/nebula.jpg' |
同一个物体添加多个材质:
1 | import starts from '../img/stars.jpg' |
Select选中
选中一个物体,首先需要在绘制区域创建一个二维坐标系:
1 | let mousePosition = new THREE.Vector2() |
这里实现选中物体的原理是从摄像机Camera和鼠标Mouse之间发射出一条射线,
所有被射线穿透的物体即视为选中状态,
因此,我们需要创建一条射线:
1 | let rayCaster = new THREE.Raycaster() |
然后在loop函数中持续对选中物体进行检测
1 | function animate(time) { |
VertexPosition顶点坐标/ShaderMaterial渲染器材质/ModelImport模型导入
通过直接修改obj.geometry.attributes.position数组中数值进行顶点修改,
注意:修改后需要将needsUpdate设置为true
1 | let posArray = plane.geometry.attributes.position.array; |
方式1:shader程序用字符串变量/常量定义:
1 | const vShader = ` |
方式2:shader程序使用script标签写在html文件中:
1 | <script id="vShader" type="x-vertex"> |
1 | const sphereMaterial = new THREE.ShaderMaterial({ |
这里以导入gltf格式模型为例,
对于不同模型,threejs提供了不同loader:
1 | import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader' |
由于项目内使用了parcel作为打包工具,
因此模型文件的路径需要动态获取:
1 | const monkeyUrl = new URL('../assets/monkey.glb', import.meta.url) |
通过loader读取模型数据并绘制:
1 | gltfLoader.load(monkeyUrl.href, function (gltf) { |
CanvasResponsive响应式画布
在屏幕尺寸发生变化时,需要对相机camera的比例进行更新,
renderer需要重绘:
1 | window.onresize = function () { |