七、Three.jsPBR材质与纹理贴图

1、PBR材质金属度和粗糙度

1、金属度 metalness

金属度 属性.metalness表示材质像金属的程度, 非金属材料,如木材或石材,使用0.0,金属使用1.0。

threejs的PBR材质,.metalness默认是0.5,0.0到1.0之间的值可用于生锈的金属外观

javascript 复制代码
new THREE.MeshStandardMaterial({
    metalness: 1.0,//金属度属性
})
javascript 复制代码
mesh.material.metalness = 1.0;//金属度

2、粗糙度 roughness

生活中不同物体表面的粗糙程度不同,比如地面比较粗糙,比如镜子表面就非常非常光滑。

粗糙度 roughness表示模型表面的光滑或者说粗糙程度,越光滑镜面反射能力越强,越粗糙,表面镜面反射能力越弱,更多地表现为漫反射。

粗糙度 roughness,0.0表示平滑的镜面反射,1.0表示完全漫反射,默认0.5。

javascript 复制代码
new THREE.MeshStandardMaterial({
    roughness: 0.5,//表面粗糙度
})
javascript 复制代码
mesh.material.roughness = 0.5;//表面粗糙度

3、全部代码

原本样式

javascript 复制代码
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const loader = new GLTFLoader()
const group = new THREE.Group()
loader.load('./build/金属.glb', function (gltf) {
    gltf.scene.traverse(function (obj) {
        if(obj.isMesh){
            obj.material.metalness = 1.0
            obj.material.roughness = 0.5
        }
    })
    group.add(gltf.scene)
})

export default group 

2、环境贴图.envMap(金属效果)

环境贴图对PBR材质渲染效果影响还是比较大,一般渲染PBR材质的模型,最好设置一个合适的环境贴图。

1、立方体纹理加载器CubeTextureLoader

  • TextureLoader返回Texture
  • CubeTextureLoader返回CubeTexture

2、CubeTextureLoader加载环境贴图

所谓环境贴图 ,就是一个模型周围的环境的图像,比如一间房子,房子的上下左右前后分别拍摄一张照片,就是3D空间中6个角度方向的照片。

javascript 复制代码
// 加载环境贴图
// 加载周围环境6个方向贴图
// 上下左右前后6张贴图构成一个立方体空间
// 'px.jpg', 'nx.jpg':x轴正方向、负方向贴图  p:正positive  n:负negative
// 'py.jpg', 'ny.jpg':y轴贴图
// 'pz.jpg', 'nz.jpg':z轴贴图
const textureCube = new THREE.CubeTextureLoader()
    .setPath('./环境贴图/环境贴图0/')
    .load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']);
    // CubeTexture表示立方体纹理对象,父类是纹理对象Texture 

3、MeshStandardMaterial环境贴图属性.envMap

实际生活中,一个物体表面,往往会反射周围的环境。人的眼睛看到的东西,往往反射有周围景物,所以three.js渲染模型,如果想渲染效果更好看,如果想更符合实际生活情况,也需要想办法让模型反射周围景物。

MeshStandardMaterial材质的环境贴图属性是.envMap,通过PBR材质的贴图属性可以实现模型表面反射周围景物,这样渲染效果更好。

javascript 复制代码
// 加载环境贴图
const textureCube = new THREE.CubeTextureLoader()
    .setPath('./环境贴图/环境贴图0/')
    .load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']);
new THREE.MeshStandardMaterial({
    metalness: 1.0,
    roughness: 0.5,
    envMap: textureCube, //设置pbr材质环境贴图
})    
javascript 复制代码
obj.material.envMap = textureCube; //设置环境贴图 

1、全部代码

javascript 复制代码
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const loader = new GLTFLoader()
const group = new THREE.Group()

//环境贴图
const textureCube = new THREE.CubeTextureLoader()
.setPath('./build/环境贴图1/')
.load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']);

loader.load('./build/金属.glb', function (gltf) {
    gltf.scene.traverse(function (obj) {
        if(obj.isMesh){
            obj.material.metalness = 1.0
            obj.material.roughness = 0
            obj.material.envMap = textureCube
        }
    })
    group.add(gltf.scene)
})

export default group 

2、环境贴图反射率.envMapIntensity

MeshStandardMaterial.envMapIntensity属性主要用来设置模型表面反射周围环境贴图的能力,或者说环境贴图对模型表面的影响能力。具体说.envMapIntensity相当于环境贴图的系数,环境贴图像素值乘以该系数后,在用于影响模型表面。

javascript 复制代码
// envMapIntensity:控制环境贴图对mesh表面影响程度
//默认值1, 设置为0.0,相当于没有环境贴图
obj.material.envMapIntensity = 1.0;

3、粗糙度 roughness为0

你可以尝试把粗糙度 roughness设置为0,看看模型对环境贴图的反射效果。

javascript 复制代码
obj.material.roughness = 0.0;//完全镜面反射,像镜子一样

4、纹理和渲染器颜色空间一致

javascript 复制代码
//如果renderer.outputEncoding=THREE.sRGBEncoding;环境贴图需要保持一致
textureCube.encoding = THREE.sRGBEncoding;   

4、环境贴图2

1、环境贴图作用测试

实际生活中光源照射到一个物体上,这个物体反射出去的光线也会影响其他的物体,环境贴图就是用一种简单方式,近似模拟一个物体周边环境对物体表面的影响。

测试:对于PBR材质,如果threejs三维场景不添加任何光源,物体就是完全黑色的,你可以不添加任何光源,尝试只使用环境贴图,你会发现物体表面的颜色也能看到,这说明环境贴图其实相当于提供了物体周围环境发射或反射的光线。

测试:更换不同明暗的环境贴图,你会发现场景中模型的明暗也有变化。

1、场景环境属性.environment

网格模型可以通过材质的.envMap属性设置环境贴图,如果一个gltf模型中所有的Mesh都要设置环境贴图就需要递归遍历gltf模型,给里面每个Mesh的材质设置.envMap

javascript 复制代码
loader.load("../工厂.glb", function (gltf) {
    // 递归遍历批量设置环境贴图
    gltf.scene.traverse(function (obj) {
        if (obj.isMesh) { //判断是否是网格模型
            obj.material.envMap = textureCube; //设置环境贴图
        }
    });
})

如果你希望环境贴图影响场景中scene所有Mesh,可以通过Scene的场景环境属性.environment实现,把环境贴图对应纹理对象设置为.environment的属性值即可。

javascript 复制代码
// 环境贴图纹理对象textureCube作为.environment属性值,影响所有模型
scene.environment = textureCube;

2、环境贴图色彩空间编码.encoding

javascript 复制代码
//如果renderer.outputEncoding=THREE.sRGBEncoding;环境贴图需要保持一致
textureCube.encoding = THREE.sRGBEncoding;   

注意:设置环境贴图后可以不设置光源,也可以显示出物体的样式

5、MeshPhysicalMaterial清漆层

MeshPhysicalMaterialMeshStandardMaterial都是拥有金属度metalness、粗糙度roughness属性的PBR材质,MeshPhysicalMaterial是在MeshStandardMaterial基础上扩展出来的子类,除了继承了MeshStandardMaterial的金属度、粗糙度等属性,还新增了清漆.clearcoat、透光率.transmission、反射率.reflectivity、光泽.sheen、折射率.ior等等各种用于模拟生活中不同材质的属性。

1、清漆层属性.clearcoat

清漆层属性.clearcoat可以用来模拟物体表面一层透明图层,就好比你在物体表面刷了一层透明清漆,喷了点水。.clearcoat的范围0到1,默认0。

javascript 复制代码
const material = new THREE.MeshPhysicalMaterial( {
	clearcoat: 1.0,//物体表面清漆层或者说透明涂层的厚度
} );

2、清漆层粗糙度.clearcoatRoughness

清漆层粗糙度.clearcoatRoughness属性表示物体表面透明涂层.clearcoat对应的的粗糙度,.clearcoatRoughness的范围是为0.0至1.0。默认值为0.0。

javascript 复制代码
const material = new THREE.MeshPhysicalMaterial( {
	clearcoat: 1.0,//物体表面清漆层或者说透明涂层的厚度
	clearcoatRoughness: 0.1,//透明涂层表面的粗糙度
} );

3、车外壳PBR材质设置

在设置车外壳清漆层之前,先创建一个MeshPhysicalMaterial材质,并设置好环境贴图、金属度、粗糙度,属性值先根据文档说明给一个大概的值,具体可以通过gui交互界面可视化调试。

javascript 复制代码
const mesh = gltf.scene.getObjectByName('外壳01');
mesh.material = new THREE.MeshPhysicalMaterial({
        color: mesh.material.color, //默认颜色
        metalness: 0.9,//车外壳金属度
        roughness: 0.5,//车外壳粗糙度
        envMap: textureCube, //环境贴图
        envMapIntensity: 2.5, //环境贴图对Mesh表面影响程度
})  

4、全部代码

javascript 复制代码
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const group = new THREE.Group();
const textureCube = new THREE.CubeTextureLoader().setPath('./build/环境贴图1/').load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'])
textureCube.encoding = THREE.sRGBEncoding;

const loader = new GLTFLoader();
loader.load('./build/轿车.glb', function (glb) {
    const mesh = glb.scene.getObjectByName('外壳01')
    mesh.material = new THREE.MeshPhysicalMaterial({
        color:mesh.material.color,
        // color:'red',
        metalness:1,//金属度
        roughness:0.5,//粗糙度
        envMap:textureCube,
        envMapIntensity:2.0,
        clearcoat:1.0,//清漆
        clearcoatRoughness:0.1,//清漆层粗糙度
    })
    group.add(glb.scene)
})

export default group 

6、物理材质透光率.transmission

1、透光率(透射度).transmission

为了更好的模拟玻璃、半透明塑料一类的视觉效果,可以使用物理透明度.transmission属性代替Mesh普通透明度属性.opacity

使用.transmission属性设置Mesh透明度,即便完全透射的情况下仍可保持高反射率。

物理光学透明度.transmission的值范围是从0.0到1.0。默认值为0.0。

javascript 复制代码
const mesh = gltf.scene.getObjectByName('玻璃01')
mesh.material = new THREE.MeshPhysicalMaterial({
    transmission: 1.0, //玻璃材质透光率,transmission替代opacity 
})

2、折射率.ior

非金属材料的折射率从1.0到2.333。默认值为1.5。

不同材质的折射率,你可以百度搜索。

javascript 复制代码
new THREE.MeshPhysicalMaterial({
    ior:1.5,//折射率
})

3、玻璃透光率.transmission设置

先设置玻璃金属度和粗糙度

javascript 复制代码
const mesh = gltf.scene.getObjectByName('玻璃01')
mesh.material = new THREE.MeshPhysicalMaterial({
    metalness: 0.0,//玻璃非金属 
    roughness: 0.0,//玻璃表面光滑
    envMap:textureCube,//环境贴图
    envMapIntensity: 1.0, //环境贴图对Mesh表面影响程度
})

设置透光率.transmission和折射率.ior

javascript 复制代码
new THREE.MeshPhysicalMaterial({
    transmission: 1.0, //玻璃材质透光率,transmission替代opacity 
    ior:1.5,//折射率
})

4、全部代码

javascript 复制代码
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const group = new THREE.Group();
const textureCube = new THREE.CubeTextureLoader().setPath('./build/环境贴图1/').load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'])
textureCube.encoding = THREE.sRGBEncoding;

const loader = new GLTFLoader();
loader.load('./build/轿车.glb', function (glb) {
    const mesh = glb.scene.getObjectByName('外壳01')
    mesh.material = new THREE.MeshPhysicalMaterial({
        color:mesh.material.color,
        // color:'red',
        metalness:1,//金属度
        roughness:0.5,//粗糙度
        envMap:textureCube,
        envMapIntensity:2.0,
        clearcoat:1.0,//清漆
        clearcoatRoughness:0.1,//清漆层粗糙度

    })

    const mesh1 = glb.scene.getObjectByName('玻璃01')
    mesh1.material = new THREE.MeshPhysicalMaterial({
        color:mesh1.material.color,
        metalness:0.0,//金属度
        roughness:0.0,//粗糙度,
        envMap:textureCube,
        envMapIntensity:1.0,
        transmission:1.0,//透光率
        ior:1.5,//折射率
    })
    group.add(glb.scene)
})

export default group 
相关推荐
韩大帅6661 天前
酒店客房拖鞋材质款式多样,对顾客入住感受影响大
材质
烟水寻常2 天前
UE5 材质淡入淡出
ue5·材质
weixin_460186132 天前
基于51单片机的自动洗衣机衣料材质proteus仿真
51单片机·proteus·材质
Tiger Z2 天前
R 语言科研绘图 --- 桑基图-汇总
开发语言·r语言·贴图
yaoshengvalve2 天前
V型球阀材质性能深度解析:专攻颗粒、料浆与高腐蚀介质的工业利器-耀圣
开发语言·网络·数据结构·c++·安全·材质
技术流浪者2 天前
PCB设计实践(十二)PCB设计电容选型:功能、材质、规则
硬件工程·材质·pcb工艺
优雅永不过时·2 天前
实现一个漂亮的Three.js 扫光地面 圆形贴图扫光
前端·javascript·智慧城市·three.js·贴图·shader
龙湾开发2 天前
计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 05.纹理贴图
c++·笔记·学习·3d·图形渲染·贴图
凌霜残雪2 天前
深入解析WPF中的3D图形编程:材质与光照
3d·wpf·材质
XuX033 天前
MATLAB绘制局部放大图
matlab·贴图