Three.js材质(纹理贴图Texture)

博客围绕Three.js展开,介绍了纹理的偏移、旋转、重复等特性,以及纹理显示清晰度和透明处理。详细讲解了PBR物理渲染,包括位移、粗糙、金属感、法线等贴图。还提及加载管理器、环境纹理和360°环境贴图加载,用于全景看房,最后给出获取纹理贴图的途径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
const textureLoader = new THREE.TextureLoader() // 纹理加载器(实际是一个图片加载器)
const texture = textureLoader.load('./c4965b97abab46118cb221b818bc74a5.png') // 导入纹理
const material = new THREE.MeshBasicMaterial({
 map: texture // 颜色贴图
}); // 基础网格材质
const cube = new THREE.Mesh(geometry, material)
scene.add(cube)

纹理偏移

在这里插入图片描述

texture.offset.x = 0.5 // 向左偏移,负为右偏移
texture.offset.y = 0.5 // 向下偏移,负为向上
texture.offset.set(0.5, 0.5)

纹理旋转

在这里插入图片描述在这里插入图片描述

texture.center.set(0.5, 0.5) // 设置旋转中心点,默认为 (0, 0)左下角
texture.rotation = Math.PI / 4 // 逆时针旋转45°

纹理重复

在这里插入图片描述

texture.repeat.set(2, 3) // 水平重复2次,竖着重复3次
// 设置纹理重复的模式 (默认是将重复的纹理推至外部边缘)
texture.wrapS = THREE.MirroredRepeatWrapping // 水平贴图,镜像重复
texture.wrapT = THREE.RepeatWrapping // 垂直贴图,纹理重复到无穷大

纹理显示的清晰度

在这里插入图片描述

// 放大滤镜和缩小滤镜(通过算法实现)
// 比方说图片大小是10px,显示的几何是100px,此时一个实际像素需要覆盖多个纹理像素,则用到放大滤镜magFilter
texture.minFilter = THREE.NearestFilter // 默认是.LinearFilter;它会对离采样点最近的几个纹理像素的颜色值进行加权平均
texture.magFilter = THREE.NearestFilter // 取离采样点最近的纹理像素的颜色值作为最终的颜色

纹理透明,环境遮挡贴图(模拟物体之间所产生的阴影的贴图)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

// 导入纹理
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load('./c4965b97abab46118cb221b818bc74a5.png')
const aplhaTexture = textureLoader.load('./44add4748d2b47e8bfa7e58cd2545981.jpeg')
const aoTexture = textureLoader.load('./26ad6804f422468988c3de6fe003bd6a.jpeg')

const geometry = new THREE.BoxGeometry(1, 1, 1);
// 设置第二组UV,新版本好像用不上了
// geometry.setAttribute(
//   "uv2", // 第二个uv
//   new THREE.BufferAttribute(planeGeometry.attributes.uv.array, 2), // 取原uv数组,设置为第二组坐标
// )
const material = new THREE.MeshBasicMaterial({
  // color: 0xff0000,//0xff0000设置材质颜色为红色
  map: texture, // 颜色贴图
  alphaMap: aplhaTexture, // 灰度纹理贴图 (黑色显示透明【看不见】,白色不透明)
  transparent: true,
  // opacity: 0.8, // 整体透明度
  side: THREE.DoubleSide, // 因为性能原因默认只渲染正面,设置可以显示背面
  aoMap: aoTexture, // 环境遮挡贴图:模拟物体之间的阴影交互,增加体积感和真实感;需要第二组UV
  aoMapIntensity: 0.8, // 遮挡强度默认为1,很黑
});
// material.side = THREE.DoubleSide // 里面的属性可在构建时设置,也可以之后通过.的形式来设置
const cube = new THREE.Mesh(geometry, material)
scene.add(cube)
</script>

详解PBR物理渲染

实现PBR标准的材质:MeshStandardMaterial

位移贴图

注意顶点数量需要给多一些,不然体现不出来效果。
在这里插入图片描述
在这里插入图片描述

// 场景
const scene = new THREE.Scene();

// 模型
// 顶点着色器
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 100, 100, 100);
// 片元着色器
// 导入纹理
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load('./c4965b97abab46118cb221b818bc74a5.png')
const aplhaTexture = textureLoader.load('/44add4748d2b47e8bfa7e58cd2545981.jpeg')
const aoTexture = textureLoader.load('./26ad6804f422468988c3de6fe003bd6a.jpeg')
const heightTexture = textureLoader.load('./178dba688dde40558095c585f1bf6cbe.jpeg')

const cubeMaterial = new THREE.MeshStandardMaterial({
  color: 0xffff00,
  map: texture,
  alphaMap: aplhaTexture,
  transparent: true,
  side: THREE.DoubleSide, // 因为性能原因默认只渲染正面
  aoMap: aoTexture, // 环境遮挡贴图;需要第二组UV
  displacementMap: heightTexture, // 设置位移贴图
  displacementScale: 0.1 // 影响程度,默认为1; 黑色无位移,白色是最大位移
});
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// console.log(cube);

scene.add(cube);

// 环境光
const light = new THREE.AmbientLight(0xffffff, 1)
scene.add(light)
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.9)
directionalLight.position.set(2, 2, 2) // target默认为(0, 0, 0)
scene.add(directionalLight)
</script>

粗糙贴图

在这里插入图片描述
在这里插入图片描述

// 模型
// 顶点着色器
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 100, 100, 100);
// 片元着色器
// 导入纹理
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load('./c4965b97abab46118cb221b818bc74a5.png')
const aplhaTexture = textureLoader.load('/44add4748d2b47e8bfa7e58cd2545981.jpeg')
const aoTexture = textureLoader.load('./26ad6804f422468988c3de6fe003bd6a.jpeg')
const heightTexture = textureLoader.load('./178dba688dde40558095c585f1bf6cbe.jpeg')
const roughnessTexture = textureLoader.load('./e35ed3d8a9d54ca0bf1b615a077274b1.jpeg')

const cubeMaterial = new THREE.MeshStandardMaterial({
  color: 0xffff00,
  map: texture,
  alphaMap: aplhaTexture,
  transparent: true,
  side: THREE.DoubleSide, // 因为性能原因默认只渲染正面
  aoMap: aoTexture, // 环境遮挡贴图;需要第二组UV
  displacementMap: heightTexture, // 设置置换贴图
  displacementScale: 0.1, // 置换贴图影响程度,默认为1; 黑色无位移,白色是最大位移
  // roughness: 0.5, // 设置材质的粗糙程度,默认为1.0。 0.0镜面反射,1.0完全漫反射
  roughnessMap: roughnessTexture // 如果已设置粗糙度,则会2个数值相乘(黑色光滑,白色粗糙)
});
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// console.log(cube);

scene.add(cube);

// 环境光
const light = new THREE.AmbientLight(0xffffff, 1)
scene.add(light)
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.9)
directionalLight.position.set(2, 2, 2) // target默认为(0, 0, 0)
scene.add(directionalLight)

金属感贴图

在这里插入图片描述
在这里插入图片描述

// 模型
// 顶点着色器
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 100, 100, 100);
// 片元着色器
// 导入纹理
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load('./c4965b97abab46118cb221b818bc74a5.png')
const aplhaTexture = textureLoader.load('/44add4748d2b47e8bfa7e58cd2545981.jpeg')
const aoTexture = textureLoader.load('./26ad6804f422468988c3de6fe003bd6a.jpeg')
const heightTexture = textureLoader.load('./178dba688dde40558095c585f1bf6cbe.jpeg')
const roughnessTexture = textureLoader.load('./e35ed3d8a9d54ca0bf1b615a077274b1.jpeg')
const metalnessTexture = textureLoader.load('./10a429ee358849a9aaafeb3e5817641b.jpeg')

const cubeMaterial = new THREE.MeshStandardMaterial({
  color: 0xffff00,
  map: texture,
  alphaMap: aplhaTexture,
  transparent: true,
  side: THREE.DoubleSide, // 因为性能原因默认只渲染正面
  aoMap: aoTexture, // 环境遮挡贴图;需要第二组UV
  displacementMap: heightTexture, // 设置置换贴图
  displacementScale: 0.1, // 置换贴图影响程度,默认为1; 黑色无位移,白色是最大位移
  roughnessMap: roughnessTexture, // 如果已设置粗糙度,则会2个数值相乘(黑色光滑,白色粗糙)
  metalness: 1, // 金属感默认为0.0, 0为木材或石材,1为金属
  metalnessMap: metalnessTexture,
});
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// console.log(cube);

scene.add(cube);

// 环境光
const light = new THREE.AmbientLight(0xffffff, 1)
scene.add(light)
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.9)
directionalLight.position.set(2, 2, 2) // target默认为(0, 0, 0)
scene.add(directionalLight)

法线贴图(模拟物体表面凹凸细节,增强光照效果)

不同颜色代表不同的光照方向和反射效果

  • 红色(R)代表x轴方向
  • 绿色(G)代表y轴方向
  • 蓝色(B)代表z轴方向
    在这里插入图片描述在这里插入图片描述
// 模型
// 顶点着色器
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 100, 100, 100);
// 片元着色器
// 导入纹理
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load('./c4965b97abab46118cb221b818bc74a5.png')
const aplhaTexture = textureLoader.load('/44add4748d2b47e8bfa7e58cd2545981.jpeg')
const aoTexture = textureLoader.load('./26ad6804f422468988c3de6fe003bd6a.jpeg')
const heightTexture = textureLoader.load('./178dba688dde40558095c585f1bf6cbe.jpeg')
const roughnessTexture = textureLoader.load('./e35ed3d8a9d54ca0bf1b615a077274b1.jpeg')
const metalnessTexture = textureLoader.load('./10a429ee358849a9aaafeb3e5817641b.jpeg')
const normalTexture = textureLoader.load('./f9fec9a6991242c38a0ab3197a4a82df.jpeg')

const cubeMaterial = new THREE.MeshStandardMaterial({
  color: 0xffff00,
  map: texture,
  alphaMap: aplhaTexture,
  transparent: true,
  side: THREE.DoubleSide, // 因为性能原因默认只渲染正面
  aoMap: aoTexture, // 环境遮挡贴图;需要第二组UV
  displacementMap: heightTexture, // 设置置换贴图
  displacementScale: 0.1, // 置换贴图影响程度,默认为1; 黑色无位移,白色是最大位移
  roughnessMap: roughnessTexture, // 如果已设置粗糙度,则会2个数值相乘(黑色光滑,白色粗糙)
  metalnessMap: metalnessTexture,
  normalMap: normalTexture // 法线贴图,每个颜色代表不一样的朝向
});
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// console.log(cube);

scene.add(cube);

// 环境光
const light = new THREE.AmbientLight(0xffffff, 1)
scene.add(light)
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.9)
directionalLight.position.set(2, 2, 2) // target默认为(0, 0, 0)
scene.add(directionalLight)

加载管理器

单张纹理图的加载

function onLoad(texture) {
	// 加载完成时调用的函数
}
function onProgress(xhr) {
	// 加载进度更新时调用的函数
	const percentComplete = (xhr.loaded / xhr.total * 100);
	console.log(`Progress: ${Math.round(percentComplete)}%`);
}
function onError(error) {
	// 加载失败时调用的函数
}
const textureLoader = new THREE.TextureLoader();
textureLoader.load(
    'path/to/your/texture.jpg', // 替换为你的纹理文件路径
    onLoad,
    onProgress,
    onError
);

加载管理器(可以用来管理纹理、模型等加载)

<script setup>
const div = document.createElement('div')
div.style.width = '200px'
div.style.height = '200px'
div.style.color = '#ffffff'
div.style.position = 'fixed'
div.style.top = '0'
div.style.right = '0'
div.style.textAlign = 'right'
document.body.append(div)
let progress = ''

const manager = new THREE.LoadingManager(
  () => {
    console.log('加载完成');
  },
  (url, itemsLoaded, itemsTotal) => {
    console.log(url, itemsLoaded, itemsTotal);
    console.log((itemsLoaded / itemsTotal * 100).toFixed(2) + '%');
    progress = (itemsLoaded / itemsTotal * 100).toFixed(2) + '%' // 四舍五入,输出字符串
    div.innerText = progress
  },
  () => {
    console.log('报错');
  },
); // 或通过.onStart, .onLoad, .onProgress, .onError来设置

// 导入管理器
const textureLoader = new THREE.TextureLoader(manager)
</script>

环境纹理

将环境显示在物体上
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// 设置cube纹理加载器
const cubeTextureLoader = new THREE.CubeTextureLoader()
const envMapTexture = cubeTextureLoader.load([ // 6个面,还可以使用.hdr文件
  "./textures/environmentMaps/1/px.jpg",
  "./textures/environmentMaps/1/nx.jpg",
  "./textures/environmentMaps/1/py.jpg",
  "./textures/environmentMaps/1/ny.jpg",
  "./textures/environmentMaps/1/pz.jpg",
  "./textures/environmentMaps/1/nz.jpg"
])

// 添加物体
const sphereGeometry = new THREE.SphereGeometry(1, 20, 20) // 球形几何体
const material = new THREE.MeshStandardMaterial({
  metalness: 0.7, // 材质与金属的相似度。非金属材质,如木材或石材,使用0.0,金属使用1.0。 默认值为0.0 
  roughness: 0.1, // 材质的粗糙程度。0.0表示平滑的镜面反射,1.0表示完全漫反射。
  // envMap: envMapTexture, // 环境贴图,也可在场景中设置
})//材质

const sphere = new THREE.Mesh(sphereGeometry, material)
scene.add(sphere)
// 给场景添加背景
scene.background = envMapTexture
// 给场景所有的物体添加默认的环境贴图
scene.environment = envMapTexture

// 灯光
// 环境光(四面八方)
const light = new THREE.AmbientLight(0xffffff, 0.5); // soft white light
scene.add(light);
// 直线光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(10, 10, 10)
scene.add(directionalLight);

加载360°环境贴图

const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("textures/hdr/002.hdr").then((texture) => {
  texture.mapping = THREE.EquirectangularReflectionMapping // 说明文件类型;.hdr文件(高动态范围技术, 它通过拍摄多张不同曝光的照片,然后使用软件将其合成一张图片,从而改善照片中过于明亮或昏暗的部分,获得更均衡的曝光效果)
  scene.background = texture
  scene.environment = texture
})

全景看房

在这里插入图片描述

<template>
  <div id="webgl"></div>
</template>

<script setup>
import * as THREE from 'three'
//导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// 导入 dat.gui
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

// 目标:点光源

const gui = new GUI();
//1.创建场景
const scene = new THREE.Scene()

//2.创建相机 角度  宽高比  近端  远端
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
// 设置相机位置  x y z 
camera.position.set(0, 0, 0.1)
// 把相机添加到场景中
scene.add(camera)

// 立方体
const geometry = new THREE.BoxGeometry(10, 10, 10)

// 纹理加载(1片1片的)
let arr = ['textures/px.jpeg', 'textures/nx.jpeg', 'textures/py.jpeg', 'textures/ny.jpeg', 'textures/pz.jpeg', 'textures/nz.jpeg']
let boxMaterials = []
arr.forEach(item => {
  let texture = new THREE.TextureLoader().load(item)
  // 可以旋转纹理
  // texture.rotation = Math.PI
  // texture.center = new THREE.Vector2(0.5, 0.5)
  boxMaterials.push(new THREE.MeshBasicMaterial({ map: texture }))
})
const cube = new THREE.Mesh(geometry, boxMaterials)
cube.geometry.scale(1, 1, -1)
scene.add(cube)

// 初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)

// 将webgel渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement)

// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
// 设置控制器的阻尼 更真实 惯性
controls.enableDamping = true

// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)


// 设置时钟
const clock = new THREE.Clock()

function render() {
  controls.update()
  // 使用渲染器,通过相机将场景渲染进来
  renderer.render(scene, camera);
  // 渲染下一帧的时候 调用 render函数
  requestAnimationFrame(render)
}
render()

// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
  // 更新摄像头
  camera.aspect = window.innerWidth / window.innerHeight
  // 更新摄像机的投影矩阵
  camera.updateProjectionMatrix()

  // 更新渲染器
  renderer.setSize(window.innerWidth, window.innerHeight)
  // 设置渲染器的像素比
  renderer.setPixelRatio(window.devicePixelRatio)
})

</script>

加载360°环境贴图

const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("textures/hdr/002.hdr").then((texture) => {
 //  texture.mapping = THREE.EquirectangularReflectionMapping // 说明文件类型,.hdr文件(高动态范围技术, 提升最亮和最暗画面的对比度)
  const material = new THREE.MeshBasicMaterial({ map: texture })
  const sphere = new THREE.Mesh(geometry, boxMaterials)
  sphere.geometry.scale(1, 1, -1) // 由外改内
  scene.add(sphere)
})

如何获取更多的纹理贴图

https://www.poliigon.com/
https://3dtextures.me/
https://www.arroway-textures.ch/
【Bridge】软件需下载https://quixel.com/bridge

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值