1. 本地搭建Threejs官方文档
- 去到Three.js官方文档中找到github地址并跳转
- 找到当前dev环境下的代码压缩包下载并解压
- 代码导入到vscode中并安装依赖
- npm run start || yarn start
- 鼠标点击生成的本地访问地址(在浏览器里手动敲击地址可能会出现http解析错误问题)
2. Parcel
- 首先环境准备 node npm | yarn, 并通过yarn init | npm init 创建一个环境
- 下载Parcel依赖 yarn add --dev parcel | npm install --save-dev parcel
- 配置package.json
- 加入 "source": "src/index.html",
- 并创建src目录以及index.html(快捷键: html:5)
- 加入 "scripts": { "start": "parcel", "build": "parcel build" },
- 此时可以跑起来了(空白页面)
- 安装threejs依赖 yarn add three --save | npm install three --save
- 在main.js中引入threejs import * as Three from "three";
- ok
3. 浅尝
1.基础用法
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; // 导入轨道控制器
console.log(THREE);
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45, // 角度
window.innerWidth / window.innerHeight, // 长/宽比
0.1, // 近端
1000 // 远端
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建几何物体 - BoxGeometry(几何体: 长 宽 高)
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 设置物体材质 - MeshBasicMaterial(基础网格材质: )
const cubeMat = new THREE.MeshBasicMaterial({ color: 0xffff00 });
// 根据几何体和物体材质创建物体
const cube = new THREE.Mesh(cubeGeometry, cubeMat);
// 移动物体
// 修改物体的位置(距离x轴原点多远,y,z; 可以不用set方法单独设置)
// 其实物体的移动就是每次render的时候都去修改他的位置就是移动
cube.position.set(1, 1, 1);
// 缩放物体(x轴缩放多少倍, y, z; 可以不用set方法单独设置)
cube.scale.set(1, 1, 2); // 由原来的(1, 1, 1)=>(2, 1, 3)
// 旋转物体(x轴缩放多少倍, y, z; 可以不用set方法单独设置)
// 其实物体的旋转就是每次render的时候修改他的旋转
cube.rotation.set(Math.PI / 4, 0, 0); // Math.Pi : Π, 180°
// 把几何物体添加到场景中
scene.add(cube);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 使用渲染器, 通过相机将场景渲染出来
// renderer.render(scene, camera);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
//创建一个时钟
const clock = new THREE.Clock();
// 封装渲染函数
function render(time) {
/**
* 控制动画方式(一)
* 利用请求动画帧参数控制物体移动
* time: 请求动画帧requestAnimationFrame函数自带的参数
* time: 计量单位是秒 time/1000获取到毫秒
* 数学公式: s = v * t
* t的作用是保证每次移动的距离都是一样的, 而不是根据浏览器刷新频率
* 可以打印time看一下就知道了
* 取模5: 只有这样才能循环的从0位置开始移动, 不然会一直在0的位置上
* time不能总是被拿来做各种设置和控制, 所以我们可以用时间跟踪函数clock替换
* 代码: let t = (time / 1000) % 5;
*
*
* 控制动画方式(二)
* 用时钟函数来控制物体的移动
* getElapsedTime: 时钟运行的总时长
* getDelta: 间隔时常
* 代码: let t = clock.getElapsedTime() % 5
*
*
* 控制动画方式(三)
* 引入gsap第三方动画库
* 优点: 不用再去自己根据时间做限制动画了, 把物体丢进去就行了
*/
// 设置物体的移动
cube.position.x = 1 * t;
// 设置物体旋转
cube.rotation.x += 0.1;
if (cube.position.x > 5) {
cube.position.x = 0;
}
// 设置控制器update
controls.update();
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
/**
* 请求动画帧函数: 浏览器自带的渲染函数,
* 每一次浏览器渲染的时候都要渲染场景
* 有的电脑144hz,一秒钟就渲染144次
*/
requestAnimationFrame(render);
}
// 默认渲染一下
render();
2. gsap动画库集成
安装依赖
yarn add gsap | npm install gsap
引用gsap
import gsap from "gsap";
/**
* 给物体cube设置动画
* 1.沿x轴移动距离5, 时间为5秒, 速度先快后慢
* 2.沿x轴旋转360°, 时间为5秒, 速度先快后慢
* 3.这样在渲染函数里就不需要再写控制代码了, 每次渲染的时候都会自动执行
* 4.repeat: 循环的次数 -1为一直循环
* 5.yoyo: 往返运动
* 6.delay: 延迟几秒才开始运动
*/
var animate1 = gsap.to(cube.position, {
x: 5,
duration: 5,
ease: "power1.inOut",
repeat: -1,
yoyo: true,
delay: 2,
onComplete: () => {
console.log("动画完成!");
},
onStart: () => {
console.log("动画开始!");
},
});
var animate2 = gsap.to(cube.rotation, {
x: 2 * Math.PI,
duration: 5,
ease: "power1.inOut",
repeat: -1,
yoyo: true,
onComplete: () => {
console.log("动画完成!");
},
onStart: () => {
console.log("动画开始!");
},
});
// 双击控制暂停旋转或者继续
window.addEventListener("dblclick", () => {
if (animate1.isActive()) animate1.pause();
else animate1.resume();
});
3. 跟随画面变化更新渲染视图
// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
//设置渲染器的像素比(不同设备不同的像素比, 适应屏幕分辨率)
renderer.setPixelRatio(window.devicePixelRatio);
});
4. js控制全屏或者退出全屏
// 双击控制全屏或退出全屏
window.addEventListener("dblclick", () => {
let fullScreenElement = document.fullscreenElement;
if (!fullScreenElement) renderer.domElement.requestFullscreen();
else document.exitFullscreen();
});
5. 应用图形界面更改变量
安装依赖dat.gui
yarn add dat.gui --save | npm install dat.gui --save
import * as dat from "dat.gui"; // 导入可视化控制器
// 定义一个可视化界面函数
const gui = new dat.GUI();
/**
* 给物体添加x轴移动的可视化
* min: 最小值
* max: 最大值
* step: 每次移动的距离
* name: 给当前命名
*/
gui
.add(cube.position, "x")
.min(0)
.max(5)
.step(0.01)
.name("x轴移动")
.onChange((value) => {
console.log("值被修改为:", value);
})
.onFinishChange((val) => {
console.log("完全停下来的值:", val);
});
// 给物体添加一个设置颜色的可视化界面
const params = {
color: "#ffff00",
fn: () => {
// 点击事件让物体运动起来
gsap.to(cube.position, { x: 0, duration: 2, yoyo: true, repeat: -1 });
},
};
// 添加颜色改变的修改事件
gui.addColor(params, "color").onChange((value) => {
cube.material.color.set(value);
});
// 控制物体是否显示
gui.add(cube, "visible").name("是否显示");
// 给物体添加点击事件
gui.add(params, "fn").name("点击立方体运动");
// 创建一个文件夹(把事件等用文件夹来归拢)
var folder = gui.addFolder("设置几何立方体");
// 添加一个设置材质为线框的属性
folder.add(cube.material, "wireframe");
6. 基础用法总结
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; // 导入轨道控制器
import gsap from "gsap"; // 导入动画库
import * as dat from "dat.gui"; // 导入可视化控制器
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建几何体 - BoxGeometry(几何体: 长 宽 高)
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 设置物体材质 - MeshBasicMaterial(基础网格材质: )
const cubeMat = new THREE.MeshBasicMaterial({ color: 0xffff00 });
// 根据几何体和物体材质创建物体
const cube = new THREE.Mesh(cubeGeometry, cubeMat);
// 移动物体
cube.position.set(1, 1, 1);
// 缩放物体(x轴缩放多少倍, y, z; 可以不用set方法单独设置)
cube.scale.set(1, 1, 2); // 由原来的(1, 1, 1)=>(2, 1, 3)
// 旋转物体(x轴缩放多少倍, y, z; 可以不用set方法单独设置)
cube.rotation.set(Math.PI / 4, 0, 0); // Math.Pi : Π, 180°
// 把几何体添加到场景中
scene.add(cube);
// 定义一个可视化界面函数
const gui = new dat.GUI();
/**
* 给物体添加x轴移动的可视化
* min: 最小值
* max: 最大值
* step: 每次移动的距离
* name: 给当前命名
*/
gui
.add(cube.position, "x")
.min(0)
.max(5)
.step(0.01)
.name("x轴移动")
.onChange((value) => {
console.log("值被修改为:", value);
})
.onFinishChange((val) => {
console.log("完全停下来的值:", val);
});
// 给物体添加一个设置颜色的可视化界面
const params = {
color: "#ffff00",
fn: () => {
// 点击事件让物体运动起来
gsap.to(cube.position, { x: 0, duration: 2, yoyo: true, repeat: -1 });
},
};
// 添加颜色改变的修改事件
gui.addColor(params, "color").onChange((value) => {
cube.material.color.set(value);
});
// 控制物体是否显示
gui.add(cube, "visible").name("是否显示");
// 给物体添加点击事件
gui.add(params, "fn").name("点击立方体运动");
// 创建一个文件夹(把事件等用文件夹来归拢)
var folder = gui.addFolder("设置几何立方体");
// 添加一个设置材质为线框的属性
folder.add(cube.material, "wireframe");
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
/**
* 给物体cube设置动画
* 1.沿x轴移动距离5, 时间为5秒, 速度先快后慢
* 2.沿x轴旋转360°, 时间为5秒, 速度先快后慢
* 3.这样在渲染函数里就不需要再写控制代码了, 每次渲染的时候都会自动执行
* 4.repeat: 循环的次数 -1为一直循环
* 5.yoyo: 往返运动
* 6.delay: 延迟几秒才开始运动
*/
var animate1 = gsap.to(cube.position, {
x: 5,
duration: 5,
ease: "power1.inOut",
repeat: -1,
yoyo: true,
delay: 2,
onComplete: () => {
console.log("动画完成!");
},
onStart: () => {
console.log("动画开始!");
},
});
var animate2 = gsap.to(cube.rotation, {
x: 2 * Math.PI,
duration: 5,
ease: "power1.inOut",
repeat: -1,
yoyo: true,
onComplete: () => {
console.log("动画完成!");
},
onStart: () => {
console.log("动画开始!");
},
});
// 封装渲染函数
function render() {
if (cube.position.x > 5) {
cube.position.x = 0;
}
// 设置控制器update
controls.update();
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
// 单击控制暂停旋转或者继续
window.addEventListener("click", () => {
if (animate1.isActive()) animate1.pause();
else animate1.resume();
});
// 双击控制全屏或退出全屏
window.addEventListener("dblclick", () => {
let fullScreenElement = document.fullscreenElement;
if (!fullScreenElement) renderer.domElement.requestFullscreen();
else document.exitFullscreen();
});
// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
//设置渲染器的像素比(不同设备不同的像素比, 适应屏幕分辨率)
renderer.setPixelRatio(window.devicePixelRatio);
});
4. Threejs基础
1. 几何体
创建一个具有50个面且每个面的颜色都是随机的几何体
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; // 导入轨道控制器
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
for (let i = 0; i < 50; i++) {
// 创建几何体 - BufferGeometry
const geometry = new THREE.BufferGeometry();
// 创建三维坐标位置数组
const positionArray = new Float32Array(9);
// [-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0,1.0, -1.0, -1.0, 1.0,]
// 每一个三角形有3个顶点,每个顶点有3个坐标
for (let j = 0; j < 9; j++) {
positionArray[j] = Math.random() * 10 - 5;
}
// 将3维的坐标点位置属性赋值给几何体
geometry.setAttribute(
"position",
new THREE.BufferAttribute(positionArray, 3)
);
let color = new THREE.Color(Math.random(), Math.random(), Math.random());
// 设置物体材质 - MeshBasicMaterial(基础网格材质)
const material = new THREE.MeshBasicMaterial({
color: color, // 设置材质颜色
opacity: 0.5, // 设置透明材质
transparent: true, // 设置为true才可以透明
});
// 根据几何体和物体材质创建物体
const mesh = new THREE.Mesh(geometry, material);
// 把几何体添加到场景中
scene.add(mesh);
}
const params = { color: "#ffff00" };
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
2. 材质
1. 导入纹理
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 导入轨道控制器
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建一个几何体
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1);
// 导入纹理加载器
const textureLoader = new THREE.TextureLoader();
// 导入一张纹理
const door = textureLoader.load("./textures/door/door.jpg");
// 材质
const basicMaterial = new THREE.MeshBasicMaterial({
color: "#ffff00", // 设置颜色
map: door, // 设置纹理
});
// 组合几何体和材质
const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
// 把几何体添加到场景中
scene.add(cube);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
纹理图:
2.设置纹理旋转_偏移_重复及算法mipmap
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 导入轨道控制器
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建一个几何体
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1);
// 导入纹理加载器
const textureLoader = new THREE.TextureLoader();
// 导入一张纹理
const door = textureLoader.load("./textures/door/door.jpg");
/**
* 设置纹理属性
*
* 设置纹理偏移
* door.offset.x = 0.5; // (0 - 1.0)
* door.offset.y = 0.5;
* door.offset.set(0.5, 0.5);
*
* 设置中心原点
* door.center.set(0.5, 0.5);
*
* 设置纹理旋转
* door.rotation = Math.PI / 4; // 旋转45度: 旋转多少度,单位是弧度
*
* 设置纹理重复;
* door.repeat.set(2, 3); // 水平重复2次, 竖直重复3次
*
* 设置纹理重复的模式;
* door.wrapS = THREE.MirroredRepeatWrapping; // 水平重复模式: 镜像
* door.wrapT = THREE.RepeatWrapping; // 竖直重复模式: 无限重复
*
* 纹理算法
* 类似css中的自适应, 纹理图片的大小与当前的几何体的大小自适应方式
* door.minFilter = THREE.NearestFilter; // 最接近纹素的值
* door.magFilter = THREE.NearestFilter;
* door.magFilter = THREE.LinearFilter; // 线性的
*/
// 材质
const basicMaterial = new THREE.MeshBasicMaterial({
color: "#ffff00", // 设置颜色
map: door, // 设置纹理
});
// 组合几何体和材质
const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
// 把几何体添加到场景中
scene.add(cube);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
3. 透明材质与透明纹理
import * as THREE from "three";
import { DoubleSide } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 导入轨道控制器
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建一个几何体
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1);
// 导入纹理加载器
const textureLoader = new THREE.TextureLoader();
// 导入一张纹理
const door = textureLoader.load("./textures/door/door.jpg");
// 导入透明纹理背景图
const doorAlpha = textureLoader.load("./textures/door/color.jpg");
// alphaMap就是要么黑要么白,所以这个背景图也需要是这个颜色的
// 材质
const basicMaterial = new THREE.MeshBasicMaterial({
color: "#ffff00", // 设置颜色
map: door, // 设置纹理
alphaMap: doorAlpha, // 设置纹理透明背景
transparent: true, // 允许透明的属性, 为true才可以透明
// opacity: 0.5 // 设置纹理透明度, 类似css中的背景图透明度设置
side: DoubleSide, // 设置渲染哪一面 DoubleSide: 渲染两面
});
// 组合几何体和材质
const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
// 把几何体添加到场景中
scene.add(cube);
// 添加一个平面(材质还是用上边的透明纹理)
const plane = new THREE.Mesh(
new THREE.PlaneBufferGeometry(1, 1),
basicMaterial
);
plane.position.set(3, 0, 0);
scene.add(plane);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
透明纹理图:
效果图:
4. 遮挡贴图
import * as THREE from "three";
import { DoubleSide } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 导入轨道控制器
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建一个几何体
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1);
// 导入纹理加载器
const textureLoader = new THREE.TextureLoader();
// 导入一张纹理
const door = textureLoader.load("./textures/door/door.jpg");
// 导入透明纹理背景图
const doorAlpha = textureLoader.load("./textures/door/color.jpg");
// alphaMap就是要么黑要么白,所以这个背景图也需要是这个颜色的
// 导入遮挡贴图
const doorTietu = textureLoader.load("./textures/door/tietu.jpg");
// 材质
const basicMaterial = new THREE.MeshBasicMaterial({
color: "#ffff00", // 设置颜色
map: door, // 设置纹理
alphaMap: doorAlpha, // 设置纹理透明背景
transparent: true, // 允许透明的属性, 为true才可以透明
// opacity: 0.5 // 设置纹理透明度, 类似css中的背景图透明度设置
side: DoubleSide, // 设置渲染哪一面 DoubleSide: 渲染两面
aoMap: doorTietu, // 设置贴图(贴图就是给纹理再加上一个背景贴图)
aoMapIntensity: 0.5, // ao贴图的强度设置
});
// 组合几何体和材质
const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
// 给cube设置贴图的uv
cubeGeometry.setAttribute(
"uv2",
new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
);
// 把几何体添加到场景中
scene.add(cube);
// 添加一个平面(材质还是用上边的透明纹理)
const plane = new THREE.Mesh(
new THREE.PlaneBufferGeometry(1, 1),
basicMaterial
);
plane.position.set(3, 0, 0);
scene.add(plane);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
贴图:
效果图:
5.标准网格材质与灯光物理效果
import * as THREE from "three";
import { DoubleSide } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建一个几何体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 导入纹理加载器
const textureLoader = new THREE.TextureLoader();
// 导入一张纹理
const door = textureLoader.load("./textures/door/door.jpg");
// 导入透明纹理背景图
const doorAlpha = textureLoader.load("./textures/door/color.jpg");
// alphaMap就是要么黑要么白,所以这个背景图也需要是这个颜色的
// 导入遮挡贴图
const doorTietu = textureLoader.load("./textures/door/tietu.jpg");
// 材质
const standardMaterial = new THREE.MeshStandardMaterial({
color: "#ffff00", // 设置颜色
map: door, // 设置纹理
alphaMap: doorAlpha, // 设置纹理透明背景
transparent: true, // 允许透明的属性, 为true才可以透明
// opacity: 0.5 // 设置纹理透明度, 类似css中的背景图透明度设置
side: DoubleSide, // 设置渲染哪一面 DoubleSide: 渲染两面
aoMap: doorTietu, // 设置贴图(贴图就是给纹理再加上一个背景贴图)
aoMapIntensity: 0.5, // ao贴图的强度设置
});
// 组合几何体和材质
const cube = new THREE.Mesh(cubeGeometry, standardMaterial);
// 给cube设置贴图的uv
cubeGeometry.setAttribute(
"uv2",
new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
);
// 把几何体添加到场景中
scene.add(cube);
// 添加一个平面(材质还是用上边的透明纹理)
const plane = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), standardMaterial);
plane.position.set(3, 0, 0);
scene.add(plane);
/**
* 追加灯光
* // 创建环境光
* const light = new THREE.AmbientLight(0xffffff, 0.9);
* // 0.9: 光线强度,默认是1
* // 将环境光添加到场景中
* scene.add(light);
*
* // 创建平行光
* const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
* // 设置灯光位置
* directionalLight.position.set(10, 10, 10);
* // 将平行光添加到场景中
* scene.add(directionalLight);
*/
// 创建环境光
const light = new THREE.AmbientLight(0xffffff, 0.5);
// 0.9: 光线强度,默认是1
// 将环境光添加到场景中
scene.add(light);
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置灯光位置
directionalLight.position.set(10, 10, 10);
// 将平行光添加到场景中
scene.add(directionalLight);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render()
效果图:
6.置换贴图(具有深度上的感觉, 或者说有凹凸感)
import * as THREE from "three";
import { DoubleSide } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建一个几何体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 100, 100, 100);
// 导入纹理加载器
const textureLoader = new THREE.TextureLoader();
// 导入一张纹理
const door = textureLoader.load("./textures/door/door.jpg");
// 导入透明纹理背景图
const doorAlpha = textureLoader.load("./textures/door/color.jpg");
// 导入遮挡贴图
const doorTietu = textureLoader.load("./textures/door/tietu.jpg");
// 导入置换贴图
const doorDeep = textureLoader.load("./textures/door/deep.jpg");
// 材质
const standardMaterial = new THREE.MeshStandardMaterial({
color: "#ffff00", // 设置颜色
map: door, // 设置纹理
alphaMap: doorAlpha, // 设置纹理透明背景
transparent: true, // 允许透明的属性, 为true才可以透明
// opacity: 0.5 // 设置纹理透明度, 类似css中的背景图透明度设置
side: DoubleSide, // 设置渲染哪一面 DoubleSide: 渲染两面
aoMap: doorTietu, // 设置贴图(贴图就是给纹理再加上一个背景贴图)
aoMapIntensity: 0.5, // ao贴图的强度设置
displacementMap: doorDeep, // 设置置换贴图, 使其具有深度上的效果
displacementScale: 0.05, // 置换贴图的影响强度
});
// 组合几何体和材质
const cube = new THREE.Mesh(cubeGeometry, standardMaterial);
// 给cube设置贴图的uv
cubeGeometry.setAttribute(
"uv2",
new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
);
// 把几何体添加到场景中
scene.add(cube);
// 添加一个平面(材质还是用上边的透明纹理)
const plane = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), standardMaterial);
plane.position.set(3, 0, 0);
scene.add(plane);
// 创建环境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // 0.9: 光线强度,默认是1
// 将环境光添加到场景中
scene.add(light);
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置灯光位置
directionalLight.position.set(10, 10, 10);
// 将平行光添加到场景中
scene.add(directionalLight);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
贴图:
效果图:
7.粗糙度贴图金属贴图法线贴图
import * as THREE from "three";
import { DoubleSide } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建一个几何体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 100, 100, 100);
// 导入纹理加载器
const textureLoader = new THREE.TextureLoader();
// 导入一张纹理
const door = textureLoader.load("./textures/door/door.jpg");
// 导入透明纹理背景图
const doorAlpha = textureLoader.load("./textures/door/color.jpg");
// 导入遮挡贴图
const doorTietu = textureLoader.load("./textures/door/tietu.jpg");
// 导入置换贴图
const doorDeep = textureLoader.load("./textures/door/deep.jpg");
// 导入粗糙度贴图
const doorRoughness = textureLoader.load("./textures/door/roughness.jpg");
// 导入金属贴图
const doorMetalness = textureLoader.load("./textures/door/metalness.jpg");
// 导入法线贴图
const doorNormal = textureLoader.load("./textures/door/normal.jpg");
// 材质
const standardMaterial = new THREE.MeshStandardMaterial({
color: "#ffff00", // 设置颜色
map: door, // 设置纹理
alphaMap: doorAlpha, // 设置纹理透明背景
transparent: true, // 允许透明的属性, 为true才可以透明
// opacity: 0.5 // 设置纹理透明度, 类似css中的背景图透明度设置
side: DoubleSide, // 设置渲染哪一面 DoubleSide: 渲染两面
aoMap: doorTietu, // 设置贴图(贴图就是给纹理再加上一个背景贴图)
aoMapIntensity: 0.5, // ao贴图的强度设置
displacementMap: doorDeep, // 设置置换贴图, 使其具有深度上的效果
displacementScale: 0.05, // 置换贴图的影响强度
roughness: 0, // 设置粗糙度, 0: 非常光滑, 1: 非常粗糙
roughnessMap: doorRoughness, // 设置粗糙度贴图(贴图内颜色越接近黑色的部分越光滑)
metalness: 0.5, // 设置金属度, 0: 不像金属, 1: 像金属
metalnessMap: doorMetalness, // 设置金属贴图
normalMap: doorNormal, // 设置法线贴图
});
// 组合几何体和材质
const cube = new THREE.Mesh(cubeGeometry, standardMaterial);
// 给cube设置贴图的uv
cubeGeometry.setAttribute(
"uv2",
new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
);
// 把几何体添加到场景中
scene.add(cube);
// 添加一个平面(材质还是用上边的透明纹理)
const plane = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), standardMaterial);
plane.position.set(3, 0, 0);
scene.add(plane);
// 创建环境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // 0.9: 光线强度,默认是1
// 将环境光添加到场景中
scene.add(light);
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置灯光位置
directionalLight.position.set(10, 10, 10);
// 将平行光添加到场景中
scene.add(directionalLight);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
roughness.jpg:
metalness.jpg:
normal.jpg:
粗糙贴图效果:
金属贴图效果:
法线贴图效果:
8.纹理加载进度
import * as THREE from "three";
import { DoubleSide } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 添加物体
// 创建一个几何体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 100, 100, 100);
// 设置加载管理器(除了纹理,包括模型等都可以进行管理)
const loadingManager = new THREE.LoadingManager();
loadingManager.onStart = function (url, itemsLoaded, itemsTotal) {
console.log("开始加载...", url, itemsLoaded, itemsTotal);
};
loadingManager.onProgress = function (url, itemsLoaded, itemsTotal) {
console.log("加载中...", url, itemsLoaded, itemsTotal);
};
loadingManager.onLoad = function () {
console.log("开始完成...");
};
loadingManager.onError = function (url) {
console.log("开始出错...", url);
};
// 导入纹理加载器
const textureLoader = new THREE.TextureLoader(loadingManager);
// 导入一张纹理
const door = textureLoader.load("./textures/door/door.jpg");
// 导入透明纹理背景图
const doorAlpha = textureLoader.load("./textures/door/color.jpg");
// 导入遮挡贴图
const doorTietu = textureLoader.load("./textures/door/tietu.jpg");
// 导入置换贴图
const doorDeep = textureLoader.load("./textures/door/deep.jpg");
// 导入粗糙度贴图
const doorRoughness = textureLoader.load("./textures/door/roughness.jpg");
// 导入金属贴图
const doorMetalness = textureLoader.load("./textures/door/metalness.jpg");
// 导入法线贴图
const doorNormal = textureLoader.load("./textures/door/normal.jpg");
// 材质
const standardMaterial = new THREE.MeshStandardMaterial({
color: "#ffff00", // 设置颜色
map: door, // 设置纹理
alphaMap: doorAlpha, // 设置纹理透明背景
transparent: true, // 允许透明的属性, 为true才可以透明
// opacity: 0.5 // 设置纹理透明度, 类似css中的背景图透明度设置
side: DoubleSide, // 设置渲染哪一面 DoubleSide: 渲染两面
aoMap: doorTietu, // 设置贴图(贴图就是给纹理再加上一个背景贴图)
aoMapIntensity: 0.5, // ao贴图的强度设置
displacementMap: doorDeep, // 设置置换贴图, 使其具有深度上的效果
displacementScale: 0.05, // 置换贴图的影响强度
roughness: 0, // 设置粗糙度, 0: 非常光滑, 1: 非常粗糙
roughnessMap: doorRoughness, // 设置粗糙度贴图(贴图内颜色越接近黑色的部分越光滑)
metalness: 0.5, // 设置金属度, 0: 不像金属, 1: 像金属
metalnessMap: doorMetalness, // 设置金属贴图
normalMap: doorNormal, // 设置法线贴图
});
// 组合几何体和材质
const cube = new THREE.Mesh(cubeGeometry, standardMaterial);
// 给cube设置贴图的uv
cubeGeometry.setAttribute(
"uv2",
new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
);
// 把几何体添加到场景中
scene.add(cube);
// 添加一个平面(材质还是用上边的透明纹理)
const plane = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), standardMaterial);
plane.position.set(3, 0, 0);
scene.add(plane);
// 创建环境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // 0.9: 光线强度,默认是1
// 将环境光添加到场景中
scene.add(light);
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置灯光位置
directionalLight.position.set(10, 10, 10);
// 将平行光添加到场景中
scene.add(directionalLight);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
9.环境贴图与背景贴图
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// RGBELoader加载器, 可用于导入rgbe或者hdr...等图片类型文件
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 导入环境贴图
const envTextures = new THREE.CubeTextureLoader()
.setPath("textures/cubeMaps/")
.load(["1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg", "6.jpg"]);
// 创建球星几何体
const geometry = new THREE.SphereGeometry(1, 20, 20);
// 创建标准网格材质
const material = new THREE.MeshStandardMaterial({
metalness: 0.7,
roughness: 0.1,
// envMap: envTextures, // 环境纹理贴图(设置方式1)
});
// 给场景设置背景贴图 (设置方式1)
// scene.background = envTextures;
// 异步导入hdr类型的环境贴图(设置方式2)
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("textures/hdr/1.hdr").then((texture) => {
// 设置纹理的映射方式 - 像地球一样映射
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = texture; // 设置背景纹理
scene.environment = texture; // 设置环境纹理
});
// 将材质和几何体
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
// 创建环境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // 0.9: 光线强度,默认是1
// 将环境光添加到场景中
scene.add(light);
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置灯光位置
directionalLight.position.set(10, 10, 10);
// 将平行光添加到场景中
scene.add(directionalLight);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
效果图:
10.灯光与阴影
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// RGBELoader加载器, 可用于导入rgbe或者hdr...等图片类型文件
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
/**
* 灯光与阴影
* 1. 材质要满足能够对光照反应
* 2. 设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;
* 3. 设置光照投射阴影 directionalLight.castShadow = true;
* 4. 设置物体投射阴影 sphere.castShadow = true;
* 5. 设置物体接收阴影 plane.receiveShadow = true;
*/
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 创建球星几何体
const geometry = new THREE.SphereGeometry(1, 20, 20);
// 创建标准网格材质
const material = new THREE.MeshStandardMaterial();
// 异步导入hdr类型的环境贴图(设置方式2)
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("textures/hdr/1.hdr").then((texture) => {
// 设置纹理的映射方式 - 像地球一样映射
texture.mapping = THREE.EquirectangularReflectionMapping;
});
// 将材质和几何体
const sphere = new THREE.Mesh(geometry, material);
// 设置物体投射阴影
sphere.castShadow = true;
scene.add(sphere);
// 添加一个平面
const planeGeometry = new THREE.PlaneGeometry(10, 10);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 设置物体接收阴影
plane.receiveShadow = true;
scene.add(plane);
// 创建环境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // 0.9: 光线强度,默认是1
// 将环境光添加到场景中
scene.add(light);
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置灯光位置
directionalLight.position.set(10, 10, 10);
// 设置光照投射阴影
directionalLight.castShadow = true;
// 将平行光添加到场景中
scene.add(directionalLight);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 开始场景中的阴影贴图
renderer.shadowMap.enabled = true;
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
效果图:
11.平行光阴影属性及相机原理
import * as dat from "dat.gui"; // 导入可视化控制器
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// RGBELoader加载器, 可用于导入rgbe或者hdr...等图片类型文件
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
/**
* 平行灯光与阴影
* 1. 材质要满足能够对光照反应
* 2. 设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;
* 3. 设置光照投射阴影 directionalLight.castShadow = true;
* 4. 设置物体投射阴影 sphere.castShadow = true;
* 5. 设置物体接收阴影 plane.receiveShadow = true;
*/
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 创建球星几何体
const geometry = new THREE.SphereGeometry(1, 20, 20);
// 创建标准网格材质
const material = new THREE.MeshStandardMaterial({
// metalness: 0.7,
// roughness: 0.1,
});
// 异步导入hdr类型的环境贴图(设置方式2)
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("textures/hdr/1.hdr").then((texture) => {
// 设置纹理的映射方式 - 像地球一样映射
texture.mapping = THREE.EquirectangularReflectionMapping;
// scene.background = texture; // 设置背景纹理
// scene.environment = texture; // 设置环境纹理
});
// 将材质和几何体
const sphere = new THREE.Mesh(geometry, material);
// 设置物体投射阴影
sphere.castShadow = true;
scene.add(sphere);
// 添加一个平面
const planeGeometry = new THREE.PlaneGeometry(10, 10);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 设置物体接收阴影
plane.receiveShadow = true;
scene.add(plane);
// 创建环境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // 0.9: 光线强度,默认是1
// 将环境光添加到场景中
scene.add(light);
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置灯光位置
directionalLight.position.set(5, 5, 5);
// 设置光照投射阴影
directionalLight.castShadow = true;
// 设置阴影贴图模糊度
directionalLight.shadow.radius = 20;
// 设置阴影贴图分辨率
directionalLight.shadow.mapSize.set(2048, 2048); // 值越高越清晰
// 设置平行光投射像机的属性
directionalLight.shadow.camera.near = 0.5; // 近端
directionalLight.shadow.camera.far = 500; // 远端
directionalLight.shadow.camera.top = 5; // 上
directionalLight.shadow.camera.bottom = -5;
directionalLight.shadow.camera.left = -5;
directionalLight.shadow.camera.right = 5;
// 将平行光添加到场景中
scene.add(directionalLight);
const gui = new dat.GUI();
gui
.add(directionalLight.shadow.camera, "near")
.min(0)
.max(10)
.step(0.1)
.onChange(() => {
directionalLight.shadow.camera.updateProjectionMatrix();
});
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 开始场景中的阴影贴图
renderer.shadowMap.enabled = true;
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
效果贴图:
12.聚光灯各种属性与应用
import * as dat from "dat.gui"; // 导入可视化控制器
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// RGBELoader加载器, 可用于导入rgbe或者hdr...等图片类型文件
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
/**
* 聚光灯
*/
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 创建球星几何体
const geometry = new THREE.SphereGeometry(1, 20, 20);
// 创建标准网格材质
const material = new THREE.MeshStandardMaterial({
// metalness: 0.7,
// roughness: 0.1,
});
// 异步导入hdr类型的环境贴图(设置方式2)
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("textures/hdr/1.hdr").then((texture) => {
// 设置纹理的映射方式 - 像地球一样映射
texture.mapping = THREE.EquirectangularReflectionMapping;
// scene.background = texture; // 设置背景纹理
// scene.environment = texture; // 设置环境纹理
});
// 将材质和几何体
const sphere = new THREE.Mesh(geometry, material);
// 设置物体投射阴影
sphere.castShadow = true;
scene.add(sphere);
// 添加一个平面
const planeGeometry = new THREE.PlaneGeometry(50, 50);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 设置物体接收阴影
plane.receiveShadow = true;
scene.add(plane);
// 创建环境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // 0.9: 光线强度,默认是1
// 将环境光添加到场景中
scene.add(light);
// 创建聚光灯
const spotLight = new THREE.SpotLight(0xffffff, 1);
// 设置灯光亮度
spotLight.intensity = 2;
// 设置灯光位置
spotLight.position.set(5, 5, 5);
// 设置光照投射阴影
spotLight.castShadow = true;
// 设置阴影贴图模糊度
spotLight.shadow.radius = 20;
// 设置阴影贴图分辨率
spotLight.shadow.mapSize.set(2048, 2048); // 值越高越清晰
// 设置投射目标(随着物体移动进行打光)
spotLight.target = sphere;
// 设置聚光灯的角度
spotLight.angle = Math.PI / 6; // (不要超过90°Math.PI / 2)
// 设置聚光灯能照多远(越远越暗)
spotLight.distance = 50;
// 聚光锥的半阴影效果(值为0 - 1, 默认0, 值越大阴影越小越暗, 就越像真实的聚光灯)
spotLight.penumbra = 0;
// 设置沿着光照距离的衰减量
spotLight.decay = 2;
// 设置透视相机的属性
spotLight.shadow.camera.near = 500; // 近端
spotLight.shadow.camera.far = 4000; // 远端
spotLight.shadow.camera.fov = 30; // 角度
// 将聚光灯添加到场景中
scene.add(spotLight);
const gui = new dat.GUI();
gui.add(sphere.position, "x").min(-5).max(5).step(0.1);
gui
.add(spotLight, "angle")
.min(0)
.max(Math.PI / 2)
.step(0.01);
gui.add(spotLight, "distance").min(0).max(100).step(0.01);
gui.add(spotLight, "penumbra").min(0).max(1).step(0.01);
gui.add(spotLight, "decay").min(0).max(5).step(0.01);
gui.add(spotLight, "intensity").min(0).max(2).step(0.01);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 开始场景中的阴影贴图
renderer.shadowMap.enabled = true;
// 使用物理上正确的光照模式(与decay有关)
renderer.useLegacyLights = true;
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 封装渲染函数
function render() {
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
效果图:
13.点光源各种属性与应用
import * as dat from "dat.gui"; // 导入可视化控制器
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// RGBELoader加载器, 可用于导入rgbe或者hdr...等图片类型文件
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
/**
* 点光源
*/
// 创建一个场景
const scene = new THREE.Scene();
// 创建一个相机(透视相机)
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机的位置(x, y, z)
camera.position.set(0, 0, 10);
// 把相机添加到场景中
scene.add(camera);
// 创建球星几何体
const geometry = new THREE.SphereGeometry(1, 20, 20);
// 创建标准网格材质
const material = new THREE.MeshStandardMaterial();
// 异步导入hdr类型的环境贴图(设置方式2)
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("textures/hdr/1.hdr").then((texture) => {
// 设置纹理的映射方式 - 像地球一样映射
texture.mapping = THREE.EquirectangularReflectionMapping;
// scene.background = texture; // 设置背景纹理
// scene.environment = texture; // 设置环境纹理
});
// 将材质和几何体
const sphere = new THREE.Mesh(geometry, material);
// 设置物体投射阴影
sphere.castShadow = true;
scene.add(sphere);
// 添加一个平面
const planeGeometry = new THREE.PlaneGeometry(50, 50);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 设置物体接收阴影
plane.receiveShadow = true;
scene.add(plane);
// 创建环境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // 0.9: 光线强度,默认是1
// 将环境光添加到场景中
scene.add(light);
// 创建一个小球
const smallBall = new THREE.Mesh(
new THREE.SphereGeometry(0.1, 20, 20),
new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
// 设置小球的位置
smallBall.position.set(2, 2, 2);
// 创建点光源
const pointLight = new THREE.PointLight(0xff0000, 1);
// 设置灯光亮度
pointLight.intensity = 2;
// 设置灯光位置
// pointLight.position.set(2, 2, 2);
// 设置光照投射阴影
pointLight.castShadow = true;
// 设置阴影贴图模糊度
pointLight.shadow.radius = 20;
// 设置阴影贴图分辨率
pointLight.shadow.mapSize.set(2048, 2048); // 值越高越清晰
// 设置点光源能照多远(越远越暗)
pointLight.distance = 50;
// 设置沿着光照距离的衰减量
pointLight.decay = 2;
// 设置透视相机的属性
// pointLight.shadow.camera.near = 500; // 近端
// pointLight.shadow.camera.far = 4000; // 远端
// pointLight.shadow.camera.fov = 30; // 角度
// 将点光源添加到小球上
smallBall.add(pointLight);
// 将点光源添加到场景中 - 将发光的小球添加到场景中
scene.add(smallBall);
const gui = new dat.GUI();
gui.add(pointLight.position, "x").min(-5).max(5).step(0.1);
gui.add(pointLight, "distance").min(0).max(100).step(1);
gui.add(pointLight, "decay").min(0).max(5).step(0.01);
gui.add(pointLight, "intensity").min(0).max(2).step(0.01);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 开始场景中的阴影贴图
renderer.shadowMap.enabled = true;
// 使用物理上正确的光照模式(与decay有关)
renderer.useLegacyLights = true;
// 将webgl渲染的canvas内容添加到body当中
document.body.append(renderer.domElement);
// 创建轨道控制器(围绕的相机, 渲染器)
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼, 使其更加逼真, 比如具有惯性
controls.enableDamping = true; // 每次更新都要update
// 给场景添加坐标抽辅助线(x,y,z)
const axesHelper = new THREE.AxesHelper(5, 5, 5);
scene.add(axesHelper);
// 设置时钟
const clock = new THREE.Clock();
// 封装渲染函数
function render() {
let time = clock.getElapsedTime();
smallBall.position.x = Math.sin(time) * 3; // 直线运动
smallBall.position.z = Math.cos(time) * 3; // 圆周运动
// smallBall.position.y = Math.cos(time) * 3; // 旋转运动
smallBall.position.y = 2 + Math.sin(time * 10) / 2; // 跳跃运动
controls.update();
// 使用渲染器, 通过相机将场景渲染出来
renderer.render(scene, camera);
requestAnimationFrame(render);
}
// 默认渲染一下
render();
效果图: