参考资料
- PBR材质简介
- ...
- 三维软件导出PBR材质属性
知识点
注:基于Three.jsv0.155.0
- PBR材质简介
- PBR材质金属度和粗糙度:
metalness
、roughness
- 环境贴图.envMap(金属效果):
CubeTextureLoader
、envMapIntensity
- MeshPhysicalMaterial清漆层:
clearcoat
、clearcoatRoughness
- 物理材质透光率
.transmission
、折射率.ior
- 三维软件导出PBR材质属性
PBR材质简介
所谓PBR就是,基于物理的渲染(physically-based rendering)
-
网格模型材质
- MeshLambertMaterial: Lambert光照模型(漫反射)
- MeshPhongMaterial:Phong光照模型(漫反射、高光反射)
- MeshStandardMaterial和MeshPhysicalMaterial:基于物理的光照模型(微平面理论、能量守恒、菲涅尔反射...)
PBR材质相比MeshLambertMaterial和MeshPhongMaterial可以提供更逼真的、更接近生活中的材质效果,当然也会占用更多的电脑硬件资源。
通过MeshPhysicalMaterial文档,提供的资源,可以查看多个PBR材质的案例效果,系统课程中轿车展示案例也会用到PBR材质
-
渲染占用资源和表现能力
占用渲染资源 MeshBasicMaterial < MeshLambertMaterial < MeshPhongMaterial < MeshStandardMaterial < MeshPhysicalMaterial
渲染表现能力 MeshBasicMaterial < MeshLambertMaterial < MeshPhongMaterial < MeshStandardMaterial < MeshPhysicalMaterial
代码实现
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three.js</title>
</head>
<body>
</body>
<!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 -->
<script type="importmap">
{
"imports": {
"three": "./js/three.module.js",
"three/addons/": "../three.js/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
const width = window.innerWidth
const height = window.innerHeight
// 场景
const scene = new THREE.Scene();
const cubeTexture = new THREE.CubeTextureLoader()
.setPath('./img/环境贴图3/')
.load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'])
const loader = new GLTFLoader();
// 加载工厂文件
loader.load('assets/金属.glb', function(gltf) {
// 模型
const model = gltf.scene;
// 遍历模型
model.traverse(function(child){
// 判断是否为网格
if(child.isMesh){
// 设置材质
child.material = new THREE.MeshStandardMaterial({
metalness: 1.0,//金属度属性
roughness: 0.5,//粗糙度属性
envMap: cubeTexture,//环境贴图
envMapIntensity: 0.5,//环境贴图强度
})
}
});
scene.add(model);
})
const loader2 = new GLTFLoader();
// 加载工厂文件
loader2.load('assets/轿车.glb', function(gltf) {
// 模型
const model = gltf.scene;
model.position.set(100, 100, 100);
console.log('🚀 ~ file: 7PBR材质与纹理贴图.html:61 ~ loader2.load ~ model:', model)
var waike = model.getObjectByName('外壳01')
waike.material = new THREE.MeshPhysicalMaterial({
color: waike.material.color,
clearcoat: 1.0, //物体表面清漆层或者说透明涂层的厚度
clearcoatRoughness: 0.1, //物体表面清漆的粗糙度
metalness: 0.5, //金属度属性
roughness: 0.5, //粗糙度属性
envMap: cubeTexture,//环境贴图
envMapIntensity: 0.5,//环境贴图强度
})
var boli = model.getObjectByName('玻璃01')
boli.material = new THREE.MeshPhysicalMaterial({
color: boli.material.color,
transmission: 1, //透射属性
ior:1.5,//折射率
metalness: 0.0, //金属度属性
roughness: 0, //粗糙度属性
envMap: cubeTexture,//环境贴图
envMapIntensity: 0.5,//环境贴图强度
})
scene.add(model);
})
// 点光源
const pointLight = new THREE.PointLight( 0xffffff, 1.0, 0, 0);
pointLight.position.set(200, 200, 200 );
scene.add( pointLight );
// 环境光
const ambientLight = new THREE.AmbientLight( 0xffffff, 1);
scene.add( ambientLight );
// 坐标系
const axes = new THREE.AxesHelper(200);
scene.add(axes);
// 相机
const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 3000);
camera.position.set(348, 403, 362);
camera.lookAt(0, 0, 0);
// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.render(scene, camera);
document.body.appendChild(renderer.domElement);
renderer.outputColorSpace = THREE.SRGBColorSpace;//设置为SRGB颜色空间
const controls = new OrbitControls(camera, renderer.domElement);
// 渲染循环
function render() {
renderer.render(scene, camera);
// console.log('🚀 ~ file: 7PBR材质与纹理贴图.html:110 ~ render ~ camera:', camera.position)
requestAnimationFrame(render);
}
render();
// 控制器
controls.addEventListener('change', () => {
// 因为动画渲染了,所以这里可以省略
renderer.render(scene, camera);
});
</script>
</html>