Skip to content

63. PBR 实战:汽车选配

Published:

学完 PBR 材质之后,我们就能做出车窗玻璃和车身的质感了,那这节就来实现一个汽车选配的效果。

image.png

首先分析下思路:

加载汽车模型后,遍历找到车身和车窗的网格模型,调节材质为 MeshPhysicalMaterial 物理网格材质,设置环境贴图 envMap,并且调节车窗的透光率、车身的清漆度等,就可以实现一个比较逼真的质感。

接下来就开始写:

npx create-vite car-config

image.png

进入项目,安装依赖:

npm install
npm install --save three
npm install --save-dev @types/three

改下 src/main.js

import './style.css';
import * as THREE from 'three';
import {
    OrbitControls
} from 'three/addons/controls/OrbitControls.js';
import mesh from './mesh.js';

const scene = new THREE.Scene();

scene.add(mesh);

const directionLight = new THREE.DirectionalLight(0xffffff, 10);
directionLight.position.set(100, 100, 100);
scene.add(directionLight);

const ambientLight = new THREE.AmbientLight();
scene.add(ambientLight);

const helper = new THREE.AxesHelper(100);
scene.add(helper);

const width = window.innerWidth;
const height = window.innerHeight;

const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 10000);
camera.position.set(100, 100, 100);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height)

function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

render();

document.body.append(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);

window.onresize = function () {
    const width = window.innerWidth;
    const height = window.innerHeight;

    renderer.setSize(width,height);

    camera.aspect = width / height;
    camera.updateProjectionMatrix();
};

创建 Scene、Light、Camera、Renderer。

改下 style.css

body {
  margin: 0;
}

写下 mesh.js

import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const loader = new GLTFLoader();

const mesh = new THREE.Group();

loader.load("./car.glb", function (gltf) {
    console.log(gltf);
    mesh.add(gltf.scene);
    gltf.scene.traverse((obj) => {
        if(obj.isMesh) {
            console.log(obj.name, obj);
        }
    });
});

export default mesh;

下载这个 glb 文件到 public 目录下:

image.png

image.png

用 GLTFLoader 加载车的模型。

先跑下:

npm run dev

image.png

image.png

车模型太小了,调大一点:

image.png

gltf.scene.scale.set(40, 40, 40);

image.png

打开 devtools 看下,它有非常多的汽车部件的 mesh:

2025-04-10 12.32.46.gif

找到车窗、车身这俩 mesh,看下材质:

image.png

image.png

image.png

都是物理网格材质 MeshPhysicalMaterial,那我们就可以直接改了。

把上节的天空盒图片下载下来,放到 public 目录下:

image.png

然后加载纹理作为环境贴图 envMap:

image.png

const textureCube = new THREE.CubeTextureLoader()
    .setPath('./forest/')
    .load(['px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png']);
if(obj.material.isMeshPhysicalMaterial) {
    obj.material.envMap = textureCube;
    obj.material.envMapIntensity = 2;
}

不只是车身和车窗要设置环境贴图,所有的物理网格材质都要设置下。

之前车是这样:

image.png

加上环境贴图后是这样:

image.png

之后调节下车身的材质:

image.png

if(obj.name ==='车身') {
    obj.material.metalness = 0.9;
    obj.material.roughness = 0.2;
    obj.material.clearcoat = 1;
    obj.material.clearcoatRoughness = 0;
}

设置金属度 metalness 为 0.9,因为车身一般是金属的。

粗糙度 roughness 设置 0.2,比较光滑的感觉。

看下效果:

image.png

现在车身就比较真实了。

然后再调一下车窗玻璃的材质:

image.png

if(obj.name === '车窗') {
    obj.material.color.set('white');
    obj.material.transmission= 1;
    obj.material.ior = 1.3;
}

设置完全透光、调节下折射率。

image.png

现在就能看到车内部了。

之前光线强度太强了,改成 1:

image.png

然后我们加上 GUI 来调节这些参数:

image.png

image.png

image.png

const gui = new GUI();
const body = gui.addFolder('车身');
const win = gui.addFolder('车窗');
body.addColor(obj.material, 'color');
body.add(obj.material, 'metalness', 0, 1);
body.add(obj.material, 'roughness', 0, 1);
body.add(obj.material, 'clearcoat', 0, 1);
body.add(obj.material, 'clearcoatRoughness', 0, 1);
win.addColor(obj.material, 'color');
win.add(obj.material, 'transmission', 0, 1);
win.add(obj.material, 'ior', 1, 2.3);
win.add(obj.material, 'metalness', 0, 1);
win.add(obj.material, 'roughness', 0, 1);

image.png

image.png

案例代码上传了小册仓库

总结

这节我们练习了下 PBR 材质。

加载了车的模型,然后遍历找到车窗、车身的 mesh,修改 PBR 材质的金属度 metalness、粗糙度 roughness、清漆层 clearcoat、透光率 transmission、折射率 ior 等,就可以实现真实的车窗、车身的效果。

然后加上了 GUI 来可视化的调试,大家自己调一下看看效果,就能更好的理解 PBR 材质了。

评论