上一节我们说了模型的形状以后,这一节我们讲解一下模型的表现,也就是我们看到的模型的外观——材质。
简单的说就是物体看起来是什么质地。材质可以看成是材料和质感的结合。在渲染程式中,它是表面各可视属性的结合,这些可视属性是指表面的色彩、纹理、光滑度、透明度、反射率、折射率、发光度等。Three.js
给我们封装好了大部分的材质效果,避免我们使用复杂的shader
语言自己去实现。接下来我们先介绍一下Material
常用的一些属性和方法。
基本属性和方法
needsUpdate
如果修改了Material
内的内容,需要将此属性设置为true
,然后Three.js
会在下一帧里面将修改内容同步到WebGL
的显存内。切记不要在requestAnimationFrame
方法内更新,会浪费性能,只需要在更新Material
属性后设置一次即可。
side
此属性可以定义当前面的哪个方向会被渲染,默认值是THREE.FrontSide
(只渲染正面),可选值有:THREE.BackSide
(只渲染背面)和THREE.DoubleSide
(正面和背面都会渲染)。
transparent
此属性定义了材质是否可以透明,因为对于透明需要材质进行特殊处理,并在不透明的物体渲染完成后再渲染透明物体。当设置此属性为true
后,可以通过设置opacity
来调整透明度,默认为false
。
opacity
此属性可以定义材质的透明度,必须将材质的transparent
设置为true
才可使透明度管用。取值范围为0.0
到1.0
。默认值是1.0,也就是不透明。
map
此属性可以配置当前材质的纹理贴图,是一个THREE.Texture
对象,下面我们将会讲解如何给材质贴图。这是属性大部分材质都会有的属性,只有极其个别的材质如LineBasicMaterial
(线材质)等没有这个属性。
wireframe
是否将模型渲染成线框,默认为false
。个别材质也没有这个属性。
dispose()
此方法用于将材质从内存中删除,在不需要使用当前材质时使用,但不会将材质的纹理贴图删除,如果需要将纹理贴图也删除,需要调用material.map.dispose()
。
配置纹理贴图
由于经常使用纹理贴图,所以在这里单独讲解一下如何实现一个纹理贴图。
实现纹理贴图有以下两种方式,第一种,使用THREE.TextureLoader
进行生成纹理对象:
或者直接实例化:
纹理重复问题
如果图片不是标准的2的幂数(2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, …),在控制台会给我们提示:THREE.WebGLRenderer: image is not power of two
,意思就是说图片不是标准格式高宽不是2的幂数。我们需要设置水平方向和垂直方向上图片如何重复的。需要配置的两个属性是:texture.wrapS
(水平方向重复)和texture.wrapT
(垂直方向重复),默认值是:THREE.ClampToEdgeWrapping
纹理的最后一个像素延伸到网格的边缘。可选项有:THREE.RepeatWrapping
纹理将重复无穷大,MirroredRepeatWrapping
镜像重复,可以理解为重复时,反着绘制一个然后正着绘制一个,达到的效果就是没有强烈的过渡感觉。
needsUpdate 属性
如果更新了纹理的相关属性,需要将此属性设置为true
,将数据同步到WebGL
。
repeat
纹理在整个表面水平方向和垂直方向重复多少次,也会受纹理重复的设置的影响,设置方式为:
内置常用材质
在讲解常用材质之前,我们先讲解一下如何实例化一个材质和一些需要注意的地方。我们使用第一个讲到的材质MeshBasicMaterial
作为例子。
MeshBasicMaterial和设置颜色的方法
这种材质是一种简单的材质,不会受到光的影响,直接看到的效果就是整个物体的颜色都是一样,没有立体的感觉。在实例化材质时,我们可以传入一个对象,设置材质的相关属性可以通过对象属性的方式传入,但是属性color
(颜色)例外,实例化的时候可以传入十六进制数,也可以写十六进制字符串。实例化完成后再修改需要重新赋值THREE.Color
对象,或者调用material.color.set
方法赋值。
上面的案例就是使用MeshBasicMaterial
材质创建了一个立方体,我们设置了显示颜色为一种浅蓝色,除了上面实例化的时候设置的,在后面也可以修改:
我们也可以直接赋值一个新的THREE.Color
对象,如:
我们可以通过new THREE.Color
进行创建一个颜色对象,Three.js
支持的颜色书写方式比较丰富,如:
MeshNormalMaterial法向材质
这种材质会根据面的方向不同自动改变颜色,也是我们之前一直在用的材质。此材质不受灯光影响。
LineBasicMaterial线条材质
在上一节我们讲几何体时,没有讲解如何画直线,是由于直线需要单独的材质进行实现,所以我们将直线放到了材质这一节进行讲解。主意:由于windows
系统的原因,线的宽度只能为1。
要绘制线段,我们需要确定两个点,就是起点和终点,案例中我们使用了四个顶点创建了三条线。然后Geometry
对象使用这组顶点配置几何体,实例化线的材质,最后使用THREE.Line
生成线。
LineDashedMaterial虚线
我们也可以创建虚线,这里我们来点新花样,就是实现曲线。曲线也和直线一样,在windows
系统线的粗度只能为1。
要创建曲线,我们需要使用到THREE.CatmullRomCurve3
来生成一个curve
对象,这是一个曲线对象,可以从对象获取生成的曲线的点的集合,在这里科普一下,曲线也是由无数段的直线组成的,段数分的越清晰,曲线过渡越顺滑。
添加光
由于MeshBasicMaterial
不会受光的影响,即使有光也不会影响它的效果,前面我们也没有添加光。但是后面介绍的材质会受到光源的影响,在介绍之前,我们需要添加一个光源,来影响材质的显示效果。
上面我们添加了一个模拟太阳光线的平行光和一个对每一个物理都造成影响的环境光,具体的内容将会在下一节讲解。
下面介绍的材质都是对光有反应的,而且如果场景内没有光,模型将无法显示。
MeshLambertMaterial 兰伯特材质
这种材质会对光有反应,但是不会出现高光,可以模拟一些粗糙的材质的物体,比如木头或者石头。实现案例:
MeshPhongMaterial 高光材质
这种材质具有高光效果,可以模拟一些光滑的物体的材质效果,比如油漆面,瓷瓦等光滑物体。实现案例:
MeshStandardMaterial 基于物理的渲染(PBR)材质
这种材质基于物理的渲染(PBR)材质,生成的材质效果更佳,但是相应也占用更多的计算量。这种材质我们可以定义它的粗糙度来确定反光效果,经常用于模拟金属的质感,使金属质感更加真实。
案例代码
最后,我讲这节的内容整理成了一个案例放到了github上:github代码地址 案例效果查看地址:github地址