const m1 = new THREE.MeshBasicMaterial({color: 0xFF0000});
const m2 = new THREE.MeshBasicMaterial({color: 'red'});
const m3 = new THREE.MeshBasicMaterial({color: '#F00'});
const m4 = new THREE.MeshBasicMaterial({color: 'rgb(255,0,0)'});
const m5 = new THREE.MeshBasicMaterial({color: 'hsl(0,100%,50%)');
接下来看看three.js的几种材质的效果。
MeshBasicMaterial、MeshLambertMaterial、MeshPhongMaterial
首先是MeshBasicMaterial,其特点在于不受光照的影响。而MeshLambertMaterial 只在顶点计算光照,然后 MeshPhongMaterial 则在每个像素计算光照,并且MeshPhongMaterial 还支持镜面高光。
对于MeshPhongMaterial 的 shininess(光泽度) 设置决定了镜面高光的光泽度。它的默认值是30。通过设置不同的数值,可以看到下面的效果:
需要注意一点的是将 MeshLambertMaterial 或 MeshPhongMaterial 的 emissive( 发光度 属性设置为颜色,并将颜色设置为黑色(phong的 shininess 为0),最终看起来就像 MeshBasicMaterial 一样。
在实际工作应用场景中,可以根据不同的场景需求选用不同的材质,这也是为什么Three.js提供了这几种基本材质的原因。因为是更复杂的材质会消耗更多的GPU功耗。在一个较慢的GPU上,比如说手机,一般使用一个不太复杂的材质来减少绘制场景所需的GPU功耗。同样,如果不需要额外的功能,那就使用最简单的材质,已达到最佳的性能。如果你不需要照明和镜面高光,那么就使用 MeshBasicMaterial 。
MeshToonMaterial
MeshToonMaterial 与 MeshPhongMaterial 类似,但有一个很大的不同。它不是平滑地着色,而是使用一个渐变图(一个X乘1的纹理(X by 1 texture))来决定如何着色。默认使用的渐变图是前70%的部分,使用70%的亮度,之后的部分使用100%的亮度,我们可以定义自己的渐变图。这最终会给人一种两种色调的感觉。使用MeshToonMaterial材质之后的效果如下:
MeshStandardMaterial
接下来介绍一下图形学上经常提到的PBR,其全称是Physically Based Rendering,俗称物理渲染。Three.js提供了两种材质用于物理渲染,分别是MeshStandardMaterial与MeshPhysicalMaterial。
上面提到的材质只是使用简单的数学来实现的,虽然看起来是3D的,但它们并不是现实世界中实际存在的东西。而MeshStandardMaterial与MeshPhysicalMaterialPBR材质使用的是更复杂的数学来实现接近现实世界中的效果。
MeshPhongMaterial 和 MeshStandardMaterial 最大的区别是它们使用的参数不同。MeshPhongMaterial 有一个参数用来设置 shininess 属性。MeshStandardMaterial 有2个参数用来分别设置 roughness 和 metalness 属性。
在某种意义上将,roughness(粗糙度) 和 shininess(光泽度)是相反的 。粗糙度(roughness)高的东西,比如棒球,就不会有很强烈的反光,而不粗糙的东西,比如台球,就很有光泽。其设置范围从0到1。
另一个设定,metalness,说的是材质的金属度。金属与非金属的表现不同。0代表非金属,1代表金属。
下图是一个MeshStandardMaterial 快速示例,从左至右看,粗糙度从0到1,从上至下看,金属度从0到1。
MeshPhysicalMaterial
MeshPhysicalMaterial 与 MeshStandardMaterial 相同,但它增加了一个clearcoat 参数,该参数从0到1,决定了要涂抹的清漆光亮层的程度,还有一个 clearCoatRoughness 参数,指定光泽层的粗糙程度。
这里是和上面一样的以二维网格的形式对比,但可以设置 clearcoat 和 clearCoatRoughness 。
各种标准材质的创建速度从最快到最慢顺序如下:
MeshBasicMaterial -> MeshLambertMaterial-> MeshPhongMaterial-> MeshStandardMaterial-> MeshPhysicalMaterial
创建速度越慢的材质,做出的场景越逼真,但在低功率或移动设备上可能会有性能问题,所以在实际应用中需要根据具体场景进行优化。
接下来的3种材质有特殊用途。
ShadowMaterial 用于获取阴影创建的数据。
MeshDepthMaterial 渲染每个像素的深度,其中处在摄像机负近端面的像素其深度为0,处在摄像机负远端面的像素其深度为1。使用这个属性可以实现一些特殊效果。一个简单的例子
side:要显示三角形的哪个面。默认值是 THREE.FrontSide,其他值THREE.BackSide 和 THREE.DoubleSide(正反两面)。Three.js中,大多数3D对象可能都是不透明的实体,所以不需要绘制反面(面向实体内部的面)。设置 side 的最常见的原因是用于绘制平面或其他非实体对象,在这些对象中通常会看到三角形的反面。
下面是用 THREE.FrontSide 和 THREE.DoubleSide 绘制的6个平面对比效果
material.needsUpdate:Three.js会在使用材质时应用材质设置,也就是使用了材质的物体会被渲染。有些材质设置只应用一次,因为改变材质需要消耗很多资源。在这种情况下,需要设置 material.needsUpdate = true 来告诉 three.js 应用材质的变化。当你在使用材质后再去更改设置,需要去设置 needsUpdate的最常见的几种情况:
flatShading
添加或删除纹理,改变纹理是可以的,但是如果想从使用无纹理切换到使用纹理,或者从使用纹理切换到无纹理,那么你需要设置 needsUpdate = true。
本文介绍了Three.js的材质相关的内容,包含了MeshBasicMaterial、MeshLambertMaterial、MeshPhongMaterial、MeshToonMaterial、MeshStandardMaterial、MeshPhysicalMaterial,希望对有帮助
本文发布自 云图三维大前端团队,文章未经授权禁止任何形式的转载。