呀哈喽!这里是alphardex。
在使用three.js开发时,有时会感觉场景的渲染不是非常美观,本文就来一步一步地将一个不是很美观的场景重新焕发它的生机。
场景美化前:
场景美化后:
准备工作
首先在码上掘金上打开并fork这个初始场景
环境贴图
尽管已经有了2个光照,但模型还是显得非常暗,第一个任务就是要增加模型的亮度
该模型的主要材质是MeshStandardMaterial
,它是一种基于PBR的材质,PBR材质比较容易受光照的影响,但效果最显著的还是要靠环境贴图
环境贴图往往就是360°的全景照片,通常可以在polyhaven网站上找到,这里选用了最常见的potsdamer_platz来模拟城市的环境光
在kokomi.AssetManager中加载HDR素材(加载的背后用到了RGBELoader)
const am = new kokomi.AssetManager(
this,
[
{
name: "hdr",
type: "hdrTexture",
path: "https://kokomi-demo-1259280366.cos.ap-nanjing.myqcloud.com/potsdamer_platz_1k.hdr",
},
...
],
{
useDracoLoader: true,
}
);
用THREE.PMREMGenerator提取出envmap,应用到scene.environment
即可
const getEnvmapFromHDRTexture = (
renderer,
texture
) => {
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
const envmap = pmremGenerator.fromEquirectangular(texture).texture;
pmremGenerator.dispose();
return envmap;
};
const envMap = getEnvmapFromHDRTexture(this.renderer, am.items["hdr"]);
this.scene.environment = envMap;
输出编码
three.js默认的输出编码是线性编码(THREE.LinearEncoding
),这种编码会使场景看上去偏暗淡一点
为了获得一个色彩更加明艳的场景,我们需要将编码改为THREE.sRGBEncoding
this.renderer.outputEncoding = THREE.sRGBEncoding;
后期处理
如果说以上的两步是必经之路的话,那这一步可以算是画龙点睛了
Bloom
滤镜是最常用的滤镜之一,它可以照亮整个场景
SMAA
滤镜也是很常用的滤镜,它能消除场景中的锯齿,尤其是对这种顶点很多的模型颇为有效
this.scene.background = this.scene.background.convertSRGBToLinear();
const composer = new POSTPROCESSING.EffectComposer(this.renderer, {
frameBufferType: THREE.HalfFloatType,
multisampling: 8,
});
this.composer = composer;
composer.addPass(new POSTPROCESSING.RenderPass(this.scene, this.camera));
const bloom = new POSTPROCESSING.BloomEffect({
blendFunction: POSTPROCESSING.BlendFunction.ADD,
mipmapBlur: true,
luminanceThreshold: 1,
});
const smaa = new POSTPROCESSING.SMAAEffect();
const effectPass = new POSTPROCESSING.EffectPass(this.camera, bloom, smaa);
composer.addPass(effectPass);
this.renderer.autoClear = true;
使用了它们后,会发现场景除了无锯齿外并没有什么明显的变化,别急,好戏还在后头~
在这个场景中,车灯、轮胎灯、尾灯都用到了自发光贴图emissive map
,而这个贴图的显示效果跟材质的某个参数息息相关,这个参数是emissiveIntensity,将它调高就会使自发光的效果更加显著
此外,我们也要将材质的tonemapping给关闭,因为tonemapping会自动把颜色的RGB值限制在0-1内,达不到自发光的要求,解除了这个限制后,我们就会发现那些地方亮起来了
还有一个注意点:在Bloom
滤镜中,我们把luminanceThreshold
设为了1,这是为了防止场景的其他部分发亮,仅仅让那些有emissive map
的材质发亮