ThreeJs入门17-纹理,为物体加上皮肤,让世界还原真实

1,958 阅读3分钟

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

示例代码采用three.js-r73版本: cdnjs.cloudflare.com/ajax/libs/t…

yuque_diagram.jpg

皮肤就是纹理,怎么给我们的三维世界添加纹理,让它更真实地反应现实生活。我们一起来看看吧。

纹理介绍

  • 纹理的本质是图片
  • 给我们的院墙贴上好看的花纹,就会变得五彩缤纷。

image.pngimage.png

  • 给我们的3D模型贴上人的皮肤,就变成了一个真实的人

image.pngimage.png

纹理类

在threejs中,纹理类由THREE.Texture表示,它有三个常用的属性

  • image:图片
  • wrapS:回环方式
  • offset:偏移

其构造函数如下所示:

THREE.Texture = function (image, mapping, wrapS, wrapT, magFilter, minFilter, 
                           format, type, anisotropy
                         )
  • image:这是一个图片类型,基本上它有ImageUtils来加载
  • mapping:是一个THREE.UVMapping()类型,它表示的是纹理坐标(纹理怎么映射到物体上).
  • wrapS:表示x轴的纹理的回环方式,就是当纹理的宽度小于需要贴图的平面的宽度的时候,平面剩下的部分应该p以何种方式贴图的问题。
  • wrapT:表示y轴的纹理回环方式。
  • magFilter和minFilter表示过滤的方式,这是OpenGL的基本概念,目前你不用担心它的使用。当您不设置的时候,它会取默认值。
  • format:表示加载的图片的格式,这个参数可以取值THREE.RGBAFormat,RGBFormat等。THREE.RGBAFormat表示每个像素点要使用四个分量表示,分别是红、绿、蓝、透明来表示。RGBFormat则不使用透明,也就是说纹理不会有透明的效果。
  • type:表示存储纹理的内存的每一个字节的格式,是有符号,还是没有符号,是整形,还是浮点型。默认是无符号型(THREE.UnsignedByteType)
  • anisotropy:各向异性过滤。使用各向异性过滤能够使纹理的效果更好,但是会消耗更多的内存、CPU、GPU时间。

使用纹理需要注意的点

纹理加载类 ImageUtils

  • 加载不同图片格式的一个类
THREE.TextureLoader()

cross-origin交叉域错误

  • javascipt没有访问本地文件的功能
  • 如果本地开发,我们需要启动一个静态服务
  • 如果实在是想本地开发,使用本地文件可以给chrome添加后缀
    • 为chrome浏览器创建一个快捷方式,右键点击chrome.exe,选择“创建快捷方式”或者“发送到”→“桌面快捷方式”),右键点击快捷方式,选择属性。 然后将“--enable-webgl --ignore-gpu-blacklist --allow-file-access-from-files”参数加到目标后,注意exe后面一定要加空格

加载的图片应该是2的次方

如果图片不是2的次方,会报如下错误

THREE.WebGLRenderer: image is not power of two (915x631). Resized to 1024x512

实战在场景中显示纹理图片

  • 我们使用一张512*512的图片作为纹理图片

image_gaitubao_512x512.png

  • 将我们之前的代码进行修改,注释掉关于灯光的部分,使用纹理作为材质
function initObject() {
    // 创建平面几何体
    var geometry = new THREE.PlaneGeometry(512, 512);
    // 获取纹理,内部使用ImageLoader来实现
    // 获取纹理,内部使用ImageLoader来实现
    var loader = new THREE.TextureLoader();
    loader.setCrossOrigin("Anonymous");  // 解决跨域问题
    var texture = loader.load("textures/image.png");
    // 使用纹理进行材质创建
    var material = new THREE.MeshBasicMaterial({ map: texture })
    var mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh)
}
  • THREE.PlaneGeometry: 用来创建平面几何体
  • THREE.TextureLoader: 纹理的一个类,内部使用ImageLoader实现,用来加载纹理图片
  • THREE.MeshBasicMaterial: map属性可以设置纹理贴图
  • 如果使用在线图片,需要设置loader.setCrossOrigin("Anonymous")来解决图片跨域问题
  • 显示效果

image.png

codepen示例代码

总结

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

  • 纹理的介绍
  • 纹理类
  • 使用纹理需要注意的问题
  • 实战在场景中显示纹理图片