threejs-d-4.0

threejs-d-4.0

一、基础网格材质

一个以简单着色(平面或线框)方式来绘制几何体的材质。

这种材质不受光照的影响。

//main.js+
const textureLoader = new THREE.TextureLoader();//初始化一个加载器
const mbColortexture = textureLoader.load('./texture/mb.png') //加载一张纹理贴图

const geometry = new THREE.BoxGeometry( 1, 1, 1 );//创建一个立方体
const material = new THREE.MeshBasicMaterial( { 
    color: '#ffffff',//给立方体添加颜色
    map:mbColortexture//加载贴图
 } );
const cube = new THREE.Mesh( geometry, material );
console.log(cube)
.alphaMap : Texture 
#alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。

仅使用纹理的颜色,忽略alpha通道(如果存在)。 对于RGB和RGBA纹理,WebGL渲染器在采样此纹理时将使用绿色通道, 因为在DXT压缩和未压缩RGB 565格式中为绿色提供了额外的精度。 Luminance-only以及luminance/alpha纹理也仍然有效。

.aoMap : Texture
该纹理的红色通道用作环境遮挡贴图。默认值为null。aoMap需要第二组UV。

.aoMapIntensity : Float
环境遮挡效果的强度。默认值为1。零是不遮挡效果。

.color : Color
材质的颜色(Color),默认值为白色 (0xffffff)。

.combine : Integer
如何将表面颜色的结果与环境贴图(如果有)结合起来。

选项为THREE.MultiplyOperation(默认值),THREE.MixOperation, THREE.AddOperation。如果选择多个,则使用.reflectivity在两种颜色之间进行混合。

.envMap : Texture
环境贴图。默认值为null。

.fog : Boolean
材质是否受雾影响。默认为true。

.lightMap : Texture
光照贴图。默认值为null。lightMap需要第二组UV。

.lightMapIntensity : Float
烘焙光的强度。默认值为1。

.map : Texture
颜色贴图。可以选择包括一个alpha通道,通常与.transparent 或.alphaTest。默认为null。

.reflectivity : Float
环境贴图对表面的影响程度; 见.combine。默认值为1,有效范围介于0(无反射)和1(完全反射)之间。

.refractionRatio : Float
空气的折射率(IOR)(约为1)除以材质的折射率。它与环境映射模式THREE.CubeRefractionMapping 和THREE.EquirectangularRefractionMapping一起使用。 The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material. It is used with environment mapping mode THREE.CubeRefractionMapping. 折射率不应超过1。默认值为0.98。

.specularMap : Texture
材质使用的高光贴图。默认值为null。

.wireframe : Boolean
将几何体渲染为线框。默认值为false(即渲染为平面多边形)。

.wireframeLinecap : String
定义线两端的外观。可选值为 'butt','round' 和 'square'。默认为'round'。

该属性对应2D Canvas lineJoin属性, 并且会被WebGL渲染器忽略。

.wireframeLinejoin : String
定义线连接节点的样式。可选值为 'round', 'bevel' 和 'miter'。默认值为 'round'。

该属性对应2D Canvas lineJoin属性, 并且会被WebGL渲染器忽略。

.wireframeLinewidth : Float
控制线框宽度。默认值为1。

效果展示:

二、纹理常用属性

const textureLoader = new THREE.TextureLoader();
const mbColortexture = textureLoader.load('./texture/mb.png') 
console.log(mbColortexture)

我们可以看到mbColortexture的属性

1.纹理偏移

//main.js+
const textureLoader = new THREE.TextureLoader();
const mbColortexture = textureLoader.load('./texture/mb.png') 
mbColortexture.offset.set(0.2,0.2)//默认是x,y,范围是0.0 to 1.0

效果展示:

2.纹理旋转

const textureLoader = new THREE.TextureLoader();
const mbColortexture = textureLoader.load('./texture/mb.png') 
mbColortexture.center.set(0.5,0.5)//设置中心点,(0.5, 0.5)对应纹理的正中心。默认值为(0,0),即左下角
mbColortexture.rotation = Math.PI / 4 //纹理将围绕中心点旋转多少度,单位为弧度(rad)。正值为逆时针方向旋转,默认值为0。

效果展示:

3.纹理重复

当我们旋转或者改变了uv属性,那么可能就出现了上面那种情况,是因为

.wrapS : number

这个值定义了纹理贴图在水平方向上将如何包裹,在UV映射中对应于U
默认值是THREE.ClampToEdgeWrapping,即纹理边缘将被推到外部边缘的纹素。

我们需要修改属性,使其达到合适的uv

//main.js+
const textureLoader = new THREE.TextureLoader();
const mbColortexture = textureLoader.load('./texture/mb.png') 
mbColortexture.wrapS = THREE.RepeatWrapping//使用RepeatWrapping,纹理将简单地重复到无穷大。
mbColortexture.wrapT = THREE.RepeatWrapping
mbColortexture.center.set(0.5,0.5)
mbColortexture.rotation = Math.PI / 4

//使用MirroredRepeatWrapping, 纹理将重复到无穷大,在每次重复时将进行镜像。

wrapS和wrapT可以设置相同的属性

.wrapS : number

这个值定义了纹理贴图在水平方向上将如何包裹,在UV映射中对应于U
默认值是THREE.ClampToEdgeWrapping,即纹理边缘将被推到外部边缘的纹素。 其它的两个选项分别是THREE.RepeatWrapping和THREE.MirroredRepeatWrapping。 请参阅texture constants来了解详细信息。

.wrapT : number

这个值定义了纹理贴图在垂直方向上将如何包裹,在UV映射中对应于V
可以使用与 .wrapS : number相同的选项。

请注意:纹理中图像的平铺,仅有当图像大小(以像素为单位)为2的幂(2、4、8、16、32、64、128、256、512、1024、2048、……)时才起作用。 宽度、高度无需相等,但每个维度的长度必须都是2的幂。 这是WebGL中的限制,不是由three.js所限制的。

//main.js+
const textureLoader = new THREE.TextureLoader();
const mbColortexture = textureLoader.load('./texture/mb.png') 
mbColortexture.wrapS = THREE.RepeatWrapping
mbColortexture.wrapT = THREE.RepeatWrapping
mbColortexture.repeat.set(1,1)//设置重复的次数
mbColortexture.center.set(0.5,0.5)

三、纹理算法显示

这里主要是两个属性.magFilter和.minFilter

.magFilter : number

当一个纹素覆盖大于一个像素时,贴图将如何采样。默认值为THREE.LinearFilter, 它将获取四个最接近的纹素,并在他们之间进行双线性插值。 另一个选项是THREE.NearestFilter,它将使用最接近的纹素的值。
请参阅texture constants页面来了解详细信息。

.minFilter : number

当一个纹素覆盖小于一个像素时,贴图将如何采样。默认值为THREE.LinearMipmapLinearFilter, 它将使用mipmapping以及三次线性滤镜。

magFilter为THREE.NearestFilter效果展示:

magFilter为THREE.LinearFilter时效果展示:

.minFilter 的一些属性值

四、透明材质和纹理

alphaMap和opacity

//main.js
const textureLoader = new THREE.TextureLoader();
const mbColortexture = textureLoader.load('./texture/AHS_AlphaPack_V3_ (1).png') //加载颜色贴图
const mbAlphatexture = textureLoader.load('./texture/AHS_AlphaPack_V3_ (1).jpg') //加载Alpha贴图
mbColortexture.wrapS = THREE.RepeatWrapping
mbColortexture.wrapT = THREE.RepeatWrapping
mbColortexture.center.set(0.5,0.5)
// mbColortexture.rotation = Math.PI / 4
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { 
    color: '#ffffff',
    map:mbColortexture,
    alphaMap:mbAlphatexture,//alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。
    transparent:true //定义此材质是否透明。这对渲染有影响,因为透明对象需要特殊处 理,并在非透明对象之后渲染。设置为true时,通过设置材质的opacity属性来控制材质透明的程度。默认值为false。
    opacity:0.5 //设置材质的opacity属性来控制材质透明的程度
 } );
const cube = new THREE.Mesh( geometry, material ); 
scene.add( cube );

透明纹理效果展示:

五、环境遮挡贴图与强度

.aoMap : Texture

该纹理的红色通道用作环境遮挡贴图。默认值为null。aoMap需要第二组UV。

.aoMapIntensity : Float

环境遮挡效果的强度。默认值为1。零是不遮挡效果。

const textureLoader = new THREE.TextureLoader();
const mbColortexture = textureLoader.load('./texture/road_with_tram_rails_24_71_diffuse.jpg') 
const mbHeighttexture = textureLoader.load('./texture/road_with_tram_rails_24_71_height.jpg') 
mbColortexture.wrapS = THREE.RepeatWrapping
mbColortexture.wrapT = THREE.RepeatWrapping
mbColortexture.center.set(0.5,0.5)
// mbColortexture.rotation = Math.PI / 4
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { 
    color: '#ffffff',
    map:mbColortexture,
    aoMap:mbHeighttexture,
    aoMapIntensity:1//范围 0-1
 } );
const cube = new THREE.Mesh( geometry, material );
console.log(cube)

添加环境遮挡贴图前:

添加环境遮挡贴图后:

六、PBR

PBR是Physically-Based Rendering(基于物理的渲染)的简称,这个词的字面意思并不容易弄懂,到底什么是PBR呢?

让PBR材质流区别与其他手法的重要一点是光对表面造成的细腻效果,它有着更为准确的模拟,而且同时不失一定的艺术感。让我们从最基础的概念说起:

1.漫射与反射

这是两个材质制作里最基本的概念,是光与表面最基础的相互作用,很多人都知道这一点,但不一定知道在物理层面上到底是什么。

当一束光照射到一个表面,有些光会被反射,即从物体表面沿着法线反方向弹射回去。这一过程和一个球打在了墙上或地上反弹回去差不多。在一个光滑的表面上,这会产生一种镜面效果。

也不是所有的光都被物体表面反弹回去,有些会被物体表面吸收,或者散射进了物体内部,有些散射进去的光又会从后面再次穿出去,再次被眼睛或相机捕捉到。

-

光的这种被物体表面吸收和散射因光的不同波长而不同,也即颜色的不同而不同。由于这种散射极为不规则,所以看起来给人感觉是来自各个方向。这和镜面效果很不同!要在材质里模拟这种效果,可以通过定义一个漫射颜色来做到。

2.半透与透明

但有些漫射很复杂,比如皮肤和蜡烛的表面,简单的定义一个漫射颜色是不够的,还需要考虑材质的厚度和形状。如果物体本身很薄,那么就应该能看到透明效果。这时就需要特殊材质才能模拟了。

能量守恒(一)
通过以上对反射和漫射的描述,我们不难得出一个结论:漫射和反射是互斥的。为了能看到漫射颜色,光必须先穿过表面,或者说没能被表面反射回去。那么根据能量守恒法则,就出现这样的情况:越是反射强烈的表面,其漫射越是弱(暗),因为没有那么多的光穿过去,大部分都被反射回去了。一个表面很明亮的物体它不可能有很强的反射。

-

能量守恒是PBR材质流的基础,要做出自然逼真的材质来,不可以无视这个规则。

3.金属

导电体,比如金属材质要特别单独拿出来讲一下。因为:
首先,它们比绝缘体的表面更加具有反射效果,它们的反射率高达60-90%,而绝缘体只有0-20%。高反射率让光无法穿过表面进入物体内部,从而产生了闪光的质感。

其次,金属的反射效果还会随着光谱而不同,这就是说,金属的反射是带有颜色的,而且很不均匀,比如金,铜等。而绝缘体的反射是无色的。

最后,穿过导电体表面的光最后大部分也会被吸收而不是被散射出去,这既是说,理论上导电体是没有漫射颜色的。

4.菲涅尔

奥古斯汀-让·菲涅尔,这个人的名字是绝对不可能被遗忘的,因为他的名字和反射现象结合到了一起去,不说他的名字谈反射几乎不可能。

在CG里,菲涅尔代表了反射效果因观察角度的不同而不同,也即是物体边缘的反射效果会更加明亮。PBR材质流在这个效果上有几个特色:

首先,对于所有的材质来说,反射效果在接近0度角时最明显,就像镜面反射一样,不管是什么材质都是如此。只要足够光滑能产生反射,那么一定能在某一个角度观察时,看到完美的镜面反射效果!这听起来有点玄乎,但这就是物理。

其次,这种反射效果的变化随着材质的不同而有所不同,如下图:

-

-

-

这个图的意思是在说:在模拟真实材质时,反射效果必须要稍微有些收敛,至少要在需要弱的地方弱下来。这并不难做到,而且现在的材质系统都能自带这种菲尼尔效果了。PBR材质流是可以带出些艺术处理的,在做出基础反射效果后,你可以再添加一些完全反射的小局部做点缀。

5.微表面

上面都是基于物体表面说的东西,或者说是物体能被渲染出来的效果。但物体表面并非完美无瑕,小凹痕,裂纹,凹凸,这些无法被眼睛看到,也无法在法线贴图里被体现出来的微小细节,确实左右漫射和反射效果的真正因素。

-

-

-

上图中,平行照射到物体表面的三道光线被反射到不同的方向上去了,因为它们所照到的物体表面具有不同的方向,使得这种反射的角度变得不可预测,这就产生了模糊反射效果。

但要从物理级别上模拟出这种无规则的反射需要大量的内存和计算量,在CG里只能大概模拟一个整体效果,我们一般叫反射光泽度或反射模糊度。

这是材质制作里一个重要的部分,因为真实世界里到处充满了这种模糊反射效果。

能量守恒(二)
现在渲染器都有了这种虚拟的模糊反射的模拟,正确的参数能让效果更加逼真,比如粗糙的表面会产生更大更柔和的高光区,请看下图:

05.png

-

-

-

图中的小球具有相同的反射强度,但因为不同的反射模糊度而表现出不同的质感,高光随着光滑度越来越清晰明亮。这又是能量守恒的法则体现之一。

微表面反射也同样遵守菲涅尔效果

-

-

-

PBR材质似乎在一夜之间改变了人们对于引擎实时渲染画面的理解。在游戏中我们也能够体验到锈蚀的金属,厚重的皮革,精细的纹理,更加真实的世界从此展现在眼前。从此,PBR材质成为了“次时代”游戏必备的标准。

七、标准网格材质

一种基于物理的标准材质

基于物理的渲染(PBR)这种方法与旧方法的不同之处在于,不使用近似值来表示光与表面的相互作用,而是使用物理上正确的模型。 我们的想法是,不是在特定照明下调整材质以使其看起来很好,而是可以创建一种材质,能够“正确”地应对所有光照场景。

我们PBR材质是和光相辅相成的

1.PointLight( color : Integer, intensity : Float, distance : Number, decay : Float )

color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
intensity - (可选参数) 光照强度。 缺省值 1。
distance - 这个距离表示从光源到光照强度为0的位置。 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.
decay - 沿着光照距离的衰退量。缺省值 2

2.AmbientLight( color : Integer, intensity : Float )

color - (参数可选)颜色的rgb数值。缺省值为 0xffffff。
intensity - (参数可选)光照的强度。缺省值为 1。

//main.js+
const textureLoader = new THREE.TextureLoader();
const mbColortexture = textureLoader.load('./texture/road_with_tram_rails_24_71_diffuse.jpg') 
const mbHeighttexture = textureLoader.load('./texture/road_with_tram_rails_24_71_height.jpg') 
mbColortexture.wrapS = THREE.RepeatWrapping
mbColortexture.wrapT = THREE.RepeatWrapping
mbColortexture.center.set(0.5,0.5)
// mbColortexture.rotation = Math.PI / 4
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
//和基础网格材质一样具备相同属性
const material = new THREE.MeshStandardMaterial( { 
    color: '#ffffff',
    map:mbColortexture,
    aoMap:mbHeighttexture,
    aoMapIntensity:1
 } );
const cube = new THREE.Mesh( geometry, material );
console.log(cube)
scene.add( cube );

// const light = new THREE.AmbientLight( 0xffffff); // 环境光,相当于各个方向射过来的光(没有投影)
// scene.add( light );

const light = new THREE.PointLight( 0xffffff, 5, 100 );//点光源,相当于灯泡,相对灯光的物体背面是没光的
light.position.set( 10, 10, 10 );
scene.add( light );

参考链接:

[什么是PBR]: “https://tao0.date/2021/06/shenmeshipbrcaizhi/

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2022-2023 alan_mf
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信