备注:“本文中部分核心知识点整理自老师的授课网站”
网站地址:http://www.webgl3d.cn/pages/aac9ab/
一·three.js初始化操作
1 · 下载连接

2、文档链接(中文)
3 、 vscode插件

4 、使用
预览代码3D效果,打开对应的html文件,右键点击Open with Live Server即可。
二、学习环境和开发环境引入js库
1、开发环境
注意:项目开发引入three.js,比如vue或者react脚手架引入three.js
1.1、安装命令
npm install three@0.164.0 -save
1.2、引入three.js
import * as THREE from 'three';
1.3、引入three.js的扩展库
//引入扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
1.4、扩展库的位置
注意:很多的扩展库具体几乎都在 examples/jsm里面

2、学习环境
注意:入门three.js阶段,.html文件中直接引入three.js
2.1、ES6 import引入方式
注意:给script标签设置type="module",就可以通过import的方式进行引入three.js
import * as THREE from 'three';
2.2、type="importmap"配置路径
<script type="importmap">
{
"imports": {
"three": "../three.js-r164/build/three.module.js"
}
}
</script>
2.3、全部代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "../three.js-r164/build/three.module.js"
}
}
</script>
<script type="module" src="./build/index.js">
import * as THREE from 'three';
console.log(THREE.Scene);
</script>
</body>
</html>
2.4、扩展库的配置

代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "../three.js-r164/build/three.module.js",
"three/addons/": "../three.js-r164/examples/jsm/"
}
}
</script>
<script type="module" src="./build/index.js">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
console.log(THREE.Scene);
</script>
</body>
</html>
三、第一个3D案例--创建3D场景
注意:入门three.js的第一步,就是认识场景Scene、相机Camera、渲染器Renderer三个概
1、场景Scene
1.1、三维场景Scene
//创建3D场景对象Scene
const scene = new THREE.Scene();
1.2、物体形状Geometry
注意:threejs提供了各种几何形状的api,用来表示三维物体的几何形状
//创建一个几何体,长方体 长宽高100
const geometry = new THREE.BoxGeometry(100, 100, 100);
1.3、物体外观:材质Material
注意:如果想定义物体的外观效果,比如颜色,就需要通过材质Material相关的API去实现
//创建一个基础网格材质,颜色为红色
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
1.4、物体:网格模型Mesh
实际生活中有各种各样的物体,在threejs中通过网格模型Mesh表示一个虚拟的物体,比如一个箱子,一个鼠标等。
//创建网格模型
const cube = new THREE.Mesh( geometry, material );
1.5、模型的位置 .position
现实生活中,一个物体往往都是有位置的,对于threejs而言也是有的,可以通过位置属性.position定义网格模型Mesh在三维场景Scene中的位置。
//创建网格模型
const cube = new THREE.Mesh(geometry, material);
//设置网格模型在三维空间中的位置坐标,默认是坐标原点
cube.position.set(0, 10, 0)
1.6、.add() 方法
在threejs中创建一个表示物体的虚拟对象Mesh,需要通过.add()方法,把网格模型mesh添加到三维场景scene中
scene.add( cube );
2、相机Camera
threejs如果想把三维的场景Scene渲染到web网页上,还需要定义一个虚拟相机Camera,就像生活中想获得一张照片,需要一台相机拍照一样。
创建一个新的Camera(摄像机)。注意:这个类并不是被直接调用的;你所想要的或许是一个 PerspectiveCamera(透视摄像机)或者 OrthographicCamera(正交摄像机)。
2.1、透视投影相机PerspectiveCamera
这一投影模式被用来模拟人眼所看到的景象,它是3D场景的渲染中使用得最普遍的投影模式。
let width = 500
let height = 500
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
scene.add(camera);
2.2、相机位置 .position
生活中用相机拍照,相机的位置不同,拍照结果也不同,threejs中虚拟相机同样如此。
相机对象Camera具有位置属性 .position,通过位置属性 .position可以设置相机的位置。
camera.position.set(200, 200, 200)
2.3、相机观察目标 .lookAt()
用相机拍照需要控制相机的拍照目标,两点构成一条直线。具体就像相机看向什么方向。
对于threejs而言,就是设置.lookAt() 方法的参数,指定一个3D坐标。
//看向坐标原点
camera.lookAt(0,0,0)
3、渲染器Renderer
threejs中的渲染器就相当于相机按下快门那一下,会得到一张人眼能够看见的图片。
3.1、WebGL渲染器 WebGLRenderer
通过WebGL渲染器WebGLRenderer可以实例化一个WebGL渲染器对象
//创建一个WebGL渲染器
const renderer = new THREE.WebGLRenderer();
3.2、设置canvas画布的尺寸 .setSize()
//定义threejs输出画布的尺寸
renderer.setSize(width, height)
3.3、渲染器渲染方法 .render()
渲染器WebGLRenderer执行渲染方法.render()就可以生成一个canvas画布(照片)
renderer.render(scene, camera)
3.4、渲染器Canvas画布属性 .domElement
渲染器WebGLRenderer通过属性.domElement可以获得渲染方法.render()生成的canvas画布,.domElement本质上就是一个HTML元素:Canvas画布
document.body.appendChild(renderer.domElement)
4、例子显示结果
全部代码:
import * as THREE from 'three';
//场景
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry( 100, 100, 100 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( geometry, material );
cube.position.set(0, 10, 0)
scene.add( cube );
//相机
let width = 500
let height = 500
const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
camera.position.set(200, 200, 200)
camera.lookAt(0,0,0)
scene.add( camera );
//渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height)
renderer.render(scene, camera)
document.body.appendChild(renderer.domElement)
运行结果:

四、Threejs三维坐标系加强三维空间的认识
加强threejs三维空间的认识
1、辅助观察坐标系
THREE.AxesHelper()的参数表示坐标系坐标轴线段尺寸大小,
//添加辅佐坐标系
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);
2、材质半透明
设置材质半透明这样可以看见坐标系的原点
const material = new THREE.MeshBasicMaterial({
color: 0x00ff00,
transparent: true,
opacity: 0.5
});
3、AxesHelper的xyz轴
threejs坐标轴颜色红R,绿G,蓝B分别对应坐标系的x,y,z轴。对于threejs的3D坐标系默认y轴朝上。
五、光源对物体表面的影响
实际生活中物体表面的明暗效果是会受到光照的影响,比如晚上不开灯,你就看不到物体,灯光比较暗,物体也比较暗。在threejs中,咱们用网格模型Mesh模拟生活中物体,所以threejs中模拟光照Light对物体表面的影响,就是模拟光照Light对网格模型Mesh表面的影响。
1、受光照影响材质
threejs提供的网格材质,有的受光照影响,有的不受光照影响。

1.1、基础网格材质MeshBasicMaterial
不会受到光照影响。
const material = new THREE.MeshBasicMaterial({
color: 0x0000ff, //设置材质颜色
});
1.2、 漫反射网格材质MeshLambertMaterial
会受到光照影响,该材质也可以称为Lambert网格材质一个立方体长方体使用MeshLambertMaterial材质,不同面和光线夹角不同,立方体不同面就会呈现出来不同的明暗效果。
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff, //设置材质颜色
});

2、光源简介
Three.js提供了多种模拟生活中光源的API,文档搜索关键词light就可以看到。

3、点光源

点光源PointLight (opens new window)可以类比为一个发光点,就像生活中一个灯泡以灯泡为中心向四周发射光线。
//光源
//参数1:光线颜色
//参数2:光照强度
const pointLight = new THREE.PointLight('#fff',1.0);
注意:也可以通过.intensity设置光照强度
pointLight.intensity = 2.0
4、光源衰减
实际生活中点光源,比如比如一个灯泡,随机距离的改变,光线会衰减,越来越弱,光源衰减属性.decay默认值是2.0,如果你不希望衰减可以设置为0.0
pointLight.decay = 0.0;
5、光源位置
你把点光源想象为一个电灯泡,你在3D空间中,放的位置不同,模型的渲染效果就不一样。
注意光源位置尺寸大小:如果你希望光源照在模型的外表面,那你就需要把光源放在模型的外面。
pointLight.position.set(400, 0, 0)
6、光源添加到场景
光源和网格模型Mesh对应一样是三维场景的一部分,自然需要添加到三维场景中才能起作用。
scene.add(pointLight)
7、光源代码和效果
//光源
//参数1:光线颜色
//参数2:光照强度
const pointLight = new THREE.PointLight('#fff', 1.0);
pointLight.intensity = 2.0
pointLight.decay = 0.0;
pointLight.position.set(400, 0, 0)
scene.add(pointLight)

8、全部代码和效果
import * as THREE from 'three';
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(100, 100, 100);;
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff, //设置材质颜色
});
const cube = new THREE.Mesh(geometry, material);
cube.position.set(0, 10, 0)
scene.add(cube);
let width = 500
let height = 500
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
camera.position.set(200, 200, 200)
camera.lookAt(0, 0, 0)
scene.add(camera);
// AxesHelper:辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);
//光源
//参数1:光线颜色
//参数2:光照强度
const pointLight = new THREE.PointLight('#fff', 1.0);
pointLight.intensity = 2.0
pointLight.decay = 0.0;
pointLight.position.set(400, 200, 100)
scene.add(pointLight)
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height)
renderer.render(scene, camera)
document.body.appendChild(renderer.domElement)

六、相机控件OrbitControls
1、引入扩展库OrbitControls.js
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
2、使用OrbitControls
//相机控件
const controls = new OrbitControls(camera, renderer.domElement)
controls.addEventListener('change',function(){
renderer.render(scene, camera)
})
3、全部代码
import * as THREE from 'three';
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(100, 100, 100);;
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff, //设置材质颜色
});
const cube = new THREE.Mesh(geometry, material);
cube.position.set(0, 10, 0)
scene.add(cube);
let width = 500
let height = 500
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
camera.position.set(200, 200, 200)
camera.lookAt(0, 0, 0)
scene.add(camera);
// AxesHelper:辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);
//光源
//参数1:光线颜色
//参数2:光照强度
const pointLight = new THREE.PointLight('#fff', 1.0);
pointLight.intensity = 2.0
pointLight.decay = 0.0;
pointLight.position.set(400, 200, 100)
scene.add(pointLight)
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height)
renderer.render(scene, camera)
document.body.appendChild(renderer.domElement)
//相机控件
const controls = new OrbitControls(camera, renderer.domElement)
controls.addEventListener('change',function(){
renderer.render(scene, camera)
})
七、平行光与环境光
1、点光源辅助观察PointLightHelper
预览观察:可以借助相机控件OrbitControls旋转缩放三维场景便于预览点光源位置
//光源辅助观察
const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
scene.add(pointLightHelper)
2、环境光设置
环境光AmbientLight没有特定方向,只是整体改变场景的光照明暗。
//添加环境光
const ambient = new THREE.AmbientLight(0xffffff, 0.4)
scene.add(ambient);

3、平行光
平行光DirectionalLight就是沿着特定方向发射。
//添加平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(80,100,50);
directionalLight.target = cube;
scene.add(directionalLight)

4、平行光辅助观察DirectionalLightHelper
通过点光源辅助观察对象DirectionalLightHelper 可视化点光源
const dirLightHelper = new THREE.DirectionalLightHelper(directionalLight, 5,0xff0000);
scene.add(dirLightHelper);

八、动画渲染循环
threejs可以借助HTML5的API请求动画帧window.requestAnimationFrame实现动画渲染。
1、请求动画帧window.requestAnimationFrame
function render() {
requestAnimationFrame(render)
}
render()
2、threejs旋转动画
function render() {
cube.rotateY(0.5)
renderer.render(scene, camera)
requestAnimationFrame(render)
}
render()
九、Canvas画布布局和全屏
1、全屏渲染
// width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
const width = window.innerWidth; //窗口文档显示区的宽度作为画布宽度
const height = window.innerHeight; //窗口文档显示区的高度作为画布高度
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
2、canvas画布宽高度动态变化
canvas画布宽高度动态变化,需要更新相机和渲染的参数,否则无法正常渲染。
window.onresize = function () {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix()
}
十、 stats查看threejs渲染帧率
three.js每执行WebGL渲染器.render()方法一次,就在canvas画布上得到一帧图像,不停地周期性执行.render()方法就可以更新canvas画布内容,一般场景越复杂往往渲染性能越低,也就是每秒钟执行.render()的次数越低。
通过stats.js库可以查看three.js当前的渲染性能,具体说就是计算three.js的渲染帧率(FPS),所谓渲染帧率(FPS),简单说就是three.js每秒钟完成的渲染次数,一般渲染达到每秒钟60次为最佳状态。
stats.js下载链接:https://github.com/mrdoob/stats.js
1、引入Stats
//引入性能监视器stats.js
import Stats from 'three/addons/libs/stats.module.js';
2、Stats使用

//引入性能监视器stats.js
import Stats from 'three/addons/libs/stats.module.js';
const state = new Stats();
document.body.appendChild(state.domElement)
function render() {
state.update();
cube.rotateY(0.05)
renderer.render(scene, camera)
requestAnimationFrame(render)
}
render()

3、性能测试
// 随机创建大量的模型,测试渲染性能
const num = 1000; //控制长方体模型数量
for (let i = 0; i < num; i++) {
const geometry = new THREE.BoxGeometry(5, 5, 5);
const material = new THREE.MeshLambertMaterial({
color: 0x00ffff
});
const mesh = new THREE.Mesh(geometry, material);
// 随机生成长方体xyz坐标
const x = (Math.random() - 0.5) * 200
const y = (Math.random() - 0.5) * 200
const z = (Math.random() - 0.5) * 200
mesh.position.set(x, y, z)
scene.add(mesh); // 模型对象插入场景中
}

十一、阵列立方体和相机适配体验
1、for循环创建一列模型
const geometry2 = new THREE.BoxGeometry(100, 100, 100)
const material2 = new THREE.MeshLambertMaterial({
color: 0x00ffff, //设置材质颜色
transparent: true,//开启透明
opacity: 0.5,//设置透明度
})
for (let index = 0; index < 10; index++) {
const mesh = new THREE.Mesh(geometry2, material2);
mesh.position.set(index * 200, 0, 0)
scene.add(mesh);
}

2、双层for循环创建阵列模型
const geometry2 = new THREE.BoxGeometry(100, 100, 100)
const material2 = new THREE.MeshLambertMaterial({
color: 0x00ffff, //设置材质颜色
transparent: true,//开启透明
opacity: 0.5,//设置透明度
})
for (let index = 0; index < 10; index++) {
for (let j = 0; j < 10; j++) {
const mesh = new THREE.Mesh(geometry2, material2);
mesh.position.set(index * 200, 0, j * 200)
scene.add(mesh);
}
}

3、远小近大投影规律
透视投影相机的投影规律是远小近大,通过相机观察阵列立方体大小变化,可以看到距离相机越远,立方体的渲染视觉效果越小。
4、fov改变
增加相机视角fov,视锥体范围更大,意味着可以看到渲染范围更大,远小近大的视觉效果更明显。
十二、Threejs常见几何体简介
Three.js提供的几何体API很多,本节课先给大家介绍几个比较简单的案例,为后面的学习打下基础。

const scene = new THREE.Scene();
//长方体
const geometry = new THREE.BoxGeometry(10, 10, 10);
const material = new THREE.MeshLambertMaterial({
color: 'red', //设置材质颜色
});
const cube = new THREE.Mesh(geometry, material);
cube.position.set(0, 10, 0)
scene.add(cube);
//球
const Sphere = new THREE.SphereGeometry(10);
const SphereMesh = new THREE.Mesh(Sphere, material);
SphereMesh.position.set(0, 30, 0)
scene.add(SphereMesh);
//圆柱
const Cylinder = new THREE.CylinderGeometry(10,10,10);
const CylinderMesh = new THREE.Mesh(Cylinder, material);
CylinderMesh.position.set(0, 50, 0)
scene.add(CylinderMesh);
//矩形平面
const Circle = new THREE.CircleGeometry(10,10);
const CircleMesh = new THREE.Mesh(Circle,material)
CircleMesh.position.set(0, 90, 0)
scene.add(CircleMesh);
//圆形平面
const Plane = new THREE.PlaneGeometry(10,10);
const PlaneMesh = new THREE.Mesh(Plane,material)
PlaneMesh.position.set(0, 70, 0)
scene.add(PlaneMesh);

2、双面可见
Three.js的材质默认正面可见,反面不可见,对于矩形平面PlaneGeometry、圆形平面如果你想看到两面,可以设置side: THREE.DoubleSide。
new THREE.MeshBasicMaterial({
side: THREE.FrontSide, //默认只有正面可见
});
new THREE.MeshBasicMaterial({
side: THREE.DoubleSide, //两面可见
});
十三、高光网格材质Phong
高光网格材质MeshPhongMaterial和基础网格材质MeshBasicMaterial、漫反射网格材质MeshLambertMaterial一样都是网格模型的Mesh的材质。
高光网格材质MeshPhongMaterial和漫反射网格材质MeshLambertMaterial一样会受到光照的影响。

1、MeshPhongMaterial对光照反射特点
MeshPhongMaterial和MeshLambertMaterial都会受到光照的影响区别在于,对光线反射方式有差异。
MeshPhongMaterial可以实现MeshLambertMaterial不能实现的高光反射效果。对于高光效果,你可以想象一下,你在太阳下面观察一辆车,你会发现在特定角度和位置,你可以看到车表面某个局部区域非常高亮。
2、镜面反射与漫反射
MeshPhongMaterial可以提供一个镜面反射效果,可以类比你生活中拿一面镜子,放在太阳光下,调整角度,可以把太阳光反射到其它地方,如果反射光对着眼睛,也就是反射光线和视线平行的时候,会非常刺眼。
MeshLambertMaterial对应的Mesh受到光线照射,没有镜面反射的效果,只是一个漫反射,也就是光线向四周反射
3、高光亮度属性.shininess
通过MeshPhongMaterial的高光亮度.shininess属性,可以控制高光反射效果。
const material = new THREE.MeshPhongMaterial({
color: 'red', //设置材质颜色
shininess: 20,
specular: '#fff', //高光部分的颜色
});
//需要用到点光源
const pointLight = new THREE.PointLight('#fff', 1.0);
pointLight.intensity = 2.0
pointLight.decay = 0.0;
pointLight.position.set(400, 200, 100)
scene.add(pointLight)

十四、WebGL渲染器设置(锯齿模糊)
1、渲染器锯齿属性.antialias
设置渲染器锯齿属性.antialias的值可以直接在参数中设置,也可通过渲染器对象属性设置。
const renderer = new THREE.WebGLRenderer({
antialias:true,
});
2、设备像素比window.devicePixelRatio
如果你有web前端基础,应该了解window对象,设备像素比.devicePixelRatio是window对象的一个属性,该属性的值和你的硬件设备屏幕相关,不同硬件设备的屏幕window.devicePixelRatio的值可能不同,可能就是1、1.5、2.0等其它值。
console.log('查看当前屏幕设备像素比',window.devicePixelRatio)
3、设置设备像素比.setPixelRatio()
如果你遇到你的canvas画布输出模糊问题,注意设置renderer.setPixelRatio(window.devicePixelRatio)。
注意:注意你的硬件设备设备像素比window.devicePixelRatio刚好是1,那么是否执行.setPixelRatio()不会有明显差异,不过为了适应不同的硬件设备屏幕,通常需要执行该方法。
renderer.setPixelRatio(window.devicePixelRatio);
4、设置背景颜色.setClearColor()
renderer.setClearColor('green', 1)

十五、gui.js库(可视化改变三维场景)
dat.gui.js说白了就是一个前端js库,对HTML、CSS和JavaScript进行了封装,学习开发的时候,借助dat.gui.js可以快速创建控制三维场景的UI交互界面,你打开课件中案例源码体验一下就能感受到。
课程学习dat.gui.js也不仅仅是为了学习dat.gui.js,也是建立一种思想,就是threejs三维空间的很多参数,不是心算出来的,往往需要可视化的方式调试出来。
1、引入dat.gui.js
gihtub地址:https://github.com/dataarts/dat.gui
npm地址:https://www.npmjs.com/package/dat.gui
你可以通过npm或github方式获得dat.gui.js库,当然为了学习方便,threejs官方案例扩展库中也提供了gui.js,你可以直接使用。
// 引入dat.gui.js的一个类GUI
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
2、创建一个GUI对象
创建一个GUI对象,你可以看到浏览器右上角多了一个交互界面,GUI本质上就是一个前端js库。
// 实例化一个gui对象
const gui = new GUI();

3、.domElement:改变GUI界面默认的style属性
通过.domElement属性可以获取gui界面的HTML元素,那就意味着你可以改变默认的style样式,比如位置、宽度等。
//改变交互界面style属性
gui.domElement.style.right = '0px';
gui.domElement.style.width = '300px';
4、.add()方法
执行gui的.add()方法可以快速创建一个UI交互界面,比如一个拖动条,可以用来改变一个JavaScript对象属性的属性值。
格式:.add(控制对象,对象具体属性,其他参数)
其他参数,可以一个或多个,数据类型也可以不同,gui会自动根据参数形式,自动生成对应的交互界面。
参数3和参数4,分别是一个数字,交互界面是一个鼠标可以拖动的拖动条,可以在一个区间改变属性的值
执行gui.add(obj, 'x', 0, 100);你可以发现右上角gui界面增加了新的内容,可以控制obj对象x属性的新交互界面。
//创建一个对象,对象属性的值可以被GUI库创建的交互界面改变
const obj = {
x: 30,
};
// gui增加交互界面,用来改变obj对应属性
gui.add(obj, 'x', 0, 100);

5、gui改变js对象多个属性
const obj = {
x: 30,
y: 60,
z: 300,
};
// gui界面上增加交互界面,改变obj对应属性
gui.add(obj, 'x', 0, 100);
gui.add(obj, 'y', 0, 50);
gui.add(obj, 'z', 0, 60);

6、gui改变threejs光照强度测试
three.js在调试场景渲染效果的时候,比如光照的强度,人大脑的CPU是没有能力通过光照参数算出来模型渲染效果的,一般来说你先大概给一个经验值,然后通过gui在这个大概值的基础上下浮动可视化调试。
光源对象具有一个光照强度属性.intensity,可以通过gui拖动条改变该属性。
const pointLight = new THREE.PointLight('#fff', 1.0);
pointLight.intensity = 2.0
pointLight.decay = 0.0;
pointLight.position.set(400, 200, 100)
scene.add(pointLight)
gui.add(pointLight, 'intensity', 1, 3)

7、gui改变threejs模型位置测试
mesh.position是JavaScript对象,具有x、y、z属性,这三个属性分别表示模型的xyz坐标,这就是说,gui改变mesh.position的x、y、z属性,就可以可视化改变mesh的位置。
const scene = new THREE.Scene();
//长方体
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshPhongMaterial({
color: 'red', //设置材质颜色
shininess: 20,
specular: '#fff', //高光部分的颜色
});
const cube = new THREE.Mesh(geometry, material);
cube.position.set(0, 10, 0)
gui.add(cube.position, 'x', 0, 100)
gui.add(cube.position, 'y', 0, 100)
gui.add(cube.position, 'z', 0, 100)
scene.add(cube);

十六、gui调试界面2-颜色命名等
1、.name()方法
.add()创建的交互界面,会默认显示所改变属性的名字,为了通过交互界面更好理解你改变的某个对象属性,你可以通过.name()方法改变gui生成交互界面显示的内容
const gui = new GUI();//创建GUI对象
gui.add(ambient, 'intensity', 0, 2.0).name('环境光强度');
gui.add(directionalLight, 'intensity', 0, 2.0).name('平行光强度');

2、步长.step()方法
步长.step()方法可以设置交互界面每次改变属性值间隔是多少。每一次拖动的时候,每一步的长度。
gui.add(pointLight, 'intensity', 1, 3).name('点光源').step(0.2)
3、.onChange()方法
当gui界面某个值的时候,.onChange()方法就会执行,这时候你可以根据需要通过.onChange()执行某些代码。
gui.add(cube.position, 'z', 0, 100).onChange((e) => {
camera.position.set(200, 200, 200 + e)
console.log('asdf', e);
})
4、.addColor()颜色值改变
.addColor()生成颜色值改变的交互界面
let obj = {
color: '#fff'
}
gui.addColor(obj, 'color').onChange(e => {
cube.material.color.set(e)
})

十七、gui调试3-下拉菜单、单选框
前面大家学过通过.add()方法可以添加一个拖动条用来改变对象的某个属性,本节课给大家介绍.add()方法创建新的UI交互界面,比如下拉菜单、单选框。
1、.add()方法参数3和4数据类型:数字
格式:add(控制对象,对象具体属性,其他参数)
其他参数,可以一个或多个,数据类型也可以不同,gui会自动根据参数形式,自动生成对应的交互界面。
参数3和参数4,分别是一个数字,交互界面是一个鼠标可以拖动的拖动条,可以在一个区间改变属性的值
gui.add(pointLight, 'intensity', 1, 3).name('点光源')

2、.add()方法参数3数据类型:数组
参数3是一个数组,生成交互界面是下拉菜单
gui.add(pointLight, 'intensity', [1, 2, 3]).name('点光源')

3、.add()方法参数3数据类型:对象
参数3是一个对象,生成交互界面是下拉菜单
let obj = {
color: '#fff'
}
gui.add(obj, 'color', {
'红': 'red',
'绿': 'green',
'蓝': 'blue',
}).onChange(e=>{
cube.material.color.set(e)
})

4、.add()方法对应属性的数据类型:布尔值
控制一个对象是否旋转。
// 实例化一个gui对象
const gui = new GUI();
let obj = {
BooleanValue: false
}
gui.add(obj,'BooleanValue')
function render() {
state.update();
if (obj.BooleanValue) {
cube.rotateY(0.05)
}
renderer.render(scene, camera)
requestAnimationFrame(render)
}
render()

十八、gui.js库(分组)
当GUI交互界面需要控制的属性比较多的时候,为了避免混合,可以适当分组管理,这样更清晰。
1、.addFolder()分组
new GUI()实例化一个gui对象,默认创建一个总的菜单,通过gui对象的.addFolder()方法可以创建一个子菜单,当你通过GUI控制的属性比较多的时候,可以使用.addFolder()进行分组。
.addFolder()返回的子文件夹对象,同样具有gui对象的.add()、.onChange()、.addColor()等等属性。
// 实例化一个gui对象
const gui = new GUI();
let obj = {
color: 'green',
specular: '#fff',
BooleanValue: false
}
const matFolder = gui.addFolder('材质')
matFolder.addColor(obj, 'color').onChange(e => {
cube.material.color.set(e)
})
matFolder.addColor(obj, 'specular').onChange(e => {
cube.material.specular.set(e)
})
gui.add(obj, 'BooleanValue')
function render() {
state.update();
if (obj.BooleanValue) {
cube.rotateY(0.05)
}
renderer.render(scene, camera)
requestAnimationFrame(render)
}
render()

2、关闭.close()和展开.open()交互界面
gui对象创建的总菜单或gui.addFolder()创建的子菜单都可以用代码控制交互界面关闭或开展状态。
const gui = new GUI(); //创建GUI对象
gui.close();//关闭菜单
// 创建材质子菜单
const matFolder = gui.addFolder('材质');
matFolder.close();//关闭菜单
3、.addFolder()套娃——子菜单嵌套子菜单
.addFolder()创建的对象,同样也具有.addFolder()属性,可以继续嵌套子菜单。
// 平行光子菜单
const dirFolder = gui.addFolder('平行光');
dirFolder.close();//关闭菜单
// 平行光强度
dirFolder.add(directionalLight, 'intensity',0,2);
const dirFolder2 = dirFolder.addFolder('位置');//子菜单的子菜单
dirFolder2.close();//关闭菜单
// 平行光位置
dirFolder2.add(directionalLight.position, 'x',-400,400);
dirFolder2.add(directionalLight.position, 'y',-400,400);
dirFolder2.add(directionalLight.position, 'z',-400,400);
5667

被折叠的 条评论
为什么被折叠?



