屏幕后处理的基本原理
一、什么是屏幕后处理
屏幕后处理效果(Screen Post-Processing Effects)是一种在渲染管线的最后阶段应用的视觉效果
允许你在场景渲染完后对最终图像进行各调整和效果处理,从而增强视觉体验
常见的屏幕后处理效果:
景深、模糊、色彩调整 等等
二、基本原理
最关键的问题: 1. 如何获取游戏画面渲染完毕后的画面信息 2. 如何为 获取到的画面信息添加自定义效果
解决方法: 1. 如何获取游戏画面渲染完毕后的画面信息
在Unity中获取纹理有三种常用方法 - RendererTexture - GrabPass - OnRenderImage
我们在处理屏幕后期处理效果时,会使用
OnRenderImage函数来获取游戏画面渲染完毕后的画面信息 2. 如何为 获取到的画面信息添加自定义效果
主要思路是将获取到的游戏画面 作为自定义Shader的主纹理
通过自定义Shader利用捕获的画面来实现自定义效果
三、捕获画面的关键——OnRenderImage函数
OnRenderImage函数
它是继承了MonoBehaviour的脚本中能够被自动调用的函数(类似于生命周期函数)
它会在图像的渲染操作完成后调用
固定写法: 1
2
3
4
5//第一个参数:原渲染纹理,当前渲染得到的屏幕图像存储在该函数中
//第二个参数:目标渲染纹理,将经过处理的的图像写入到目标纹理中用于最终的显示
void OnRendererImage(RenderTexture source,RenderTexture destination)
{
}
通过该函数我们便可以得到当前渲染纹理的游戏画面
并在该函数中对画面对应的渲染纹理进行处理后用于最终显示
注意:
该函数得到的原纹理默认为所有不透明和透明的Pass执行完毕后调用的
基于该纹理进行修改,会对游戏场景中所有的游戏对象产生影响
如果想要在不透明的Pass执行完毕后就调用该函数,需要在该函数前添加[ImageEffetQpaque]
四、实现效果的关键——Graphics.Blit函数
主要用于将一个图像从一个纹理复制到另一个纹理
这里只讲常用的几个重载: 1. 将源纹理直接复制到目标纹理 Graphics.Blit(Texture soure,RenderTexture dest) 2. 将源纹理复制到目标纹理并应用一个材质 Graphics.Blit(Texture source,RenderTexture dest,Material mat,int Pass = -1) - 参数一:源纹理 - 参数二:目标纹理 - 参数三:应用材质 source纹理会被传递到材质中Shader 并应用到名为_MainTex的纹理属性中 - 参数四:调用Shader中Pass的索引。-1为依次调用全部的Pass 且默认为-1
1 | void OnRendererImage(RenderTexture source,RenderTexture destination) |
五、屏幕后处理基类
1.补充知识
材质球中的 HideFlags 枚举 从材质球对象中可以点出 HideFlags 枚举 - HideFlags.None:对象是完全可见和可编辑的。这是默认值。 - HideFlags.HideInHierarchy:对象在层级视图中被隐藏,但仍然存在于场景中。 - HideFlags.HideInInspector:对象在检査器中被隐藏,但仍然存在于层级视图中。 - HideFlags.DontSaveInEditor:对象不会被保存到场景中。适用于编辑器模式,不会影响播放模式 - HideFlags.NotEditable:对象在检査器中是只读的,不能被修改。 - HideFlags.DontSaveInBuild:对象不会被包含在构建中。 - HideFlags.DontUnloadUnusedAsset:对象在资源清理时不会被卸载,即使它没有被引用。 - HideFlags.DontSave:过象不会被保存到场景中,不会在构建中保存,也不会在编辑器中保存。 这是DontSaveInEditor | DontSaveInBuild | DontUnloadUnusedAsset 的组合。
注意: 如果想要设置枚举满足多个条件 直接多个枚举 进行位或运算即可
2.为什么要实现屏幕后处理的基类
- 为了实现屏幕后处理的效果,我们每一次都要做几件事
- 实现一个继承自MonoBehavior的自定义基类脚本
- 关联对应的材质球或者Shader
- 实现OnRendererImage函数
- 在OnRenderImage函数中使用Graphics.Blit函数
再在子类中去实现各自的基本逻辑 - 我们可以在基类中动态的创建材质球 不需要为每一个后处理效果都手动的创建材质球 只需要在Inspector窗口中关联对应的Shader即可
- 在屏幕后处理之前,我们往往需要一系列的检查某一些条件是否满足
比如:
当前平台是否支持当前使用的UnityShader(Shader.isSupported),这可以在基类中判断,避免重复书写
3.实现基类功能
- 声明基类功能,让其依赖Camera,并且让其在编辑模式下可以运行,保证我们随时可以看见效果
- 基类中声明 公共Shader 用于在Inspector窗口中关联
- 基类中声明 私有的Material 用于动态创建
- 基类中实现判断Shader是否可用 并且动态创建Material的方法
- 基类中是实现OnRenderImage的虚方法,完成基本逻辑
1 | [] |