最近同事在项目中遇到一个需求,要求将在两个显示器上显示同一个摄像机的内容,其实最简单的办法,就是在显示器设置中,将复制主屏的画面,对于更多的屏幕的输出,可以采用分屏器等硬件设备来实现,但是如果想对一个屏幕输出结果做一些处理,这种方法就么有办法解决了,实现的办法有很多种,本文主要介绍一种基于 RenderTexture 的方法。
实现思路
在了解需求的最开始,本来想通过两个 Camera 来分别对应两个显示器的输出,这种方法虽然能够解决问题,但是最大的缺点是,将会渲染两遍场景内物体,为了优化这一点,需要利用 RenderTexture 来实现,具体的实现思路如下:
- 创建两个Camera,Camera_01 输出到 Display 1,Camera_02 输出到 Display_02;
- 为了避免 Display_02 重复渲染两遍,将其 CullMask 设置为 Nothing;
- 在 Camera_01 上,通过 OnRenderImage 回调,将渲染结果存储到 RenderTexture;
- 在 Camera_02 上,读取上面存储的 RenderTexture,拷贝到后缓冲中;
具体实现
实现只有两部分,Camera_01 输出缓存,Camera_02 读取缓存并输出显示,先看Camera_01 实现缓存输出,代码如下:
1 | using System.Collections; |
上面代码的主要功能就是将 Camera 的渲染结果拷贝到一个 RenderTexture 进行缓存,并将结果输出到当先屏幕,这里有一点需要注意,Graphic.Blit(source,destination)
必须在 Graphic.Blit(source,_renderTexture)
之后进行调用,否则编辑器会报警告: OnRenderImage() possibly didn't write anything to the destination texture
,这并不是 Unity 的 Bug,而就这样的设计的,用户手册中给出的解释如下:
When OnRenderImage finishes, Unity expects that the destination render texture is the active render target. Generally, a Graphics.Blit or manual rendering into the destination texture should be the last rendering operation.
好了,接着说上面的实现,在 RenderTexture 创建完成之后,就需要在 Camera_02 上输出显示,具体的代码如下:
1 | using System.Collections; |
总结
经过简单测试,这种方法的 CPU 实现占用低于 1ms(测试结果根硬件有很大差别,我的测试环境是 3.2GHZ i5 处理器,显卡是 AMD Radeon R9 M380),但是在其他硬件上相差应该不会太大。
这种方式的优点如下:
- 实现简单高效;
- 其额外性能开销,与场景的复杂度无关;
缺点是只能显示与主屏相同的结果,或者进行一些图像后处理,比如夜视、颜色调整等等,没有办法针对场景内单独的物体进行渲染调整。