玩过blender的都知道,我们建立模型后,如果需要呈现光照效果或生成精细化美工渲染图,我们需要使用blender的烘焙功能,而这个功能在前端也是可以实现的,今天我无意中发现一个webgl的烘焙库three-gpu-pathtracer
效果如下:未烘焙的图像
烘焙后的图像
我们可以清晰地看到经过烘焙的图像有了光影的变化,同时模型表面纹理也更加细致。但是由于我设备的原因,无法呈现出高质量的渲染效果,也是依然能够明显看到这二者的差别的。
如果电脑GPU性能足够强大强烈推荐这个库来渲染高精度的渲染图,该库是我目前见到的最好的threejs烘焙引擎。
具体的示例代码如下:(该代码源自 该仓库的README.MD文件)
import * as THREE from 'three';
import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
import {
PathTracingSceneGenerator,
PathTracingRenderer,
PhysicalPathTracingMaterial,
} from 'three-gpu-pathtracer';
// init scene, renderer, camera, controls, etc
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
// 初始化路径跟踪材质和渲染器
const ptMaterial = new PhysicalPathTracingMaterial();
const ptRenderer = new PathTracingRenderer( renderer );
ptRenderer.setSize( window.innerWidth, window.innerHeight );
ptRenderer.camera = camera;
ptRenderer.material = ptMaterial;
// 开启透明北京
ptRenderer.alpha = true;
// init quad for rendering to the canvas
const fsQuad = new FullScreenQuad( new THREE.MeshBasicMaterial( {
map: ptRenderer.target.texture,
// 设置透明背景
blending: THREE.CustomBlending,
} ) );
// 更新模型矩阵数据
scene.updateMatrixWorld();
// 初始化场景和材质
const generator = new PathTracingSceneGenerator();
const { bvh, textures, materials, lights } = generator.generate( scene );
// 更新bvh和几何体属性
ptMaterial.bvh.updateFrom( bvh );
ptMaterial.attributesArray.updateFrom(
geometry.attributes.normal,
geometry.attributes.tangent,
geometry.attributes.uv,
geometry.attributes.color,
);
// 更新材质到纹理阵列
ptMaterial.materialIndexAttribute.updateFrom( geometry.attributes.materialIndex );
ptMaterial.textures.setTextures( renderer, 2048, 2048, textures );
ptMaterial.materials.updateFrom( materials, textures );
// 更新光线
ptMaterial.lights.updateFrom( lights );
// 设置环境贴图
const texture = await new RGBELoader().setDataType( THREE.FloatType ).loadAsync( envMapUrl );
ptRenderer.material.envMapInfo.updateFrom( texture );
animate();
function animate() {
camera.updateMatrixWorld();
ptRenderer.update();
fsQuad.material.map = ptRenderer.target.texture;
fsQuad.render( renderer );
}