1. 模型使用纹理贴图
const geometry = new THREE.BoxGeometry(10, 10, 10);
const textureLoader = new THREE.TextureLoader(); // 创建纹理贴图加载器
const texture = textureLoader.load("/crate.gif"); // 加载纹理贴图
const material = new THREE.MeshLambertMaterial({
map: texture,
side: THREE.DoubleSide, //两面可见
});
2. 加载外部gltf格式
GLTF(GL Transmission Format)
是一种高效、开放的3D文件格式,专为Web和移动端实时渲染而设计。GLTF文件格式旨在传输3D模型数据,具有快速加载、渲染效率高、支持丰富的材质和动画等优点,被称为“3D领域的JPEG”。
GLTF文件结构:
.gltf(JSON文件)
: 描述模型的主要结构,包括几何体、材质、动画、场景等。
.bin(二进制文件)
: 存储顶点数据、法线、UV坐标等二进制数据。
纹理(.png, .jpg): 存储模型使用的纹理贴图。
.glb(单文件格式)
: GLB是GLTF的二进制版本,将所有数据(JSON、二进制和纹理)合并到一个文件中,方便传输和使用。
可以用Blender软件导出绘制好的三维模型,也可以打开和预览gltf格式文件模型。
注意: 纹理贴图和gltf格式存放在public
目录下
// 创建GLTFLoader实例
const loader = new GLTFLoader();
// 加载.gltf文件
loader.load("/models/Parrot.glb", function (gltf) {
const model = gltf.scene;
// 修改模型的位置
model.position.set(0, 15, 0); // 设置为(x, y, z),可根据需要调整
// 修改模型的旋转
model.rotation.set(Math.PI / 4, Math.PI / 4, 0); // 设置旋转角度(弧度),如(x, y, z)
// 修改模型的缩放
model.scale.set(0.2, 0.2, 0.2); // 设置缩放比例 (x, y, z)
scene.add(model);
});
3. 光源辅助查看
1.点光源辅助查看:
PointLightHelper( light : PointLight, sphereSize : Float, color : Hex )
light – 要模拟的光源.
sphereSize – (可选的) 球形辅助对象的尺寸. 默认为 1.
color – (可选的) 如果没有赋值辅助对象将使用光源的颜色.
const pointLight = new THREE.PointLight( 0xff0000, 1, 100 );
pointLight.position.set( 10, 10, 10 );
scene.add( pointLight );
const sphereSize = 1;
const pointLightHelper = new THREE.PointLightHelper( pointLight, sphereSize );
scene.add( pointLightHelper );
2.平行光源辅助查看:
DirectionalLightHelper( light : DirectionalLight, size : Number, color : Hex )
light-- 被模拟的光源.
size – (可选的) 平面的尺寸. 默认为 1.
color – (可选的) 如果没有设置颜色将使用光源的颜色.
const light = new THREE.DirectionalLight( 0xFFFFFF );
const helper = new THREE.DirectionalLightHelper( light, 5 );
scene.add( helper );
4. 案例代码
<template>
<div class="wrapper">
<div ref="threeRef"></div>
</div>
</template>
<script setup lang="ts">
// 引入three.js
import * as THREE from "three";
// 引入扩展库OrbitControls.js
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
// 引入dat.gui.js的一个类GUI
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { onMounted, ref } from "vue";
const threeRef = ref();
// 模型1
const createMesh1 = () => {
const geometry = new THREE.BoxGeometry(10, 10, 10);
const textureLoader = new THREE.TextureLoader(); // create a texture loader.
const texture = textureLoader.load("/crate.gif"); // load a texture
const material = new THREE.MeshLambertMaterial({
// color: 0xff0000,
map: texture,
side: THREE.DoubleSide, //两面可见
});
return new THREE.Mesh(geometry, material);
};
// 模型2
const createMesh2 = () => {
const geometry = new THREE.BoxGeometry(3, 3, 3);
const textureLoader = new THREE.TextureLoader(); // create a texture loader.
const texture = textureLoader.load("/grid.png"); // load a texture
texture.repeat.set(2, 2); // 设置纹理的重复次数
texture.rotation = Math.PI / 4; // 旋转纹理(以弧度为单位)
texture.center.set(0.5, 0.5); // 设置旋转的中心
texture.center.set(0.5, 0.5); // 设置旋转的中心
const material = new THREE.MeshStandardMaterial({
map: texture,
});
return new THREE.Mesh(geometry, material);
};
// 添加光源
const createDictionLight = (target) => {
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 设置光源的方向:通过光源position属性和目标指向对象的position属性计算
directionalLight.position.set(10, 15, 25);
// 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
directionalLight.target = target;
return directionalLight;
};
// 添加渲染器
const createRenderer = (dom: HTMLElement) => {
const renderer = new THREE.WebGLRenderer({
antialias: true, // 设置锯齿属性,为了获得更好的图像质量
});
// 定义threejs输出画布的尺寸(单位:像素px)
renderer.setSize(window.innerWidth, window.innerHeight);
// 为了适应不同的硬件设备屏幕,设置设备像素比
renderer.setPixelRatio(window.devicePixelRatio);
// 插入到任意HTML元素中
dom.append(renderer.domElement);
return renderer;
};
// 响应式窗口处理
const onResize = (camera, renderer) => {
window.onresize = function () {
// 更新相机纵横比
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
// 更新渲染器的大小
renderer.setSize(window.innerWidth, window.innerHeight);
};
};
// 添加操作面板
const createGui = (mesh, light) => {
// 实例化一个gui对象
const gui = new GUI();
//设置操作面板位置
gui.domElement.style.right = "0px";
gui.domElement.style.width = "300px";
//添加光照强度,并使用name重命名,step设置步长
gui.add(light, "intensity", 0, 2.0).name("平行光强度").step(0.1);
// 添加颜色
gui
.addColor(
{
color: 0xff0000,
},
"color"
)
.name("颜色")
.onChange(function (value) {
mesh.material.color.set(value);
});
};
// 添加了一个相机控制插件,实现平移、旋转和缩放/推拉相以从任何角度查看场景
// 改变的实际上时相机的位置,并不是物体
const createControls = (scene, camera, renderer) => {
const controls = new OrbitControls(camera, renderer.domElement);
// 这个插件允许您
controls.addEventListener("change", function () {
renderer.render(scene, camera); //执行渲染操作
});
};
const init = () => {
//! 1.创建场景
// 创建3D场景对象Scene
const scene = new THREE.Scene();
scene.background = new THREE.Color("#c1c5d8"); // 设置场景颜色
// 物体
const mesh1 = createMesh1();
mesh1.position.set(0, 0, 0);
scene.add(mesh1); // 将模型添加到场景中
const mesh2 = createMesh2();
mesh2.position.set(0, 8, 0);
scene.add(mesh2);
//! 2.创建相机
// 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000:远裁截面
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
3000
);
camera.position.set(10, 10, 10); // 相机位置
camera.lookAt(mesh1.position); //指向mesh对应的位置
camera.lookAt(mesh2.position); //指向mesh对应的位置
// !AxesHelper:辅助观察的坐标系
// const axesHelper = new THREE.AxesHelper(20);
// scene.add(axesHelper);
//渲染
const renderer = createRenderer(threeRef.value);
renderer.render(scene, camera);
// 添加光源
const dictionLight = createDictionLight(mesh1);
// 将光源添加到场景中
scene.add(dictionLight);
// 查看平行光
const helper = new THREE.DirectionalLightHelper(dictionLight, 5);
scene.add(helper);
//环境光:没有特定方向,整体改变场景的光照明暗
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
// 设置相机控件轨道控制器
createControls(scene, camera, renderer);
// ! 创建循环动画,使物体可以动起来
function rotateRender() {
renderer.render(scene, camera); //执行渲染操作
mesh1.rotateY(0.01); //每次绕y轴旋转0.01弧度
mesh2.rotateX(0.01);
requestAnimationFrame(rotateRender); //请求再次执行渲染函数render,渲染下一帧
}
// 创建GLTFLoader实例
const loader = new GLTFLoader();
// 加载.gltf文件
loader.load("/models/Parrot.glb", function (gltf) {
const model = gltf.scene;
// 修改模型的位置
model.position.set(0, 15, 0); // 设置为(x, y, z),可根据需要调整
// 修改模型的旋转
model.rotation.set(Math.PI / 4, Math.PI / 4, 0); // 设置旋转角度(弧度),如(x, y, z)
// 修改模型的缩放
model.scale.set(0.2, 0.2, 0.2); // 设置缩放比例 (x, y, z)
scene.add(model);
});
rotateRender();
// 添加操作面板
createGui(mesh2, dictionLight);
onResize(camera, renderer);
};
onMounted(() => {
init();
});
</script>
<style scoped></style>
案例纹理图片:位置放在/public
下
https://github.com/mrdoob/three.js/blob/dev/examples/textures/crate.gif
案例gltf文件: 位置放在/public/models
下
https://github.com/mrdoob/three.js/blob/dev/examples/models/gltf/Parrot.glb