写点什么

Three.js 杂记(十)——贴图

用户头像
空城机
关注
发布于: 2021 年 03 月 22 日
Three.js杂记(十)——贴图

贴图介绍

纹理贴图是 Threejs 一个很重要的内容

程序员加载模型的同时同时需要处理纹理贴图。

简单的纹理贴图

通过纹理贴图加载器TextureLoader的 load()方法加载一张图片可以返回一个纹理对象Texture纹理对象Texture可以作为模型材质颜色贴图.map 属性的值。


材质的颜色贴图属性.map 设置后,模型会从纹理贴图上采集像素值,这时候一般来说不需要在设置材质颜色.color。.map 贴图之所以称之为颜色贴图就是因为网格模型会获得颜色贴图的颜色值 RGB。

例子:

使用平铺的方式,将草地图片贴到PlaneGeometry上,图片如下:



代码:


<div id="app"></div><script type="text/javascript">	var scene = new THREE.Scene();	camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);	render = new THREE.WebGLRenderer({		antialias: true	});	render.setPixelRatio(window.devicePixelRatio);	render.setSize(window.innerWidth, window.innerHeight)	/********************************************************/	var app = document.getElementById("app");	app.appendChild(render.domElement);			var geometry = new THREE.PlaneGeometry(20, 20, 32); //平面	var textureLoader = new THREE.TextureLoader(); // 纹理加载器	var texture = textureLoader.load('./img/grass/grass.png'); 	// 设置阵列模式   默认ClampToEdgeWrapping  RepeatWrapping:阵列  镜像阵列:MirroredRepeatWrapping	texture.wrapS = THREE.RepeatWrapping;	texture.wrapT = THREE.RepeatWrapping;	// uv两个方向纹理重复数量	texture.repeat.set(10, 10);	var material = new THREE.MeshBasicMaterial({		map: texture, // 设置纹理贴图		side: THREE.DoubleSide	});	var plane = new THREE.Mesh(geometry, material);	scene.add(plane);
// 相机 camera.position.set(20, 20, 40); //设置相机位置 camera.lookAt(new THREE.Vector3(0, 0, 0)) /********************************************************/ function animate(){ render.render(scene, camera); window.requestAnimationFrame(animate); } animate();</script>
复制代码

效果:


此时纹理贴图是静止状态,如果想要一个运动的纹理贴图,可以设置texture.offset位置


function animate(){	// 设置纹理偏移	texture.offset.x -= 0.06	render.render(scene, camera);	window.requestAnimationFrame(animate);}animate();
复制代码

效果:

canvas 纹理贴图

在使用贴图的过程中,贴图上可以使用不同的材质


通过 Three.js 类CanvasTexture可以分别实现把 Canvas 画布作为纹理贴图使用。


Canvas 画布作为 Three.js 纹理贴图(CanvasTexture)

Canvas 画布可以通过 2D API 绘制各种各样的几何形状,可以通过 Canvas 绘制一个轮廓后然后作为 Three.js 网格模型、精灵模型等模型对象的纹理贴图。


核心代码:


var textureLoader = new THREE.TextureLoader(); // 纹理加载器var texture = new THREE.CanvasTexture(canvas); 
复制代码


使用 canvas 当作贴图的图片,首先先创建好 canvas 的内容,不需要将 canvas 加入 dom 树中


var canvas = document.createElement("canvas");canvas.width = 512;canvas.height = 128;var c = canvas.getContext('2d');// 矩形区域填充背景c.fillStyle = "#ff0000";c.fillRect(0, 0, 512, 128);c.beginPath();// 文字c.beginPath();c.translate(256, 64);c.fillStyle = "#fff"; //文本填充颜色c.font = "bold 28px 宋体"; //字体样式设置c.textBaseline = "middle"; //文本与fillText定义的纵坐标c.textAlign = "center"; //文本居中(以fillText定义的横坐标)c.fillText("空城机  ( ̄ε(# ̄)☆╰╮o( ̄皿 ̄///)", 0, 0);
复制代码


var geometry = new THREE.PlaneGeometry(40, 20, 32); var textureLoader = new THREE.TextureLoader(); // 纹理加载器var texture = new THREE.CanvasTexture(canvas);  // canvas做画布
// 设置阵列模式 默认ClampToEdgeWrapping RepeatWrapping:阵列 镜像阵列:MirroredRepeatWrappingtexture.wrapS = THREE.RepeatWrapping;texture.wrapT = THREE.RepeatWrapping;// uv两个方向纹理重复数量texture.repeat.set(1, 1);
var material = new THREE.MeshBasicMaterial({ map: texture, // 设置纹理贴图 side: THREE.DoubleSide // 双面});var box = new THREE.Mesh(geometry, material);scene.add(box);
复制代码


效果:


video 视频纹理贴图

通过 Three.js 类``VideoTexture``可以分别实现把视频作为纹理贴图使用。


视频作为 Three.js 纹理贴图(VideoTexture)

视频本质上就是一帧帧图片流构成,把视频作为 Threejs 模型的纹理贴图使用,就是从视频中提取一帧一帧的图片作为模型的纹理贴图,然后不停的更新的纹理贴图就可以产生视频播放的效果。


使用视频当作贴图的图片,首先先创建好 video 的内容,不需要将 video 加入 dom 树中

代码:


let video = document.createElement('video'); //创建video对象video.src = "../img/灭世 第二季1.mp4"; // 设置视频地址video.autoplay = "autoplay"; //要设置播放video.loop = "loop";  //循环播放
复制代码

核心代码:


var textureLoader = new THREE.TextureLoader(); // 纹理加载器var texture = new THREE.VideoTexture(video);  //视频当作贴图
复制代码

效果:(因上传图片大小限制,删减了 gif 图的帧数,造成下图显示效果卡顿)


凹凸贴图 bumpMap 和法线贴图 normalMap

一个复杂的曲面模型,往往模型顶点数量比较多,模型文件比较大,为了降低模型文件大小,法线贴图.normalMap 算法自然就产生了,复杂的三维模型 3D 美术可以通过减面操作把精模简化为简模,然后把精模表面的复杂几何信息映射到法线贴图.normalMap 上

在之前的一篇文章中,其实就已经使用贴图制作了一个旋转的地球模型了,具体可参考:Three.js杂记(九)—— 练习:地球


之前的地球上并没有什么山脉突起,只是一个平面图。而现在,可以使用发现贴图,来造成山脉的效果

法线贴图:


代码:

var textureLoader = new THREE.TextureLoader(); // 纹理加载器var texture = textureLoader.load('./img/earth/css_globe_diffuse.jpg'); // 加载图片,返回Texture对象// 加载法线贴图var textureNormal = textureLoader.load('./img/earth/earth_normal_2048.jpg');
var material = new THREE.MeshPhongMaterial({ map: texture, // 设置纹理贴图 normalMap: textureNormal, //法线贴图 //设置深浅程度,默认值(1,1)。 normalScale: new THREE.Vector2(1.2, 1.2),});var sphere = new THREE.Mesh(geometry, material);scene.add(sphere);
复制代码

效果:


发布于: 2021 年 03 月 22 日阅读数: 15
用户头像

空城机

关注

曾经沧海难为水,只是当时已惘然 2021.03.22 加入

业余作者,在线水文

评论

发布
暂无评论
Three.js杂记(十)——贴图