ThreeJs入门32-WebGL模型篇:怎么给Obj模型赋予多个纹理

2,726 阅读2分钟

「这是我参与2022首次更文挑战的第36天,活动详情查看:2022首次更文挑战

在3D世界中,很多模型,包括OBJ、VTK、GLTF等等,它们有很多相似的地方。无论是什么模型,在三维世界中它们都是由点线面组成的,在加上纹理、材质和光线,就更接近自然世界中的物体。

这节我们来看下怎么给Obj模型赋予多个纹理。

准备纹理

  • 我们需要准备两张纹理图来实现我们的功能

UV_Grid_Sm.jpg

disturb.jpg

  • 第一张图是我们之前使用过的带有纹理坐标的纹理图
  • 第二张图是我们找的一张新的纹理图

创建多个纹理实例

  • 一个纹理实例绑定一个纹理贴图,我们这里需要两个
// 创建纹理实例
var texture = new THREE.Texture();
var texture2 = new THREE.Texture();

加载多个纹理图片资源

  • 加载多个纹理资源,赋值给不同的纹理实例进行缓存。
var loader = new THREE.ImageLoader(manager);
loader.setCrossOrigin("Anonymous");  // 解决跨域问题

loader.load(`${base_url}/textures/UV_Grid_Sm.jpg`, function (image) {
    texture.image = image;
    texture.needsUpdate = true;
})
loader.load(`${base_url}/textures/disturb.jpg`, function (image) {
    texture2.image = image;
    texture2.needsUpdate = true;
})
  • 使用 THREE.ImageLoader 加载我们的图片资源
  • 设置 setCrossOrigin 来解决我们线上图片跨域问题
  • 加载的图片添加到纹理中
  • 纹理需要设置 needsUpdate 来进行更新。

给obj模型添加多个的纹理

  • 我们遍历模型中的子模型,通过判断取模给子模型赋值不同的纹理
var i = 0;
var objLoader = new THREE.OBJLoader(manager)
objLoader.setCrossOrigin("Anonymous");  // 解决跨域问题
objLoader.load(`${base_url}/models/obj/male02/male02.obj`, function (object) {
    // 遍历子模型
    object.traverse(function (child) {
        if (child instanceof THREE.Mesh) {
            // 当取模等于0的时候赋予纹理2
            if (i % 2 == 0) {
                child.material.map = texture2
            } else {
                child.material.map = texture
            }
            i++
        }
    })
    object.position.y = -80
    scene.add(object)
}, onProgress, onError)
  • 通过 THREE.OBJLoader 加载我们的 obj 模型
  • 加载完成获取到模型后,通过 object.traverse 遍历子模型
  • 根据我们的判断条件给不同的子模型赋值不同的纹理
  • 我们也可以通过 onProgress 监听加载进度, onError 监听加载错误。
  • 完成效果展示,目前随机给的纹理贴图,两只手和两只脚的贴图不一样,有点不协调。

image.png

  • 我们也可以只给身体赋予纹理2,其他部位赋予纹理1,这样手和脚的贴图就能对称了。
object.traverse(function (child) {
  if (child instanceof THREE.Mesh) {
      // 模型的名字是身体部位,赋予纹理2
      if (child.name === 'mesh1.002_mesh1-geometry') {
          child.material.map = texture2
      } else {
          child.material.map = texture
      }
  }
})
  • mesh1.002_mesh1-geometry 这个模型是模型的身体部位,其他的子模型就是手脚和头发了。
  • 完成效果展示,这样看起来协调多了,如果想把头部单独赋予贴图,需要把头部做成一个单独的模型,这个需要模型师进行处理。

image.png

codepen示例代码 以上就是我们对与如何给模型赋予多个纹理的实战了。

总结

这一节我们主要讲了以下内容:

  • 准备多个纹理图片
  • 通过判断给模型赋予多个纹理