THREE.JS中不同贴图的搭配使用

2,914 阅读5分钟

前言

本文主要介绍各种贴图在 THREE.JS 中的搭配使用,并通过完成一个小 demo 来加深理解。

在 THREE.JS 中,贴图、透明度贴图、环境贴图和高光贴图等不同类型的纹理可以配合使用,以实现更加复杂和细致的效果。为了更好地学习各种贴图的使用,我们将通过完成一个小 demo 来实践和探索。

demo效果:

image.png

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);

image.png

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);

效果:

image.png

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 中环境贴图的映射模式有哪些?

  1. THREE.CubeReflectionMapping:该映射模式将环境贴图作为一个立方体贴图,将六个面分别映射到对应的立方体面上,以模拟立方体环境映射和反射效果。

  2. THREE.CubeRefractionMapping:该映射模式与 THREE.CubeReflectionMapping 类似,但是它模拟的是折射效果,即将环境贴图中的物体看作透明的,经过物体的折射后反射到表面上。

  3. THREE.EquirectangularReflectionMapping:该映射模式将环境贴图作为一个全景图片,将图片映射到球体或半球体上,以模拟球形环境映射和反射效果。

  4. THREE.EquirectangularRefractionMapping:该映射模式与 THREE.EquirectangularReflectionMapping 类似,但是模拟的是折射效果,即将环境贴图中的物体看作透明的,经过物体的折射后反射到表面上。

  5. THREE.SphericalReflectionMapping:该映射模式将环境贴图映射到一个球形贴图上,以模拟球形环境映射和反射效果。与 THREE.EquirectangularReflectionMapping 相比,该映射模式需要使用一个球形贴图,因此对图像质量的要求较高,但可以实现更加真实的球形反射效果。

3. 设置透明度贴图

透明度贴图一般长这样:

image.png 在透明度贴图中,黑色表示完全不透明的区域,白色表示完全透明的区域,灰色表示不同程度的半透明区域。

// 透明度贴图
let alphaMap = textureLoader.load("./texture/door/height.jpg");
let planeMaterial = new THREE.MeshBasicMaterial({
  color: 0xffffff,
  map: texture,
  // 允许透明
  transparent: true,
  // 透明度贴图
  alphaMap: alphaMap,
});

效果:

image.png

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,
});

image.png

5. 设置光照贴图

光照贴图用于控制对象表面的光照强度和位置,通常使用灰度图像来表示不同的光照强度值。光照贴图可以让对象表面看起来更加真实,增强细节和立体感。

我们的光照贴图长这样:

image.png

// 光照贴图
let lightMap = textureLoader.load("./texture/colors.png");
let planeMaterial = new THREE.MeshBasicMaterial({
  color: 0xffffff,
  map: texture,
  // 允许透明
  transparent: true,
  // 设置光照贴图
  lightMap: lightMap,
});

image.png

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("高光强度");