为了让物体呈现更多细节或使其增加美感,ThreeJS提供足够的实现方式,其中,纹理贴图 Texture 是给材质表面添加图像或颜色,以此改进、丰富材质的外观属性。
贴图需要加载图像,ThreeJS内置有多种图像的加载方案,一般建议使用 TextureLoader() 加载器,它有一个加载方法 load(url) 用以加载图像资源(url地址):
// 创建 texture 加载器
var loader = new THREE.TextureLoader();
// 创建 texture 贴图
var texture = loader.load('图片地址');
// 上述写法等同于
var texture = new THREE.TextureLoader().load('图片地址');
这里有两个问题需要注意:其一,加载为 texture 纹理贴图的图片资源应是同源的或支持跨域的。同源指图片和网页同一个网站,支持跨域指来自不同网站的图片支持外链且支持跨源通信;其二,TextureLoader 加载器的 load() 加载方法是一个异步方法,这会产生图片加载尚未完成其余的进程却已经进入了工作状态的现象,处理不当贴图将无法成功渲染。ThreeJS意识到这个问题,所以,它为 load() 方法设置一个回调函数,以下是一个非标准的回调处理方案:
var texture = new THREE.TextureLoader().load('图片地址', () => {
// ... texture相关属性设置略
renderer.render(scene, camera); // 加载完毕渲染器渲染效果
});
上述方法核心是让渲染器做一次渲染,以确保贴图正常显示,实际上还应该加入一个出错处理的函数。当然,如果后续的渲染放在循环运行的动画中,做不做上述处理都无伤大雅,但还是建议使用回调函数处理相关设置和渲染问题。
纹理贴图本质上是一个相当复杂的机制,还有很多很多需要设置的细节。作为入门,学习并掌握本讲所介绍的内容就已经很不错了。下面给一个完整的示例,相关核心内容均在相应的注释中有简单说明:
<div style="margin: 10px; position: absolute;">点击页面暂停/继续动画</div>
<script type="module">
import * as THREE from 'https://638183.freep.cn/638183/web/ku/three.module.min.js';
const scene = new THREE.Scene;
const clock = new THREE.Clock();
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const picUrl = 'https://638183.freep.cn/638183/small/cat1.jpg';
// 纹理加载器加载图片
const texture = new THREE.TextureLoader().load(picUrl, () => {
texture.colorSpace = THREE.SRGBColorSpace; // 保真
texture.wrapS = THREE.RepeatWrapping; // 横向重复开启
texture.wrapT = THREE.RepeatWrapping; // 纵向重复开启
texture.repeat.set(1, 1); // 重复次数纵横方向各为 1
//renderer.render(scene, camera); // 渲染效果或直接运行动画
animate();
});
// 创建立方体 :使用 map 属性给材质添加纹理,材质的 color 和纹理颜色叠加
const mesh = new THREE.Mesh(
new THREE.BoxGeometry(1.5, 1.5, 1.5),
new THREE.MeshBasicMaterial({ color: 0x00ffee, map: texture })
);
scene.add(mesh);
const animate = () => {
requestAnimationFrame(animate);
const delta = clock.getDelta();
mesh.rotation.x += delta / 2;
mesh.rotation.y += delta / 3;
renderer.render(scene, camera);
};
window.onresize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
document.onclick = () => clock.running ? clock.stop() : clock.start();
//animate(); // 纹理加载时已经运行动画的话这里就不用重复运行
</script>
运行代码
以上是老师直播带货的主打产品六只猫苦咖啡包装盒原型,六只猫苦咖啡系支农产品,通过老师讲堂下单所得收益老师分文不取。感谢大家的爱心,有你,咖啡再苦,也苦不了山沟沟里的孩纸。
附:ThreeJS中文网·纹理(Texture)