ThreeJS(WebGL)如何使用UV坐标贴图,实现UV旋转偏移?

ThreeJS是WebGL的一种前端框架,UV坐标的原理是一样的。

前置知识

WebGL纹理

如果对WebGL有兴趣,可以去看WebGL贴材质这篇文章简单了解下。

纹理坐标系统

uv其实就是纹理坐标,因为xyz已经被顶点坐标占用了,所以uvw就用来表示纹理坐标。它时候贴图影射到模型表面的依据,把表面的点与平面上的像素对应起来,一般取值在0~1;
u:图片在显示器水平的坐标
v:垂直方向
w:垂直于显示器表面
一般情况只是在表面贴图,就涉及不到w,所以常称为uv。

ThreeJS纹理贴图

使用纹理对象贴图

ThreeJS本身做了封装,贴图十分方便,如果大家英文好可以直接去官网,嫌麻烦也可以在中文网站上直接查看教程或对象方法。(⚠️以下非完整代码)

    const w=h=64,textureW=textureH=64;
    var geometry = new THREE.PlaneBufferGeometry(w, h); //矩形平面
    // TextureLoader创建一个纹理加载器对象,可以加载图片作为几何体纹理
    var textureLoader = new THREE.TextureLoader();
    // 执行load方法,加载纹理贴图成功后,返回一个纹理对象Texture
    textureLoader.load('./p.jpg', function (texture) {
      texture.wrapS = THREE.RepeatWrapping;
      texture.wrapT = THREE.RepeatWrapping;
      // texture.repeat.set(2, 2);
      var material = new THREE.MeshLambertMaterial({
        map: texture, //设置颜色贴图属性值
      }); //材质对象Material
    var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
    scene.add(mesh); //网格模型添加到场景中

    //纹理贴图加载成功后,调用渲染函数执行渲染操作
    render();

纹理对象Texture本身是有UV旋转偏移方法的,但是如果调整纹理UV,用本身自带方法就需要频繁重新贴图。
ThreeJS(WebGL)如何使用UV坐标贴图,实现UV旋转偏移?_第1张图片

UV坐标与顶点坐标的关系

原始贴图是这样:
ThreeJS(WebGL)如何使用UV坐标贴图,实现UV旋转偏移?_第2张图片

它的纹理坐标和顶点坐标对应情况,它们是一一对应的,大概是这个样子
ThreeJS(WebGL)如何使用UV坐标贴图,实现UV旋转偏移?_第3张图片
如果按上图所说,修改UV坐标就会变成这样:
ThreeJS(WebGL)如何使用UV坐标贴图,实现UV旋转偏移?_第4张图片

UV旋转偏移

我们明白UV坐标是怎么回事,就可以开始旋转、偏移了。

  1. 通过旋转和偏移的值构建一个矩阵,如果矩阵知识还不熟悉,可以看这篇文章复习下,我是用ThreeJS自带的矩阵库,因为它只有三维和四维的,所以我把uv坐标写成了三维,即齐次坐标;
  2. 通过取得BufferGeometry的顶点坐标,再去计算原始的UV坐标。不过要注意的只有是或继承BufferGeometry的对象才能取得uv、position信息;
  3. 最后通过矩阵转换每一点UV坐标,设置为BufferGeometry的UV。
      //geometry可以通过mesh对象取得,pos是保存顶点坐标的数组
      let pos = geometry.getAttribute("position").array;

      
      let uv = [];
      const startP = [pos[0],pos[1]];
      //UV偏移不能太大,一般在0到1之间
      const offsetU = 0.05,offsetV = 0.02,rotation = Math.PI/4;
      let m = new THREE.Matrix3();
      m.setUvTransform( -offsetU, -offsetV, 1, 1, rotation, 0, 0 );
      
      //取得正常情况下的UV坐标
      for (let index = 0; index*3 < pos.length; index++) {
        if(index === 0) uv.push(...[0,0,1]);
        else{
          const currentP = [pos[index*3],pos[index*3+1]]
          uv.push(...[Math.abs((currentP[0]-startP[0])/w),Math.abs((currentP[1]-startP[1])/h),1]);
        }
      }

      let uvAttr = new THREE.BufferAttribute(new Float32Array(uv) , 3) ;
      uvAttr = m.applyToBufferAttribute (uvAttr);
      geometry.attributes.uv = uvAttr;

就这么简单的代码就可以实现UV旋转偏移,但是我们一般会把它封装成函数,通过页面上的Input调整offsetU, offsetV,rotation的值。上面几行的代码,效果就是这样啦:
ThreeJS(WebGL)如何使用UV坐标贴图,实现UV旋转偏移?_第5张图片

你可能感兴趣的:(webgl,ThreeJS,UV,纹理)