问题
当我们在threejs中使用loader方法,加载已经绘制好的三维模型,当我们在三维建模软件中,我们可以看到三维模型有材质贴图,但当使用threejs加载时,材质呈现黑色或者与原有材质相差很大。
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - exporter - gltf</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setClearColor('pink')
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 设置相机控件轨道控制器OrbitControls
let controls = new OrbitControls(camera, renderer.domElement);
controls.listenToKeyEvents(window);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = true;
controls.minDistance = 1;
controls.maxDistance = 500;
controls.maxPolarAngle = Math.PI / 2;
const loader = new GLTFLoader();
loader.load(
// 模型文件的路径
'models/xxx.gltf',
// 加载完成后的回调函数
function (gltf) {
scene.add(gltf.scene);
gltf.scene.position.set(0, 0, 0);
// 可以对每个mesh进行单独的设置
gltf.scene.traverse(function (obj) {
if (obj.isMesh) {//判断是否是网格模型
}
});
}
);
renderer.outputEncoding = THREE.sRGBEncoding;
const animate = function () {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
};
animate();
</script>
</body>
</html>
解决方案
1.如果材质呈现黑色,添加物体自发光
gltf.scene.traverse(function (obj) {
if (obj.isMesh) {//判断是否是网格模型
obj.material.emissive = obj.material.color;
obj.material.emissiveMap = obj.material.map ;
}
});
2.如果模型材质受光源影响(除了MeshBasicMaterial),添加光源
解决方案第一步:如果模型的材质是MeshLambertMaterial、MeshPhongMaterial、MeshStandardMaterial以及MeshPhysicalMaterial,如下图,需要在三维场景中添加光源
。
const light = new THREE.AmbientLight(0xffffff, 10);
scene.add(light);
添加光源后,可视化效果可以看出模型的材质颜色,但缺失一些细节信息,例如金属度、粗糙度、物理材质透光率等物理属性,则可能是光源设置强度过大,或者光源位置不正确
。
// 合适的光源强度及位置,可以让三维模型材质正确显示
const light = new THREE.AmbientLight(0xffffff, 0.3);
scene.add(light);
const dirLight1 = new THREE.DirectionalLight('rgb(253,253,253)', 5);
scene.add(dirLight1);