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)

在这里插入图片描述

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

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

或者这样写

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

在这里插入图片描述

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

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

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

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

这是因为一旦材质被实例化后,它的.color属性会是一个Color
在这里插入图片描述
材质对象的一些属性可以在构造函数参数中设置,也可以访问材质对象的属性设置。
你可以通过下面俩种方式设置材质颜色属性

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

颜色和纹理可以结合起来
在这里插入图片描述

opacity属性设置材质透明度

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

material.transparent = true
material.opacity = 0.5	

在这里插入图片描述

alphaMap属性设置alpha贴图

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

在这里插入图片描述

什么是alpha贴图?

简单来讲,alpha贴图白色区域是可见的,黑色区域将被隐藏起来在这里插入图片描述
我们可以把alpha贴图和其他纹理贴图结合起来
在这里插入图片描述

side属性设置渲染哪一面

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

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

法线网格材质MeshNormalMaterial

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

const material = new THREE.MeshNormalMaterial()

如果你改变下图摄像机位置,可以观察到物体颜色会有所不同。
法线可以用于照明、反射与折射等。
在这里插入图片描述

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

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

flatShading属性

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

material.flatShading = true

可以观察到非平面物体表面不再那么光滑了。
在这里插入图片描述

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

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

网帽材质MeshMatcapMaterial

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

const material = new THREE.MeshMatcapMaterial()

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

material.matcap = matcapsTexture

在这里插入图片描述
查看渲染效果,我们会有一种错觉,感觉物体被照亮了一样。因此网帽材质的作用就是在场景没有光源的情况下,模拟出物体被光照的效果
在这里插入图片描述
在这里插入图片描述

网帽材质贴图获取网站

深度网格材质MeshDepthMaterial

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

const material = new THREE.MeshDepthMaterial()

下图为摄像机正常观察情况
在这里插入图片描述
下图为摄像机靠近圆环体的观察情况
在这里插入图片描述

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)

在这里插入图片描述
如果我们不添加光源,由于我们没有为渲染器添加背景颜色,所以我们会看到一片漆黑。

Phong网格材质MeshPhongMaterial

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

在这里插入图片描述
我们可以通过shininess属性控制光线反射高亮程度,数值越高越闪亮,并通过specular属性控制反射的颜色

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

在这里插入图片描述

Toon网格材质 MeshToonMaterial

Toon网格材质与Lambert网格材质很相似,但更偏向于卡通化。我们可以看出物体的颜色渐变非常明显
在这里插入图片描述
在这里插入图片描述

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

material.gradientMap = gradientTexture

下图是渐变纹理贴图
在这里插入图片描述
在这里插入图片描述
观察下图效果,我们不能说它与Lambert网格材质十分相似,只能说是一模一样,但是很明显失去了卡通化的效果在这里插入图片描述
这是因为放大滤镜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

在这里插入图片描述
下图为5层渐变
在这里插入图片描述

标准网格材质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

在这里插入图片描述
在这里插入图片描述
我们还可以设置环境遮挡效果的强度aoMapIntensity属性。默认值为1。零是不遮挡效果。

material.aoMapIntensity = 3.1

在这里插入图片描述

displacementMap属性

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

material.displacementMap = doorHeightTexture

在这里插入图片描述

在这里插入图片描述

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

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

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)

重新观察
在这里插入图片描述
在这里插入图片描述
观察上图可以发现几何体顶点数多起来后,物体稍微变得不再那么奇怪,至少有点规则性了。
同时我们也注意到这默认位移效果有点用力过猛,这时我们可以设置displacementScale属性:位移贴图对网格的影响程度(黑色是无位移,白色是最大位移)。默认值为1。

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

在这里插入图片描述

metalnessMap属性和roughnessMap属性

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

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

可以观察到整个木材表面非常光滑,铁锁位置粗糙
在这里插入图片描述

normalMap属性

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

material.normalMap = doorNormalTexture

在这里插入图片描述
可以观察到这个木门已经开始有点栩栩如生了
在这里插入图片描述
我们可以normalScale属性改变法线纹理贴图对材质的影响程度。典型范围是0-1。默认值是Vector2设置为(1,1)。

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

alphaMap属性

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

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

终于有了一扇完整的看起来正常的门了
在这里插入图片描述

// 标准网格材质(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粗糙度控制反射情况
在这里插入图片描述

//环境贴图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转化为立方体贴图

  • 10
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会为您解答关于WebGL three.js的阴影与实现物体动画的问题。首先,让我们来了解一下WebGL three.js是什么。 WebGL three.js是一款基于WebGL的JavaScript 3D库,可以帮助我们快速搭建3D场景和应用。接下来我们来讲解阴影和实现物体动画的方法。 一、阴影 阴影是模拟物体之间的阴影效果,让3D场景更加真实。在three.js中,我们可以通过设置Mesh的castShadow和receiveShadow属性来实现阴影效果。 1. 首先,我们需要在场景中添加光源,例如SpotLight或DirectionalLight。 2. 然后,在需要投射阴影的物体上设置castShadow为true。 3. 最后,在需要接收阴影的物体上设置receiveShadow为true。 代码示例: ```javascript // 添加光源 const light = new THREE.SpotLight(0xffffff); light.position.set(0, 100, 0); light.castShadow = true; scene.add(light); // 添加需要投射阴影的物体 const cube = new THREE.Mesh(new THREE.BoxGeometry(10, 10, 10), new THREE.MeshLambertMaterial({ color: 0xff0000 })); cube.castShadow = true; scene.add(cube); // 添加需要接收阴影的物体 const plane = new THREE.Mesh(new THREE.PlaneGeometry(200, 200, 1, 1), new THREE.MeshLambertMaterial({ color: 0xffffff })); plane.receiveShadow = true; plane.rotation.x = -Math.PI / 2; scene.add(plane); ``` 二、物体动画 在three.js中,我们可以通过Tween.js库来实现物体的动画效果。Tween.js是一款JavaScript动画库,可以帮助我们实现非常丰富的动画效果。 1. 首先,我们需要在HTML文件中引入Tween.js库文件。 2. 然后,在需要动画的物体上设置初始状态。 3. 最后,通过Tween.js库来设置物体的目标状态和动画效果,例如缓动动画(ease)或弹跳动画(bounce)。 代码示例: ```javascript // 引入Tween.js库文件 <script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/18.6.4/tween.min.js"></script> // 添加需要动画的物体 const cube = new THREE.Mesh(new THREE.BoxGeometry(10, 10, 10), new THREE.MeshLambertMaterial({ color: 0xff0000 })); cube.position.set(0, 0, 0); scene.add(cube); // 设置初始状态 const start = { x: 0, y: 0, z: 0 }; // 设置目标状态 const end = { x: 50, y: 50, z: 50 }; // 设置动画效果 const tween = new TWEEN.Tween(start) .to(end, 1000) .easing(TWEEN.Easing.Quadratic.InOut) .onUpdate(() => { cube.position.set(start.x, start.y, start.z); }) .start(); ``` 以上是关于WebGL three.js阴影与实现物体动画的方法,希望能够对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值