纹理从哪来
纹理就是一张交给 GPU 的图像。本示例不加载任何图片文件,而是程序化生成:
CanvasTexture:先用 2D Canvas API 画格子、写字,再把这块 canvas 当作纹理上传。DataTexture:直接用Uint8Array填 RGBA 字节,适合噪声、查找表、计算结果。数据准备好后要设置texture.needsUpdate = true。
UV:贴图的坐标系
每个顶点都有一个 uv 属性,(0,0) 是图像左下角,(1,1) 是右上角。注意 Canvas 的原点在左上角,three.js 默认 flipY = true 帮你翻转了。不同几何体的 UV 布局不同:立方体每个面都拿到完整的 0–1;球体的 u 绕赤道一圈、v 从南极到北极;圆环结的 u 沿着管子方向。贴图上的格子编号让你一眼看出 UV 是怎么铺的。
平铺、偏移、旋转
texture.repeat:大于 1 时图像会重复多次。texture.offset:平移图像。texture.rotation与texture.center:绕某点旋转。wrapS / wrapT:UV 超出 0–1 时怎么办。RepeatWrapping重复,MirroredRepeatWrapping镜像重复,ClampToEdgeWrapping(默认)拉伸边缘像素。所以只设置 repeat 却不改 wrap,你会看到边缘被拉长的条纹。
过滤与 Mipmap
一个纹素(texel)在屏幕上可能比像素大,也可能比像素小:
magFilter(放大):NearestFilter得到清晰的像素块,LinearFilter平滑插值。minFilter(缩小):远处纹理会闪烁,需要 mipmap(预先缩小的图像金字塔)。LinearMipmapLinearFilter最平滑。
各向异性过滤(anisotropy)专治倾斜角度下的模糊。地板是最好的观察对象:把 anisotropy 从 1 调到最大,远处的格子会明显变清晰。最大值由 renderer.capabilities.getMaxAnisotropy() 给出。
色彩空间
颜色贴图通常是在 sRGB 空间里制作的,所以要设置 texture.colorSpace = THREE.SRGBColorSpace,让 three.js 在光照计算前把它转换到线性空间。法线贴图、粗糙度贴图这类“数据”纹理则保持 NoColorSpace。
取消勾选 colorSpace = sRGB,颜色会立刻变得发灰、偏淡,这就是忘记设置色彩空间的典型症状。
核心 API
THREE.CanvasTextureTHREE.DataTexturetexture.repeattexture.offsettexture.wrapSTHREE.RepeatWrappingtexture.magFiltertexture.minFiltertexture.anisotropytexture.colorSpacerenderer.capabilities.getMaxAnisotropy动手试试
- 1把 repeatU 调到 3,再把 wrap 切到 Clamp,看看超出 0–1 的部分发生了什么。
- 2切到 data 纹理,把 magFilter 改成 Nearest,观察 16×16 的像素块。
- 3把 minFilter 设为 Nearest,转动视角看地板远处的闪烁(摩尔纹)。
- 4在 makeUvGrid 里给 canvas 加一行你的名字,确认文字出现在每个物体上的位置。
还没有输出。console.log 的内容会显示在这里。
运行中