一、在材质中使用纹理
1.加载纹理并应用
纹理最基础的用法是在材质上设置贴图。当你使用 这个材质时(和几何体一起构建网格),网格就会拥有颜色,而这个颜色则来源于纹理。
可以用如下的方式来加载纹理并应用于网格:
function createMesh(geom,imageFile){
var texture = THREE.ImageUtils.loadTexture
("../assets/textures/general/"+imageFile);
var mat = new THREE.MeshPhongMaterial();
mat.map = texture;
var mesh = new THREE.Mesh(geom,mat);
return mesh;
}
为了达到最佳效果,最好使用正方形的图片,其长宽大小是2的次方。例如大小为256*256,512*512,1024*1024的图片最合适。
由于纹理需要放大和缩小,所以纹理上的像素(也称作是texel)通常不会一对一地映射成面上的像素。因此,WebGL和Three.js提供了集中选择。你可以设置magFilter属性,指定纹理如何放大;设置minFilter属性,指定纹理如何缩小。这些属性可以设置成下面的两个基础值:
名称 | 描述 |
THREE.NearestFilter(最近过滤器) | 这个过滤器使用能够找到的最近texel(纹理上的像素)的颜色。用于放大时,这回导致方块化;用于缩小时,这回丢失很多细节 |
THREE.LinearFilter(线性过滤器) | 这个过滤器比较高级,它会使周围四个texel的颜色值来确定颜色。这样虽然在缩小时仍然会丢失很多细节,但在放大时会平滑很多,方块化也比较少 |
除了这些基础值,我们还可以使用mipmap。一个mipmap是一组纹理图片,每个图片的尺寸都是前一张图片的一半。这些图片是在加载纹理时创建的,可以生成比较光滑的过滤效果。所以如果你有一个正方形的纹理(尺寸为2的次方),只需要稍稍几步就可以达到更好的过滤效果。这些属性可以设置成下面这些值:
名称 | 描述 |
THREE.NearestMipMapNearestFilter | 这个过滤器会选择最贴近目标解析度的mipmap,然后应用前表中所讲的最近过滤原则。放大时仍然会有方块化,但缩小时会好很多。 |
THREE.NearestMipMapLinearFilter | 这个过滤器选择的不是mipmap,而是层次最近的两个mipmap。然后在这两层上应用最近过滤原则获取两个中间值。这两个中间值会传递给一个线性过滤器,以获取最终结果 |
THREE.LinearMipMapNearestFilter | 这个过滤器会选择最贴近目标解析度的mipmap,然后应用前表中所讲的线性过滤原则 |
THREE.LinearMipMapLinearFilter | 这个过滤器选择的不是一个mipmap,而是层次最近的两个mipmap。然后在这两层上应用线性过滤原则获取两个中间值。这两个中间值会传递给一个线性过滤器,以获取最终结果 |
如果你没有明确指定magFilter和minFilter属性的值,对于magFilter属性,Three.js会使用THREE.LinearFilter。对于minFilter属性,Three.js会使用THREE.LinearMipMapLinearFilter。
2.使用凹凸贴图创建皱纹
我们可以为材质设置额外的纹理(所谓的凹凸贴图)来为材质增加厚度:
function createMesh(geom,imageFile,bump){
var texture = THREE.ImageUtils.loadTexture
("../assets/textures/general/"+imageFile);
var mat = new THREE.MeshPhongMaterial();
mat.map = texture;
var bump = THREE.ImageUtils.loadTexture
("../assets/textures/general/"+bump);
mat.bumpMap = bump;
mat.bumpScale = 0.2;
var mesh = new THREE.Mesh(geom,mat);
return mesh;
}
这段代码中,除了设置map属性,我们还设置了纹理的bumpMap属性。另外,通过bumpScale属性,我们还可以设置凹凸的高度(如果是负数,则指的是深度)。像素的密集度定义的是凹凸的高度。凹凸贴图中只有像素的相对高度,没有任何坡度的方向性信息。
3.使用法向贴图创建更加细致的凹凸和皱纹
法向贴图中保存的不是每个像素的高度,而是像素的法向向量。如下图所示:
下面的代码展示的就是如何在Three.js里使用法向贴图:
function createMesh(geom,imageFile,normal){
var t = THREE.ImageUtils.loadTexture
("../assets/textures/general/"+imageFile);
var m = THREE.ImageUtils.loadTexture
("../assets/textures/general/"+normal);
var mat2 = new THREE.MeshPhongMaterial({map:t,normal:m});
var mesh = new THREE.Mesh(geom,mat2);
return mesh;
}
这里我们将normalMap属性设置为一个法向纹理。我们还可以指定凹凸的程度,方法是设置normalScale属性:mat.normalScale.set(1,1)。通过这两个属性,你可以沿着x轴和y轴进行缩放。
4.使用光照贴图假阴影
光照贴图是预先渲染好的阴影,你可以用它来模拟真实的阴影。光照贴图中的阴影将会显示成地面上的阴影,从而模拟出真实阴影的效果。你可以用这种技术创建出解析度很高的阴影,而且不会损害渲染的性能。当然,这只对静态场景有效。光照贴图的使用跟其他纹理基本一样,只有几处小小的不同:
var lm = THREE.ImageUtils.loadTexture('../assets/textures/lightmap/lm-1.png');
var wood = THREE.ImageUtils.loadTexture('../assets/textures/general/floor-wood.jpg');
var groundMaterial = new THREE.MeshBasicMaterial({lightMap:lm,map:wood});
groundGeom.faceVertexUvs[1] = groundGeom.faceVertexUvs[0];
应用光照贴图时,我们只要将材质的lightMap属性设置成刚才所示的纹理即可。但是将光照贴图显示出来我们还需要额外的几个步骤。我们需要为光照贴图明确指定UV映射(将纹理的哪一部分应用到表面)。只有这样你才能将光照贴图与其他纹理独立开来。
5.用环境贴图创建虚假的反光效果
你可以通过创建一个对象所处环境的纹理来伪装反光,并将它应用到指定的对象上。下图既是同环境贴图创建发光效果的例子:
这个截图里你可以看到球和方块反射这周围环境。如果移动鼠标,你还可以看到这个反光是跟相机角度和你所看到的城市环境相关联,要创建这样一个例子,我们要执行以下步骤:
(1)创建一个CubeMap对象:一个CubeMap是有6个纹理的集合,而这些纹理可以应用到方块的每一个面上。
(2)创建一个带有这个CubeMap对象的方块:带有CubeMap对象的方块就是移动相机时你所看到的环境。它可以在你向四周看时制造出一种幻象,就好像你站在某个环境中一样。实际上你是处在一个方块中,而这个方块内测渲染出来的纹理让你感觉好像处在某个空间中。
(3)将CubeMap作为纹理:我们用来模拟环境的CubeMap对象也可以用作网格的纹理。Three.js会让它看上去像是环境的反光。
你所需要的是六张用来构建整个场景的图片。所以你需要如下的图片:超前的(posz)、朝后的(negz)、朝上的(posy)、朝下的(negy)、朝右的(posx)、朝左的(negx)。Three.js会将它们缝合在一起,创建一个无缝的环境贴图。
二、纹理的高级用途
1.定制UV映射
通过UV映射,你可以指定纹理的哪一部分显示在物体表面上。UV映射的定制一般是在诸如Blender这样的软件中完成的,特别是当模型变得复杂时。这里需要记住的是UV映射有两个维度,U和V,取值范围是0到1。定制UV映射时,你要为物体的每个面指定其要显示纹理的哪一部分。
2.重复映射
3.在画布上绘制图案并作为纹理
- 用画布做纹理
- 用画布作凹凸贴图
- 用视频输出作为纹理