Three.js学习笔记
学习Three.js官方例子的一些总结! 🎃
学习链接
three.js
学习帮助论坛
基础
创建场景
需要:场景、相机、渲染器(三步)
设置:把渲染器添加到HTML中-即canvas元素创建立方体
需要:geometry 和 material => mesh
设置:添加进场景,设置camera的位置!!!默认情况添加元素,物体位置(0,0,0),此时考虑移动摄像机
渲染场景
以上步骤还没有真正渲染,需要一个render loop / animate loop
大多数屏幕刷新频率60次/秒1
2
3
4
5function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();让物体旋转
代码添加到animate()函数中renderer.render调用的上方:
当应用程序运行时,想要移动或者改变任何场景中的东西,都必须要经过这个动画循环。
也可以在这个函数里面调用别的函数1
2cube.rotation.x += 0.01;
cube.rotation.y += 0.01;运行
本地开启live-server
画线
- 目的:画一个圆或一条线
- 设置:渲染器、场景、摄像机
- 需要一些点(3个),材质
- 点是出现在对称点中间的。
创建文字
- 目的:使用文本
方法一 - 添加DOM,绝对定位,z-index
方法二 - 文字绘制到画布中,将其用做Texture
方法三 - 用3D软件创建模型
方法四 - three.js自带的文字几何体
THREE.TextGeometry的实例的网格:
载入3D模型
推荐使用glTf格式 - 传输效率高,加载块
根据格式引入加载器
为什么会引入viewport的标签
–用于在移动端浏览器上控制视口的大小和缩放
导入微信公众号
three.js入门001
加载three.js
1
2
3
4
5注意这里的module
模块的优点是可以很方便地导入需要的其他模块。这样我们就不用再手动引入它们所依赖的其他文件了。
<script type="module">
import * as THREE from './resources/threejs/r127/build/three.module.js';
</script>需要一个canvas标签
<canvas id="c"></canvas>
three.js需要使用这个canvas标签来绘制,
要先获取它然后传给three.js1
2
3
4function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
...设置一个透视摄像机
共四个参数1
2const camera = new THREE.PerspectiveCamera
( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
- 视野角度,显示器上看到的场景范围,单位是角度
- 长宽比,用宽度除以高度
- 近截面、远截面,注意近、远、截面,超过,不会渲染
需要移动摄像机参能照到物体camera.position.z = 2;
创建场景
添加一个盒子
把场景和摄像机都给渲染器渲染动起来
需要调用requestAnimationFrame函数官方教程可以调试,好评!!!
添加灯光
1
2
3
4
5
6
7
8{
const color = 0xFFFFFF;
const intensity = 1;
平行光
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
}响应式
使用模块加载。。。
Three.js 场景图
很有收获!!
空对象-类似 自绝父相
渲染有先后顺序 - 轴/网格
统一加入数组,es6可设置旋转
父添加子类。父放大 子也放大 - 像继承 - 需要场景节点。。。
明个在记笔记!
例子
开始敲里面的例子
- 敲完它!!
- 21-6-20
css2d_label
记录一个关于a标签的rel='noopener'
原因是使用target=_blank打开新的窗口时,赋予了新的窗口一些权限可以操作原tab页,
其中window.location就是一个。
不使用 rel=noopener就是让用户暴露在钓鱼攻击上。
关于a标签target_blank使用rel=noopener
学习内容
camera.updateProjectionMatrix();
如果相机对象与投影矩阵相关的属性发生了变化,就需要手动更新相机的投影矩阵
Three.js更新机制1
2
3
4
5
6
7
8
9
10
11
12
13
14init()
window.addEventListener('resize', onWindowResize);
//根据视图调整比例
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
// 矩阵变换(Matrix transformations)
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.setSize(window.innerWidth, window.innerHeight);
}import { OrbitControls } from ‘../jsm/controls/OrbitControls.js’;
控制摄像机 - 实现物体选择,缩放,平移 - 移动的都是摄像机
可以实现方向键漫步效果
可以设置禁止缩放等,控制缩放范围等
可以修改相机的窗口作用范围
使用change监听,控制何是渲染 - 不需要周期性渲染 - 节省性能
Three.js相机控件OrbitControls1
2
3const controls = new OrbitControls(camera, labelRenderer.domElement);
controls.minDistance = 5;
controls.maxDistance = 100;import { CSS2DRenderer, CSS2DObject } from
SS2DRenderer会递归遍历scene 去找到CSS2DObject 来进行渲染得到标签内容信息。CSS2DObject可以添加进入你想要展示其的mesh当中。
给三维物体绑定标签
CSS2DRenderer是CSS3DRenderer(CSS 3D渲染器)的简化版本,唯一支持的变换是位移。
Three.js中的CSS2DObject和CSS2DRenderer
CSS 2D渲染器(CSS2DRenderer)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23const moonDiv = document.createElement('div');
//style 中定义的
moonDiv.className = 'label';
moonDiv.textContent = 'Moon';
moonDiv.style.marginTop = '-1em';
const moonLabel = new CSS2DObject( moonDiv );
moonLabel.position.set(0, MOON_RADIUS, 0);
// moon 是三维物体
moon.add( moonLabel );
//CSS2DObject之后CSS2DRenderer()
labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
// 相对鼠标的相对偏移 ?????
labelRenderer.domElement.style.top = '0px';
document.body.appendChild(labelRenderer.domElement);
const controls = new OrbitControls(camera, labelRenderer.domElement);
controls.minDistance = 5;
controls.maxDistance = 100;const earthMaterial = new THREE.MeshPhongMaterial
该材料使用 非基于物理 的Blinn-Phong模型来计算反射系数。
与在MeshLambertMaterial中使用的Lambertian模型不同,
它可以模拟带有高光的闪亮表面(如漆木)。
学习链接的代码值得参考↓
Three.js - MeshPhongMaterial 用于光亮表面的材质1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28const earthGeometry = new THREE.SphereGeometry(EARTH_RADIUS, 16, 16);
const earthMaterial = new THREE.MeshPhongMaterial({
//材质的高光颜色。默认值是0x111111
specular: 0x333333,
//高亮的程度,越高的值越闪亮。默认值为30
shininess: 5,
//颜色贴图,默认null.纹理贴图颜色由漫反射颜色.color调节
map: textureLoader.load('../textures/planets/earth_atmos_2048.jpg'),
//镜面反射贴图值会影响 镜面高光 以及 环境贴图对表面的影响程度。默认null
specularMap: textureLoader.load('../textures/planets/earth_specular_2048.jpg'),
// 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,
// 并更改颜色照亮的方式。
// 法线贴图不会改变曲面的实际形状,只会改变光照。
normalMap: textureLoader.load('textures/planets/earth_normal_2048.jpg'),
//法线贴图对材质的影响程度。典型范围是0-1 ,默认值是Vector2 设置(1,1)
normalScale: new THREE.Vector2(0.85, 0.85)
});
// const earth = new THREE.Mesh(earthGeometry, earthMaterial);
earth = new THREE.Mesh(earthGeometry, earthMaterial);
//添加进场景
scene.add(earth);
interactive_voxelpainter
描述: 鼠标移入,有一个预加载的盒子跟着移动
点击创建一个实体盒子,按住shift可以删除盒子,
内容:创建、删除、随鼠标移动、预加载、按键配合
学习内容
- 创建时候把要用到的一起创建
1
2
3
4
5let camera, scene, renderer;
let plane;
let pointer, raycaster, isShiftDown = false;
let rollOverMesh, rollOverMaterial;
let cubeGeo, cubeMaterial;
const gridHelper = new THREE.GridHelper(1000, 20);
Three.js 坐标网格 GridHelperraycaster = new THREE.Raycaster();
ThreeJS中的点击与交互——Raycaster的用法
场景坐标、屏幕坐标、视点坐标
主要方法 - setFromCamera、intersectObject
Three.js - 通过 THREE.Raycaster 实现模型选中与信息显示
HTML DOM addEventListener() 方法添加灯光
ambientLight - 环境光
directionalLight - 平行光keyCode
Keycode对照表1
2
3
4
5
6
7function onDocumentKeyDown(event) {
switch (event.keyCode) {
case 16:
isShiftDown = true;
break;
}
}render()
在合适的时候,节约资源
- 初始化的时候
- 鼠标移动的时候
- 鼠标点击的时候
1
2
3function render() {
renderer.render(scene, camera);
}
- 未解之处。。。
threejs 之 复制删除正方体1
2
3rollOverMesh.position.copy(intersect.point).add(intersect.face.normal);
rollOverMesh.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25);
loader_gltf
描述:加载gltf
学习内容
- OrbitControls - 控制摄像机
- GLTFLoader - 加载gltf - setPath - load
- RGBELoader - 加载hdr
- RoughnessMipmapper - 未解。。。
- 运行在手机上 - 修改live-server的地址
- renderer - 重点!!!
这个链接包含renderer里面的参数,
three.js学习(5):Renderer
Github博客学习01
系统跟着学习一下!!!
Three.js达人课相关案例
01
scene - 添加
camera - 画面
render - 渲染
几何体 - 材质 - 网格
这一句值得学习!!!<body onload="init()">
02
性能检测框 - 可以显示fps
1 | <script src="../js/stats.min.js"></script> |
03
学习使用dat.GUI
1 | <script src="../js/dat.gui.min.js"></script> |
04
创建各种几何图形,旋转暂停gui
若有所思。。
图解WebGL&Three.js工作原理
three.js初探,立体几何入手(一)
在animate()里面判断条件,是否旋转
旋转的标记来自gui
1 | // 创建调试框 |
05
学习了创建线和曲线
- 先有基础的点,给一个几何物体,几何物体移动
geometry在运行的时候也会解析成bufferGeometry
BufferGeometry和Geometry有什么不同
1 | // 添加直线 |
06
学习灯光操作,配合gui,cool,光照辅助-方便查看光线,阴影
script可以放到body下面。。。。
- 灯光
- 渲染投影
- 投掷投影
- 接收投影
- 投影密度
Three.js - 使用阴影效果 shadowMap 和 设置阴影分辨率
Three.js - HemisphereLight 光源
Three.js - SpotLight 光源
GUI使用方法总结:
0. 创建 数据对象
- 创建 dat.GUI() 实例
- 添加参数 addColor/ add - 对象 名字 方法
var camera = datGui.addFolder('阴影设置');
折叠参数。
1 | // 修改球体位置的方法,平行光的target就是球 |
07
通过鼠标控制camera的运动,,点击物体,可以移动摄像机
一堆公式,暂略。。。。
08
学习创建精灵
Sprite是一个永远面向相机的平面 - 可做提示用
Sprite和points
HTML DOM getContext() 方法
HTML canvas createRadialGradient() 方法
09
orbitControls
TrackballControls
10
加载模型 + OrbitControls
加载器:
ColladaLoader
FBXLoader
GLTFLoader
JSONLoader
ObjectLoader
OBJLoader
1 | <script src="../js/loaders/ColladaLoader.js"></script> |
JSONLoader -
- 加载模型
- 导出模型 - 文件操作
- 导入模型
gui里面可以放方法。
JavaScript encodeURIComponent() 函数
1 | //创建模型 |
11
加载动画
- 变形动画 - 通过变形目标morphTargets,让所有顶点从一个位置变化到另一个位置,并重复该过程。
- 骨骼动画 - 骨骼即是网格的骨头,把所有顶点绑定到特定的骨头上
morphTargets 是制作动画的最直接的方法,
但是这种方法有一个不足,就是对于大型的模型和大型动画,
模型的文件会变得很大,因为每个变形都需要储存一下所有的顶点,示例是一匹马在奔跑。
Three.js - 用 morphTargets 制作变形动画
1 | loader.load("../js/models/json/horse.js", function (geometry) { |
定义两个变形目标,把定点放入立方体的morphTargets里面,
是几何体, 不是Mesh
这两个目标添加进gui
1 | gui = { |
骨骼动画
1 | function createMesh(geometry, bones) { |
1 | var loader = new THREE.GLTFLoader(); |
12
tween
1 | <script src="../js/Tween.js"></script> |
tween 循环
1 | //直接链式实现tween |
13
框选界面元素
getClientRects() 和 getBoundingClientRect() 的用法和区别
//声明一个显示的拖拽框的div
// 赋值css语句 也可以应用stlye里面的。
定义一个框,用来选中,确定左上距离和宽高,定义一个数组,保存原始元素数据(材料,位置)
循环全部元素,通过位置来判断是否要改变材质,
框选结束后,整体恢复材质
点击交互
//通过鼠标点击的位置计算出射线所需要的点的位置,以屏幕中心为原点,值的范围为-1到1.
//根据在屏幕的二维位置以及相机的矩阵更新射线的位置
// 获取射线直线和所有模型相交的数组集合
Github博客学习02
01
博客学习03
官方案例链接
各种材质
webgl_loader_texture_dds
各种材质+融球效果
webgl_marchingcubes
透明材质
webgl_materials_cubemap_refraction
球面反射
webgl_materials_envmaps
可以隐形。。遮挡?
webgl_materials_envmaps_parallax
名画滤镜
webgl_materials_texture_manualmipmap
材质球
webgl_multiple_elements
全景空间
webgl_panorama_equirectangular
渐变移动的点
webgl_points_billboards
移动的人形的点
webgl_points_dynamic
雪花精灵
webgl_points_sprites
岩浆。。
webgl_shader_lava
很真实的材质。。。
webgl_shading_physical
全景video,可以移动
webgl_video_panorama_equirectangular
迷雾效果。。
webgl_postprocessing_godrays
遮罩
webgl_postprocessing_masking
辉光
webgl_postprocessing_unreal_bloom
点
webgl_buffergeometry_drawrange
千纸鹤
webgl_gpgpu_birds
闪电
webgl_lightningstrike
动画组
misc_animation_groups
框选盒子
misc_boxselection
用手机测试,不开摄像头,能旋转画面
misc_controls_deviceorientation
可以wasd,鼠标,qr等移动画面
misc_controls_fly
上下左右空格跳跃,鼠标控制画面
misc_controls_pointerlock
给物体添加标签
css2d_label
卡片动画
css3d_periodictable
codepen链接
都是使用了three.js