背景:
在 Three.js
中,地面反射效果可以通过多种方式实现,常见的有 SSR(屏幕空间反射)、Reflector
和 CubeCamera
。每种方法都有各自的优缺点,下面是它们的介绍和对比:
1. SSR (Screen Space Reflection, 屏幕空间反射)
- 简介: SSR 是一种基于屏幕空间的反射技术,它通过追踪屏幕上可见像素的路径来实现反射。这意味着它只反射屏幕中已经渲染的部分,能在复杂的场景中生成实时反射效果。
- 优点:
- 计算效率相对较高,不需要额外的镜头或几何体。
- 能产生动态反射,实时反映场景中物体的变化。
- 适用于复杂几何形状和不规则表面。
- 适合大规模的动态场景,不需要额外的摄像头来更新反射贴图。
- 缺点:
- 只能反射屏幕上可见的物体,超出屏幕边界的内容无法被反射。
- 反射的物体可能存在失真或错误(尤其是边缘区域)。
- 不适合处理镜头外的反射效果,比如在场景边缘的反射可能缺失。
- 依赖屏幕分辨率,因此高分辨率下可能对性能有较大影响。
2. Reflector
- 简介:
Reflector
是Three.js
内置的一种镜面效果实现,它通过在场景中创建一个虚拟的镜子对象,并根据摄像机的视角实时渲染该对象的反射。 - 优点:
- 实现简单,内置于
Three.js
,只需添加Reflector
对象即可。 - 能生成精确的反射,包括屏幕外的物体,也可以在场景边缘有良好的反射效果。
- 适合平面或规则几何体的反射,比如地面、水面、墙壁等。
- 在特定情况下,能高效地提供高质量的反射。
- 实现简单,内置于
- 缺点:
- 仅适用于平面反射,对于复杂的几何形状或不规则表面难以使用。
- 需要对反射平面进行单独渲染,因此会增加一定的性能开销。
- 不适合动态场景中的高频率反射,因为每次视角变化都需要重新渲染反射内容。
3. CubeCamera
- 简介:
CubeCamera
是一种通过六个方向同时渲染场景并生成立方体贴图的方式。它捕捉整个场景并生成一个立方体贴图,可以用于反射和环境映射。 - 优点:
- 可以捕捉整个 360° 场景,因此适合处理复杂环境反射,比如球体反射、汽车反射等。
- 可以反射屏幕外的所有物体,反射内容较为全面。
- 生成的反射贴图可以用于多种效果(例如环境贴图)。
- 缺点:
- 每次反射更新时,摄像机需要渲染六个方向,性能开销较大,尤其是在复杂场景中可能导致帧率下降。
- 实时反射性能开销高,适合静态或少量更新的场景(例如汽车在静态场景中的反射)。
- 对于实时动态反射,CubeCamera 的开销远大于 SSR 和 Reflector,实时更新立方体贴图在性能上会有较大影响。
总结:以上都是gpt搜的,可以了解下,下面直接上干货,以下是本人逐项测试后的心得,建议。
想实现地面镜面反射:Reflector
想实现地面渐变模糊,细节反射:SSR (官方demo案例:webgl_postprocessing_ssr)
想实现地面color纹理,渐变模糊,反射等多种复合效果的:CubeCamera
原因:对于美术来说,CubeCamera是作为反射贴图贴入到PBR材质上,所以材质的其他属性都可以混合使用,不需要开发shader或者基于封装好的插件,就可以实现达到想要的效果,简单粗暴。性能来说,静态场景目前测试是以上中最低的,不管帧率和cpu占用都是首选。
CubeCamera具体应用:
const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(1024, {
format: THREE.RGBFormat,
generateMipmaps: true,
minFilter: THREE.LinearMipmapLinearFilter,
});
cubeCamera = new THREE.CubeCamera(0.01, 1000, cubeRenderTarget);
cubeCamera.lookAt(0, 0, 0);
scene.add(cubeCamera);
console.log(cubeCamera, cubeRenderTarget);
// 渲染循环中添加以下代码
let tPos = camera.position;
// 数字部分必须设置反射平面的位置
cubeCamera.position.set(tPos.x, -0.724 - (tPos.y + 0.724), tPos.z);
cubeCamera.update(renderer, scene);
踩坑
代码很简单,但是实际应用会有很多坑,小白如果不懂的话,直接复制,改参数,重要是听劝会少走很多弯路
1.cubeCamera.position 的设定的位置一定要用这个计算,只需要找到反射面的模型,取出世界坐标的位置即可,一般是模型师提供,如果自己会三维软件的话可以自己动手获取。一旦这个不对,整个反射上去也对应不上实际场景。
2.平面反射材质,用MeshPhongMaterial,如果用MeshPhysicalMaterial会不清晰,出现模糊,而且这种情况是提高参数不能改善的。以下是本人案例中的,仅供参考。
var plane1_MA = new THREE.TextureLoader().load("./textures/plane2_color.jpg");
var plane1_M = new THREE.MeshPhongMaterial({
color: 0xffffff,
map: plane1_MA,
shininess: 0,
emissive: 0xffffff,
emissiveIntensity: 0.1,
reflectivity: 0.08,
refractionRatio: 0.98,
blending: 1,
blendEquation: 1,
depthFunc: 3,
opacity: 1,
transparent: true,
});
3.材质参数上,如果以上添加好了,还没有看到反射,那需要调试参数,reflectivity 反射度开到1,
envMapIntensity开高,1-5之间测试,正常情况都是可以看到反射效果。