threejs 顶点UV坐标,纹理贴图

1,017 阅读3分钟

一、创建纹理贴图

创建一个平面,使用图片填充

const geometry = new THREE.PlaneGeometry(100, 100)
const material = new THREE.MeshLambertMaterial({})
const mesh = new THREE.Mesh(geometry, material)

const texLoader = new THREE.TextureLoader()
const texture = texLoader.load('./earth.jpg')
material.map = texture
earth.jpg

earth.jpg

image.png

长方体纹理贴图:const geometry = new THREE.BoxGeometry(100, 100, 100)

image.png

球体纹理贴图:const geometry = new THREE.SphereGeometry(50)

image.png

二、自定义顶点UV坐标

顶点UV坐标的作用

从纹理贴图上提取像素映射到网格模型Mesh的几何体表面上

纹理贴图顶点UV坐标的范围

UV坐标在[0, 1]之间取值,纹理贴图左下角对应的是(0, 0),右上角对应的是(1, 1) image.png

自定义顶点UV geometry.attributes.uv

import * as THREE from 'three'

const geometry = new THREE.BufferGeometry()
const vertices = new Float32Array([0, 0, 0, 160, 0, 0, 160, 80, 0, 0, 80, 0])
const attribue = new THREE.BufferAttribute(vertices, 3) // 3个为一组
geometry.attributes.position = attribue

const indexes = new Uint16Array([0, 1, 2, 0, 2, 3])
geometry.index = new THREE.BufferAttribute(indexes, 1) // 1个为一组

const uvs = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1])
geometry.attributes.uv = new THREE.BufferAttribute(uvs, 2) // 2个为一组

const texLoader = new THREE.TextureLoader()
const texture = texLoader.load('./earth.jpg')
const material = new THREE.MeshBasicMaterial({
  map: texture //map表示材质的颜色贴图属性
})
const mesh = new THREE.Mesh(geometry, material)

export default mesh
image.png

获取纹理贴图1/4 const uvs = new Float32Array([0, 0, 0.5, 0, 0.5, 0.5, 0, 0.5])

image.png

const uvs = new Float32Array([0.25, 0.25, 0.75, 0.25, 0.75, 0.75, 0.25, 0.75])

image.png

三、圆形平面设置纹理贴图

texture.jpg

texture.jpg

const geometry = new THREE.CircleGeometry(60, )
const texLoader = new THREE.TextureLoader()
const texture = texLoader.load('./texture.jpg')
const material = new THREE.MeshBasicMaterial({
  map: texture,
  side: THREE.DoubleSide
})
const mesh = new THREE.Mesh(geometry, material)
image.png

原理:CircleGeometry的UV坐标默认提取的是一个圆形轮廓

四、纹理对象texture阵列

矩形平面设置颜色贴图

瓷砖.jpg

瓷砖.jpg

const geometry = new THREE.PlaneGeometry(200, 200)
const texLoader = new THREE.TextureLoader()
const texture = texLoader.load('./瓷砖.jpg')

const material = new THREE.MeshLambertMaterial({ map: texture })

const mesh = new THREE.Mesh(geometry, material)
image.png

纹理对象texture的阵列功能

texture.wrapS = THREE.RepeatWrapping
texture.wrapT = THREE.RepeatWrapping
texture.repeat.set(10, 10) // 阵列数量
image.png

绕x轴旋转90° mesh.rotateX(-Math.PI / 2),这样看上去更像是地面瓷砖

image.png

五、矩形mesh+背景透明png贴图

指南针.png

指南针.png

转弯.png

转弯.png

const geometry = new THREE.PlaneGeometry(50, 50)
const texLoader = new THREE.TextureLoader()
const texture = texLoader.load('./指南针.png')
const material = new THREE.MeshLambertMaterial({
  map: texture,
  transparent: true,
  side: THREE.DoubleSide
})

const mesh = new THREE.Mesh(geometry, material)

// 网格地面辅助观察
const gridHelper = new THREE.GridHelper(300, 25, 0x004444, 0x004444)
mesh.add(gridHelper)
image.png

六、UV动画

纹理对象offset属性

纹理对象texture的offset属性可以偏移贴图在mesh上的位置,本质上是修改UV顶点坐标

纹理1.jpg

纹理1.jpg

import * as THREE from 'three'

const geometry = new THREE.PlaneGeometry(200, 20)
const texLoader = new THREE.TextureLoader()
const texture = texLoader.load('./纹理1.jpg')
const material = new THREE.MeshLambertMaterial({ map: texture })

const mesh = new THREE.Mesh(geometry, material)

export { mesh, texture }

使用纹理贴图,一般是铺满mesh

image.png

设置上offset后texture.offset.x += 0.5,可以偏移贴图在mesh上的位置

image.png

纹理对象wrapS/wrapT和offset组合使用,实现一个UV动画

设置上wrapS,对应offste.x偏移:texture.wrapS = THREE.RepeatWrapping

05-顶点坐标UV、纹理贴图.js

import { mesh, texture } from './05-model.js'

function render() {
  texture.offset.x += 0.001 // 设置纹理动画
  renderer.render(scene, camera)
  requestAnimationFrame(render)
}

动画.gif

纹理2.jpg

纹理2.jpg

替换成纹理2.jpg

动画.gif

纹理贴图阵列+UV动画

纹理3.jpg

纹理3.jpg

texture.repeat.x = 50 // 阵列数量自己调整

纹理动画的频率根据每次offset.x的偏移量来

function render() {
  texture.offset.x += 0.04 // 设置纹理动画
  renderer.render(scene, camera)
  requestAnimationFrame(render)
}

动画.gif