ThreeJs学习笔记【day11】纹理 【2】

150 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情 >>

PNG和JPG在纹理中的区别

上一篇里讲到内存占用的时候,提到了,纹理占用的内存是 宽度 * 高度 * 4 * 1.33 也就是说,JPG当做纹理的时候,并不一定比PNG占用的内存小,JPG是有损压缩,PNG是无损压缩,PNG比JPG多了透明通道。

过滤和mips

首先简单介绍一下场景,然后再说具体的内容,首先,纹理与立方体,并不一定是1:1这样的关系,那么GPU怎么知道应该如何去渲染纹理?

假设有这样一张16x16的图

image.png

绘制到一个很小的立方体上时,他的表现是这样的:

image.png 关键代码

...
camera.position.z = 1;
...
const boxWidth = 0.05;
const boxHeight = 0.05;
const boxDepth = 0.05;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
...

假如把相机拉近,来观察他上面的纹理,他是这样的:

image.png

可以看出,threeJs依然较为完整的绘制出了纹理,他是怎么做到的?这就是过滤(filter)存在的意义

如果是在photoShop里,它是通过将所有像素平均在一起,来计算出这1、2个像素的颜色。这将是一个非常缓慢的操作,GPU的话,是通过mipmaps来实现的

Mips是纹理的副本集,每一个mip都是前一个mip宽高的一半,直到得到一个1x1的mip,所以,上图会形成这样的mips

image.png

在three.js中,当纹理绘制的尺寸大于其原始尺寸时,或者绘制的尺寸小于其原始尺寸时,你都可以做出相应的处理。

texture.magFilter 可选值及效果

  • THREE.NearestFilter

    同上,在纹理中选择最近的像素。

  • THREE.LinearFilter

    和上面一样,从纹理中选择4个像素,然后混合它们

  • THREE.NearestMipmapNearestFilter

    选择合适的mip,然后选择一个像素。

  • THREE.NearestMipmapLinearFilter

    选择2个mips,从每个mips中选择一个像素,混合这2个像素。

  • THREE.LinearMipmapNearestFilter

    选择合适的mip,然后选择4个像素并将它们混合。

  • THREE.LinearMipmapLinearFilter

    选择2个mips,从每个mips中选择4个像素,然后将所有8个像素混合成1个像素。

**

image.png

纹理的重复

默认情况下,three.js中的纹理是不重复的。要设置纹理是否重复,有2个属性,wrapS用于水平包裹,wrapT用于垂直包裹。

  • THREE.ClampToEdgeWrapping

    每条边上的最后一个像素无限重复。

  • THREE.RepeatWrapping

    纹理重复

  • THREE.MirroredRepeatWrapping

    在每次重复时将进行镜像

someTexture.wrapS = THREE.RepeatWrapping;
someTexture.wrapT = THREE.RepeatWrapping;

重复是用 repeat 重复属性设置的。

const timesToRepeatHorizontally = 4;
const timesToRepeatVertically = 2;
someTexture.repeat.set(timesToRepeatHorizontally, timesToRepeatVertically);

纹理的偏移

纹理的偏移可以通过设置 offset 属性来完成。纹理的偏移是以单位为单位的,其中1个单位=1个纹理大小。换句话说,0 = 没有偏移,1 = 偏移一个完整的纹理数量。

const xOffset = .5; // 偏移二分之一个纹理
const yOffset = .25; // 偏移四分之一个纹理
someTexture.offset.set(xOffset, yOffset);

纹理的旋转

通过设置以弧度为单位的 rotation 属性以及用于选择旋转中心的 center 属性,可以设置纹理的旋转。它的默认值是0,0,从左下角开始旋转。像偏移一样,这些单位是以纹理大小为单位的,所以将它们设置为 .5.5 将会围绕纹理中心旋转。

someTexture.center.set(.5, .5);
someTexture.rotation = THREE.MathUtils.degToRad(45);