前言
本文主要介绍各种贴图在 THREE.JS 中的搭配使用,并通过完成一个小 demo 来加深理解。
在 THREE.JS 中,贴图、透明度贴图、环境贴图和高光贴图等不同类型的纹理可以配合使用,以实现更加复杂和细致的效果。为了更好地学习各种贴图的使用,我们将通过完成一个小 demo 来实践和探索。
demo效果:
demo实现
1. 先创建一个平面(PlaneGeometry)
let planeGeometry = new THREE.PlaneGeometry(1, 1);
let planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff
});
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(plane);
2. 给平面添加颜色贴图
添加颜色贴图要使用纹理加载器(TextureLoader),创建纹理加载器之后再加载纹理贴图.
// 创建纹理加载器
let textureLoader = new THREE.TextureLoader();
// 加载纹理
let texture = textureLoader.load(
"./texture/watercover/CityNewYork002_COL_VAR1_1K.png"
);
let planeGeometry = new THREE.PlaneGeometry(1, 1);
let planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
// 添加颜色贴图
map: texture,
// 允许透明(纹理贴图的透明部分不会被渲染出来)
transparent: true,
});
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(plane);
效果:
3. 添加环境贴图
这里我使用的是一个全景图作为环境贴图,所以需要使用全景图加载器(RGBELoader)
// 导入hdr加载器
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
// rgbeLoader 加载hdr贴图
let rgbeLoader = new RGBELoader();
rgbeLoader.load("./texture/Alex_Hart-Nature_Lab_Bones_2k.hdr", (envMap) => {
// 设置球形贴图映射模式
envMap.mapping = THREE.EquirectangularReflectionMapping;
// 设置环境贴图
scene.background = envMap;
// 设置环境贴图
scene.environment = envMap;
// 设置plane的环境贴图
planeMaterial.envMap = envMap;
});
其中需要注意的点是设置映射模式:envMap.mapping = THREE.EquirectangularReflectionMapping;
THREE.js 中环境贴图的映射模式有哪些?
-
THREE.CubeReflectionMapping:该映射模式将环境贴图作为一个立方体贴图,将六个面分别映射到对应的立方体面上,以模拟立方体环境映射和反射效果。 -
THREE.CubeRefractionMapping:该映射模式与THREE.CubeReflectionMapping类似,但是它模拟的是折射效果,即将环境贴图中的物体看作透明的,经过物体的折射后反射到表面上。 -
THREE.EquirectangularReflectionMapping:该映射模式将环境贴图作为一个全景图片,将图片映射到球体或半球体上,以模拟球形环境映射和反射效果。 -
THREE.EquirectangularRefractionMapping:该映射模式与THREE.EquirectangularReflectionMapping类似,但是模拟的是折射效果,即将环境贴图中的物体看作透明的,经过物体的折射后反射到表面上。 -
THREE.SphericalReflectionMapping:该映射模式将环境贴图映射到一个球形贴图上,以模拟球形环境映射和反射效果。与THREE.EquirectangularReflectionMapping相比,该映射模式需要使用一个球形贴图,因此对图像质量的要求较高,但可以实现更加真实的球形反射效果。
3. 设置透明度贴图
透明度贴图一般长这样:
在透明度贴图中,黑色表示完全不透明的区域,白色表示完全透明的区域,灰色表示不同程度的半透明区域。
// 透明度贴图
let alphaMap = textureLoader.load("./texture/door/height.jpg");
let planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
map: texture,
// 允许透明
transparent: true,
// 透明度贴图
alphaMap: alphaMap,
});
效果:
4. 设置高光贴图
高光贴图用于控制对象表面的高光反射强度和位置,通常使用灰度图像来表示不同的反射强度值。在高光贴图中,黑色表示完全不反射的区域,白色表示最大反射强度的区域,灰色表示不同程度的反射强度区域。
// 高光贴图
let specularMap = textureLoader.load(
"./texture/watercover/CityNewYork002_GLOSS_1K.jpg"
);
let planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
map: texture,
// 允许透明
transparent: true
// 设置高光贴图
specularMap: specularMap,
//设置反射强度
reflectivity: 0.5,
});
5. 设置光照贴图
光照贴图用于控制对象表面的光照强度和位置,通常使用灰度图像来表示不同的光照强度值。光照贴图可以让对象表面看起来更加真实,增强细节和立体感。
我们的光照贴图长这样:
// 光照贴图
let lightMap = textureLoader.load("./texture/colors.png");
let planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
map: texture,
// 允许透明
transparent: true,
// 设置光照贴图
lightMap: lightMap,
});
6. 设置ao贴图(环境遮挡贴图)
在 THREE.js 中,环境光遮蔽贴图(AO贴图)用于控制对象表面在环境光下的遮蔽程度,通常使用灰度图像来表示不同的遮蔽程度值。AO贴图可以让对象表面看起来更加真实,增强细节和立体感。
AO贴图中的灰度值表示该像素点在环境光下的遮蔽程度,黑色表示完全被遮蔽,白色表示没有遮蔽。
// 加载ao贴图
let aoMap = textureLoader.load("./texture/watercover/CityNewYork002_AO_1K.jpg");
let planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
map: texture,
// 允许透明
transparent: true,
// 设置ao贴图
aoMap: aoMap,
aoMapIntensity: 1,
});
总结
这里是这个小demo的完整代码,有兴趣的小伙盘可以在本地跑起来试试。如有错误之处,欢迎大家指出,谢谢大家了。
// 导入threejs
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 导入lil.gui
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
// 导入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 // 远平面
);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 设置相机位置
camera.position.z = 5;
camera.position.y = 2;
camera.position.x = 2;
camera.lookAt(0, 0, 0);
// 添加世界坐标辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// 添加轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置带阻尼的惯性
controls.enableDamping = true;
// 设置阻尼系数
controls.dampingFactor = 0.05;
// 设置旋转速度
// controls.autoRotate = true;
// 渲染函数
function animate() {
controls.update();
requestAnimationFrame(animate);
// 渲染
renderer.render(scene, camera);
}
animate();
// 监听窗口变化
window.addEventListener("resize", () => {
// 重置渲染器宽高比
renderer.setSize(window.innerWidth, window.innerHeight);
// 重置相机宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 更新相机投影矩阵
camera.updateProjectionMatrix();
});
let params = {};
// 创建GUI
const gui = new GUI();
// 创建纹理加载器
let textureLoader = new THREE.TextureLoader();
// 加载纹理
let texture = textureLoader.load(
"./texture/watercover/CityNewYork002_COL_VAR1_1K.png"
);
console.log(texture);
// 加载ao贴图
let aoMap = textureLoader.load("./texture/watercover/CityNewYork002_AO_1K.jpg");
// 透明度贴图
let alphaMap = textureLoader.load("./texture/door/height.jpg");
// 光照贴图
let lightMap = textureLoader.load("./texture/colors.png");
// 高光贴图
let specularMap = textureLoader.load(
"./texture/watercover/CityNewYork002_GLOSS_1K.jpg"
);
// rgbeLoader 加载hdr贴图
let rgbeLoader = new RGBELoader();
rgbeLoader.load("./texture/Alex_Hart-Nature_Lab_Bones_2k.hdr", (envMap) => {
// 设置球形贴图
envMap.mapping = THREE.EquirectangularReflectionMapping;
// 设置环境贴图
scene.background = envMap;
// 设置环境贴图
scene.environment = envMap;
// 设置plane的环境贴图
planeMaterial.envMap = envMap;
});
let planeGeometry = new THREE.PlaneGeometry(1, 1);
let planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
map: texture,
// 允许透明
transparent: true,
// // 设置ao贴图
aoMap: aoMap,
aoMapIntensity: 1,
// // 透明度贴图
// alphaMap: alphaMap,
// // 设置光照贴图
// lightMap: lightMap,
// // 设置高光贴图
specularMap: specularMap,
reflectivity: 0.5,
});
// planeMaterial.map = texture;
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(plane);
gui.add(planeMaterial, "aoMapIntensity").min(0).max(1).name("ao强度");
gui.add(planeMaterial, "reflectivity").min(0).max(1).name("高光强度");