在three.js中我们使用webGPU渲染,只需要简单的几步就可以实现这种车身速度光线流动的效果。

实现地面倒影效果

地面倒影效果我们可以用three.js中webGPU的reflector来实现,首先先创建一个平面对象,然后对这个对象应用PBR材质,让地面更具质感。

 const textureLoader = new THREE.TextureLoader();
 const floorColor = textureLoader.load("textures/floor/map.jpg");
 floorColor.wrapS = THREE.RepeatWrapping;
 floorColor.wrapT = THREE.RepeatWrapping;
 floorColor.colorSpace = THREE.SRGBColorSpace;

 const floorNormal = textureLoader.load("textures/floor/normal.jpg");
 floorNormal.wrapS = THREE.RepeatWrapping;
 floorNormal.wrapT = THREE.RepeatWrapping;

 const floorMaterial = new THREE.MeshStandardNodeMaterial();
 floor.material = floorMaterial;

然后创建reflector对象,让地面可以显示倒影,在地面已有的材质上叠加倒影贴图。

reflection = reflector({ resolution: 0.8 });
reflection.target.rotateX(-Math.PI / 2);
reflection.uvNode = reflection.uvNode!.add(floorNormalOffset);
scene.add(reflection.target);

floorMaterial.colorNode = texture(floorColor, floorUV)
  .add(reflection.mul(3))
  .sub(0.017);

隧道线条流动效果

实现这个效果我们可以创建一个圆柱体,可以用代码创建或者在blender里创建,在blender里创建的好处是更简单可控一些。创建好后我们可以对这个圆柱体应用一张线条贴图,让贴图在圆柱体上重复显示。

设置好贴图后,我们可以用TSL对贴图生成UV动画,TSL是Three.js Shading Language的缩写,写一次代码就可以自动编译成GLSL或webGPU的WGSL语言,以往实现这种简单顶点动画需要在shader里写许多代码,TSL的出现极大的简化了这个工作量。

 tunnel.material.colorNode = texture(material.map, uv().sub(vec2(time, 0).mul(2)));

设置车身的动态环境贴图

动态环境贴图我们可以用three.js中的CubeCamera,原理是在场景中设置一个虚拟摄像机,这个摄像机可以实时的将场景渲染成一个环境贴图。

const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(1024);
cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);

然后在渲染的每帧中调用CubeCamera的update方法实时渲染场景贴图。

cubeCamera && cubeCamera.update(renderer, scene);  

最后将渲染好的贴图应用到车子的envMap属性上就大功告成啦。

car.traverse((child) => {
  if (child.isMesh) {
    child.material.envMapIntensity = 5;
    child.material.envMap = cubeRenderTarget.texture;
  }
});