当我单纯地用MTLLoader引入材质, OBJLoader引入模型并添加到场景中时, 发现模型非常得暗. 需要将环境光的强度设置到3.5左右看起来才比较正常. 但正常情况下环境光的值不应该超出1. 研究了网上提供几种不同的方式, 再加上TS对类型的限制导致绕了些弯路.
需要调整的地方有两个, 模型材质的自发光emissive 以及渲染器renderer的渲染输出方式outputEncoding. 通过控制台输出OBJ的子对象可以看到其材质的自发光emissive是没有设置颜色的( Color为一个包含rgb颜色属性的对象, ThreeJS提供了其类型, 可以自己定义color对象并用Color类型作类型断言), emissiveMap也没有配置.
另外可以调整渲染器的toneMapping来调整模型的效果, 比如 renderer.toneMapping = ThreeJS.ACESFilmicToneMapping;
现贴上部分代码和方法.
1 import * as ThreeJS from 'three'; 2 // OBJ模型子项的类型需要自己在控制台输出查看 3 import { Mesh, MeshPhongMaterial, sRGBEncoding } from 'three'; 4 import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader'; 5 import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'; 6 7 // ...省略代码 8 9 const mtlLoader = new MTLLoader(); 10 const objLoader = new OBJLoader(); 11 mtlLoader.load('/model/body/body.mtl', (material) => { 12 material.preload(); 13 // mtl文件中的材质设置到obj加载器 14 objLoader.setMaterials(material); 15 objLoader.load( 16 'model/body/body.obj', 17 (obj) => { 18 // 设置模型大小 19 // obj.scale.set(2, 2, 2); 20 // 设置模型位置 21 obj.position.set(0, 0, 0); 22 obj.children.forEach((child) => { 23 const c = child as Mesh; 24 const cm = c.material as MeshPhongMaterial; 25 cm.emissive = cm.color; 26 cm.emissiveMap = cm.map; 27 }); 28 scene.add(obj); 29 }, 30 (xhr) => { 31 console.log(`${(xhr.loaded / xhr.total) * 100}% loaded`); 32 }, 33 (error) => { 34 console.log('An error happened', error); 35 } 36 ); 37 }); 38 // ...省略代码 39 const renderer = new ThreeJS.WebGLRenderer(); 40 renderer.outputEncoding = sRGBEncoding;
关于emissive属性的补充说明可以看这篇文章: https://www.jianshu.com/p/f9d81761ce2f
关于renderer渲染器的输出可以参考这篇文章: https://www.jb51.net/article/256430.htm
浙公网安备 33010602011771号