一、three.js快速入门学习笔记

 备注:“本文中部分核心知识点整理自老师的授课网站”

网站地址:http://www.webgl3d.cn/pages/aac9ab/

一·three.js初始化操作

1 · 下载连接

Releases · mrdoob/three.js · GitHub

2、文档链接(中文)

 three.js docs

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对光照反射特点

MeshPhongMaterialMeshLambertMaterial都会受到光照的影响区别在于,对光线反射方式有差异。 

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对象,具有xyz属性,这三个属性分别表示模型的xyz坐标,这就是说,gui改变mesh.positionxyz属性,就可以可视化改变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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值