材质与纹理
使用纹理
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// 创建场景
const scene = new THREE.Scene()
// 创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
// 设置相机位置
camera.position.set(2, 2, 2)
// 将相机添加到场景
scene.add(camera)
// 加载纹理
const doorTexture = new THREE.TextureLoader().load(
'/src/assets/textures/door/color.jpg'
)
// 使用纹理进行材质创建
const material = new THREE.MeshBasicMaterial({ map: doorTexture })
// 创建几何体
const geometry = new THREE.BoxBufferGeometry()
// 根据几何体和材质创建物体
const cube = new THREE.Mesh(geometry, material)
// 将几何体添加到场景中
scene.add(cube)
// 初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement)
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
// 阻尼效果
controls.enableDamping = true
// 渲染函数
function render() {
renderer.render(scene, camera)
// 渲染下一帧的时候就会调用render函数
requestAnimationFrame(render)
// controls.update()
}
render()
纹理相关属性设置
偏移
取值:0.1 ~ 1.0
doorTexture.offset.set(-0.2, 0)
旋转
纹理将围绕中心点旋转多少度,单位为弧度(rad)。正值为逆时针方向旋转,默认值为0
doorTexture.rotation = 45
doorTexture.center.set(0.5, 0.5)
旋转中心点为(0.5, 0.5)对应纹理的正中心。默认值为(0,0),即左下角
重复
doorTexture.repeat.set(2, 3)
wrapS
这个值定义了纹理贴图在水平方向上将如何包裹,在 UV 映射中对应于U。 默认值是THREE.ClampToEdgeWrapping
,即纹理边缘将被推到外部边缘的纹素(纹理元素)。 其它的两个选项分别是THREE.RepeatWrapping
和THREE.MirroredRepeatWrapping
。
wrapT
这个值定义了纹理贴图在垂直方向上将如何包裹,在 UV 映射中对应于 V。和wrapS
使用相同的选项
doorTexture.repeat.set(2, 3)
doorTexture.wrapT = THREE.RepeatWrapping // 简单重复
doorTexture.wrapS = THREE.MirroredRepeatWrapping // 镜像重复
设置纹理显示算法与 mipmap
magFilter
当一个纹素覆盖大于一个像素时,贴图将如何采样:
// 纹理显示算法(物体像素大于纹理像素)
doorTexture.magFilter = THREE.NearestFilter
// 物体像素小于纹理像素
doorTexture.minFilter = THREE.LinearMipmapLinearFilter
Mipmap 详解(有无 Mipmap 区别、原理、优点、缺点、优化)
透明材质与透明纹理
问 chatGPT:threejs 中设置了透明纹理 alphaMap 为什么还需要设置 transparent ?
即使您将透明纹理(alphaMap)设置为非不透明,仍然需要设置 transparent
属性,以便将该材质与其他不透明材质进行混合时透明度起作用。如果您不将 transparent
属性设置为 true
,则透明纹理中的透明度信息将被忽略,该材质将不透明。设置 transparent
属性为 true
将启用混合,并且透明度将根据 alphaMap 中的透明度信息进行计算。因此,在使用具有 alphaMap 的纹理的情况下,您仍然需要设置 transparent
属性,以便正确地呈现透明效果。
.alphaMap
:用于控制整个纹理表面的不透明度(黑色:完全透明;白色:完全不透明)
.transparent
定义此材质是否透明。设置为true
时,通过设置材质的opacity
属性来控制材质透明的程度
side
定义需要渲染那一面,默认是正面
// 加载透明纹理
const alphaTexture = new THREE.TextureLoader().load(
'/src/assets/textures/door/alpha.jpg'
)
// 使用纹理进行材质创建
const material = new THREE.MeshBasicMaterial({
map: doorTexture,
alphaMap: alphaTexture,
transparent: true,
opacity: 0.5,
side: THREE.DoubleSide,
})
环境遮挡贴图与强度
aoMap
为环境遮挡贴图,它需要第二组UV
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// 创建场景
const scene = new THREE.Scene()
// 创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
// 设置相机位置
camera.position.set(2, 2, 2)
// 将相机添加到场景
scene.add(camera)
// 加载纹理
const doorTexture = new THREE.TextureLoader().load(
'/src/assets/textures/door/color.jpg'
)
// 加载透明纹理
const alphaTexture = new THREE.TextureLoader().load(
'/src/assets/textures/door/alpha.jpg'
)
// 加载环境遮挡纹理
const AoTexture = new THREE.TextureLoader().load(
'/src/assets/textures/door/ambientOcclusion.jpg'
)
// 使用纹理进行材质创建
const material = new THREE.MeshBasicMaterial({
map: doorTexture,
alphaMap: alphaTexture,
transparent: true,
aoMap: AoTexture,
side: THREE.DoubleSide,
})
// 创建几何体
const geometry = new THREE.BoxBufferGeometry()
// 设置第二组uv
// BufferAttribute用于存储与BufferGeometry相关联的 attribute,利用 BufferAttribute,可以更高效的向GPU传递数据
geometry.setAttribute(
'uv2',
new THREE.BufferAttribute(geometry.attributes.uv.array, 2)
)
// 根据几何体和材质创建物体
const cube = new THREE.Mesh(geometry, material)
console.log(cube)
// 将几何体添加到场景中
scene.add(cube)
// 初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement)
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
// 阻尼效果
controls.enableDamping = true
// 渲染函数
function render() {
renderer.render(scene, camera)
// 渲染下一帧的时候就会调用render函数
requestAnimationFrame(render)
}
render()