three.js学习笔记(三)——material材质

什么是材质Material

材质用于在几何体的每个可见像素上添加颜色

基础网格材质MeshBasicMaterial

初始化基础网格材质MeshBasicMaterial,这种材质不受光照的影响。

const material = new THREE.MeshBasicMaterial()

接下来我们往场景中添加三个网格物体

//球形缓冲几何体
const sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(0.5,16,16),material)
//平面缓冲几何体
const plane = new THREE.Mesh(new THREE.PlaneBufferGeometry(1,1),material)
//圆环缓冲几何体
const torus = new THREE.Mesh(new THREE.TorusBufferGeometry(0.5,0.2,16,32),material)
sphere.position.x = -1.5
torus.position.x = 1.5
scene.add(sphere,plane,torus)

three.js学习笔记(三)——material材质_第1张图片

map属性可以为材质设置其纹理贴图

const material = new THREE.MeshBasicMaterial({map:doorColorTexture})

或者这样写

const material = new THREE.MeshBasicMaterial()
material.map = doorColorTexture

three.js学习笔记(三)——material材质_第2张图片

color属性可以在实例化材质时设置材质颜色

// 材质颜色设置红色
const material = new THREE.MeshBasicMaterial({color:0xff0000})

另外一种写法,效仿上面设置纹理贴图,但你会发现如果直接设置材质的颜色,会报错

// 材质颜色设置红色
const material = new THREE.MeshBasicMaterial()
console.log(material.color)
material.color = 'red'   //报错

这是因为一旦材质被实例化后,它的.color属性会是一个Color类
three.js学习笔记(三)——material材质_第3张图片
材质对象的一些属性可以在构造函数参数中设置,也可以访问材质对象的属性设置。
你可以通过下面俩种方式设置材质颜色属性

material.color.set('#ff00ff')
//或者
material.color = new THREE.Color('red')

颜色和纹理可以结合起来
three.js学习笔记(三)——material材质_第4张图片

opacity属性设置材质透明度

若想设置材质透明,则必须开启透明度效果,设置.transparent属性为true

material.transparent = true
material.opacity = 0.5	

three.js学习笔记(三)——material材质_第5张图片

alphaMap属性设置alpha贴图

//alphaMap属性同样需要开启transparent属性
material.transparent = true
material.alphaMap = doorAlphaTexture

three.js学习笔记(三)——material材质_第6张图片

什么是alpha贴图?

简单来讲,alpha贴图白色区域是可见的,黑色区域将被隐藏起来three.js学习笔记(三)——material材质_第7张图片
我们可以把alpha贴图和其他纹理贴图结合起来
three.js学习笔记(三)——material材质_第8张图片

side属性设置渲染哪一面

material.side = THREE.FrontSide   //正面 (默认)
material.side = THREE.BackSide	  //背面
material.side = THREE.DoubleSide  //双面都渲染

其中一些属性(如线框或不透明度)可用于其他类型的材质

法线网格材质MeshNormalMaterial

它是一种把法向量映射到RGB颜色的材质。

const material = new THREE.MeshNormalMaterial()

如果你改变下图摄像机位置,可以观察到物体颜色会有所不同。
法线可以用于照明、反射与折射等。
three.js学习笔记(三)——material材质_第9张图片

法线网格材质和基础网格材质拥有一些共同属性

transparentopacityside这三个属性都是所有材质共有的属性

flatShading属性

其定义材质是否使用平面着色进行渲染。

material.flatShading = true

可以观察到非平面物体表面不再那么光滑了。
three.js学习笔记(三)——material材质_第10张图片

法线网格材质通常被用于调试法线

但由于颜色纷呈,所以也可以试着运用到项目中

网帽材质MeshMatcapMaterial

网帽材质(MeshMatcapMaterial)将通过使用法线作为参照来在看起来像球体的纹理上拾取正确的颜色来显示颜色

const material = new THREE.MeshMatcapMaterial()

我们将网帽材质的matcap属性设置为下图matcap纹理贴图

material.matcap = matcapsTexture

three.js学习笔记(三)——material材质_第11张图片
查看渲染效果,我们会有一种错觉,感觉物体被照亮了一样。因此网帽材质的作用就是在场景没有光源的情况下,模拟出物体被光照的效果
three.js学习笔记(三)——material材质_第12张图片
three.js学习笔记(三)——material材质_第13张图片

网帽材质贴图获取网站

深度网格材质MeshDepthMaterial

如果几何体接近摄影机的“near”值,它将简单地将几何体着色为白色,如果几何体越接近摄影机的“far”值,则将几何体着色为黑色。

const material = new THREE.MeshDepthMaterial()

下图为摄像机正常观察情况
three.js学习笔记(三)——material材质_第14张图片
下图为摄像机靠近圆环体的观察情况
three.js学习笔记(三)——material材质_第15张图片

Lambert网格材质MeshLambertMaterial

该材质对光线有反应

const material = new THREE.MeshLambertMaterial()

因此先往场景添加光源,才可以观察到物体,这里我们添加环境光和点光源

const ambientLight = new THREE.AmbientLight(0xffffff,0.5)
scene.add(ambientLight)
const pointLight = new THREE.PointLight(0xffffff,0.5)
pointLight.position.set(2,3,4)
scene.add(pointLight)

three.js学习笔记(三)——material材质_第16张图片
如果我们不添加光源,由于我们没有为渲染器添加背景颜色,所以我们会看到一片漆黑。

Phong网格材质MeshPhongMaterial

Phong网格材质与Lambert网格材质很相似,但是你可以仔细观察到上图中Lambert网格材质的球体表面有些像是线型一样的奇怪图案,而Phong网格材质的球体相对于前者这些图案不太明显,并且你还能看到Phong网格材质球体上光线的反射更为明亮。

three.js学习笔记(三)——material材质_第17张图片
我们可以通过shininess属性控制光线反射高亮程度,数值越高越闪亮,并通过specular属性控制反射的颜色

material.shininess = 100
material.specular = new THREE.Color('0xff0000')

three.js学习笔记(三)——material材质_第18张图片

Toon网格材质 MeshToonMaterial

Toon网格材质与Lambert网格材质很相似,但更偏向于卡通化。我们可以看出物体的颜色渐变非常明显
three.js学习笔记(三)——material材质_第19张图片
three.js学习笔记(三)——material材质_第20张图片

如果要使其渐变层次更丰富,我们可以将toon材质的gradientMap属性设置为gradient渐变纹理贴图

material.gradientMap = gradientTexture

下图是渐变纹理贴图
在这里插入图片描述
three.js学习笔记(三)——material材质_第21张图片
观察下图效果,我们不能说它与Lambert网格材质十分相似,只能说是一模一样,但是很明显失去了卡通化的效果three.js学习笔记(三)——material材质_第22张图片
这是因为放大滤镜magFilter试图通过拉伸来修复这个非常小的渐变纹理贴图,这过程就使用到了mip映射(mipmapping)使其变得模糊。
所以若想防止此种情况,我们可以设置纹理贴图的缩小滤镜minFilter属性和放大滤镜magFilter属性为THREE.NearestFilter。
关于滤镜属性可以查看我另一篇笔记three.js学习笔记(二)——textures纹理

gradientTexture.minFilter = THREE.NearestFilter
gradientTexture.magFilter = THREE.NearestFilter
// 因为我们的渐变纹理贴图的缩小滤镜minFilter属性使用了NearestFilter
// 所以我们可以为该纹理停用mipmapping,使得GPU不再处理其mip映射
gradientTexture.generateMipmaps = false

three.js学习笔记(三)——material材质_第23张图片
下图为5层渐变
three.js学习笔记(三)——material材质_第24张图片

标准网格材质MeshStandardMaterial

一种基于物理的渲染(PBR)的标准材质,该材质提供了比MeshLambertMaterial 或MeshPhongMaterial 更精确和逼真的结果,代价是计算成本更高。

metalness属性

材质与金属的相似度。非金属材质,如木材或石材,使用0.0,金属使用1.0,通常没有中间值。 默认值为0.0。0.0到1.0之间的值可用于生锈金属的外观。

roughness属性

材质的粗糙程度。0.0表示平滑的镜面反射,1.0表示完全漫反射。
以上两种属性可通过添加GUI面板改变数值进行观察

aoMap属性

aoMap(ambient occlusion map)环境遮挡贴图。它将在纹理较暗的地方添加阴影,因此我们必须添加另外一组uv坐标,即uv2。
在我们的例子中,它与默认UV的坐标相同,因此我们将重用它。

sphere.geometry.setAttribute('uv2',new THREE.BufferAttribute(sphere.geometry.attributes.uv.array,2))
plane.geometry.setAttribute('uv2',new THREE.BufferAttribute(plane.geometry.attributes.uv.array,2))
torus.geometry.setAttribute('uv2',new THREE.BufferAttribute(torus.geometry.attributes.uv.array,2))

为材质aoMap属性设置ao(ambient occlusion)纹理贴图

material.aoMap = doorAmbientOcclusionTexture

three.js学习笔记(三)——material材质_第25张图片
three.js学习笔记(三)——material材质_第26张图片
我们还可以设置环境遮挡效果的强度aoMapIntensity属性。默认值为1。零是不遮挡效果。

material.aoMapIntensity = 3.1

three.js学习笔记(三)——material材质_第27张图片

displacementMap属性

位移贴图会影响网格顶点的位置。换句话说就是它可以移动顶点来创建浮雕。
为材质displacementMap属性设置位移纹理贴图,使得平面物体中间的门有凸起效果。

material.displacementMap = doorHeightTexture

three.js学习笔记(三)——material材质_第28张图片

three.js学习笔记(三)——material材质_第29张图片

物体看起来非常糟糕奇怪。这是因为我们的几何体中没有足够的顶点,所以你可以观察到平面几何体没有任何变化

重新设置几何体的分段数,给其设置更多些

const sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(0.5,64,64),material)
const plane = new THREE.Mesh(new THREE.PlaneBufferGeometry(1,1,100,100),material)
const torus = new THREE.Mesh(new THREE.TorusBufferGeometry(0.3,0.2,64,128),material)

重新观察
three.js学习笔记(三)——material材质_第30张图片
three.js学习笔记(三)——material材质_第31张图片
观察上图可以发现几何体顶点数多起来后,物体稍微变得不再那么奇怪,至少有点规则性了。
同时我们也注意到这默认位移效果有点用力过猛,这时我们可以设置displacementScale属性:位移贴图对网格的影响程度(黑色是无位移,白色是最大位移)。默认值为1。

// 设置位移程度小一点
material.displacementScale = 0.1

three.js学习笔记(三)——material材质_第32张图片

metalnessMap属性和roughnessMap属性

同样道理,还有metalnessMap属性和roughnessMap属性也一样可以设置相应纹理贴图,这样我们可以不必为整个几何体指定均匀的金属程度和粗糙度,而是变为局部改变。

// 为避免反射效果变得怪异,记得先把前面的metalness属性和roughness属性给重设为默认值
material.metalnessMap = doorMetalnessTexture
material.roughnessMap = doorRoughnessTexture

可以观察到整个木材表面非常光滑,铁锁位置粗糙
three.js学习笔记(三)——material材质_第33张图片

normalMap属性

用于创建法线纹理贴图的纹理。它将伪造法线方向,并在物体表面上添加细节。

material.normalMap = doorNormalTexture

three.js学习笔记(三)——material材质_第34张图片
可以观察到这个木门已经开始有点栩栩如生了
three.js学习笔记(三)——material材质_第35张图片
我们可以normalScale属性改变法线纹理贴图对材质的影响程度。典型范围是0-1。默认值是Vector2设置为(1,1)。

// 可以发现细节程度变小了
material.normalScale.set(0.5,0.5)

alphaMap属性

最后我们往材质中再设置alphaMap属性,添加alpha纹理贴图

material.alphaMap = doorAlphaTexture
// 使用alphaMAp记得开启transparent属性
material.transparent = true

终于有了一扇完整的看起来正常的门了
three.js学习笔记(三)——material材质_第36张图片

// 标准网格材质(MeshStandardMaterial)
const material = new THREE.MeshStandardMaterial()
material.map = doorColorTexture
material.aoMap = doorAmbientOcclusionTexture
material.aoMapIntensity = 1
material.displacementMap = doorHeightTexture
material.displacementScale = 0.05
material.metalnessMap = doorMetalnessTexture
material.roughnessMap = doorRoughnessTexture
material.normalMap = doorNormalTexture
material.normalScale.set(0.5,0.5)
material.alphaMap = doorAlphaTexture
material.transparent = true

物理网格材质MeshPhysicalMaterial

物理网格材质MeshPhysicalMaterial与标准网格材质MeshStandardMaterial很相似,只不过物理网格材质具有清晰的涂层效果和更高级的基于物理的渲染属性,可以将其看作是标准网格材质的扩展

点材质PointsMaterial

我们可以用点材质创建粒子

环境贴图Environment maps

环境贴图是场景周围环境的图像。它可以用于反射或折射,也可以用于一般照明,支持多种材质。Three.js仅支持立方环境贴图。

加载立方纹理贴图

使用CubeTextureLoader而不是TextureLoader

const cubeTextureLoader = new THREE.CubeTextureLoader()
const environmentMapTexture = cubeTextureLoader.load([
     '/textures/environmentMaps/0/px.jpg',
     '/textures/environmentMaps/0/nx.jpg',
     '/textures/environmentMaps/0/py.jpg',
     '/textures/environmentMaps/0/nx.jpg',
     '/textures/environmentMaps/0/pz.jpg',
     '/textures/environmentMaps/0/nz.jpg',
 ])

设置envMap属性

material.envMap = environmentMapTexture

观察效果。可以通过设置metalness金属度和roughness粗糙度控制反射情况
three.js学习笔记(三)——material材质_第37张图片

//环境贴图environment map
const material = new THREE.MeshStandardMaterial()
material.metalness = 0.7
material.roughness = 0.2
material.envMap = environmentMapTexture
gui.add(material,'metalness').min(0).max(1).step(0.0001)
gui.add(material,'roughness').min(0).max(1).step(0.0001)

环境贴图素材网站

polyhaven
从上面这个网站下载的环境贴图是一张HDRI图片,可以使用这个工具HDRI-to-CubeMap将HDRI转化为立方体贴图

你可能感兴趣的:(three.js学习笔记,javascript,three.js)