基本的屏幕后处理脚本系统
OnRenderImage函数:得到渲染后的屏幕图像,即抓取屏幕,声明如下:
MonoBehaviour.OnRenderImage(RenderTexture src,RenderTexture dest)
当我们在脚本中声明此函数后,Unity 会把当前渲染得到的图像存储在第一一个参 数对应的源渲染纹理中,通过函数中的一- 系列操作后,再把目标渲染纹理,即第二个参数对应的渲染纹理显示到屏幕上。在OnRenderImage函数中,我们通常是利用Graphics.Blit函数来完成对渲染纹理的处理。它有3种函数声明:
public static void Blit (Texture src, RenderTexture dest) ;
public static void Blit (Texture src, RenderTexture dest, Material mat, int pass = -1);
public static void Blit (Texture src, Material mat, int pass = -1) ;
src:源纹理,在屏幕后处理技术中通常是当前屏幕的渲染纹理或是上一步处理后得到的渲染纹理。
dest:目标渲染纹理,如果为null直接将结果显示在屏幕上。
mat:使用的材质,这个材质使用的shader将会进行各种屏幕后处理操作,而src纹理将会被传递给shader中名为_MainTex的纹理属性。
pass:默认值为-1,表示会依次调用shader中的所有pass,否则只会调用给定索引的pass。
在默认情况下,OnRenderImage函数会在所有的不透明和透明的Pass执行完毕后被调用,以便对场景中所有游戏对象都产生影响。但有时,我们希望在不透明的Pass (即渲染队列小于等于2500的Pass,内置的Background、Geometry和AlphaTest渲染队列均在此范围内)执行完毕后立即调用OnRenderImage函数,从而不对透明物体产生任何影响。此时,我们可以在OnRenderlmage函数前添加ImageEffectOpaque属性来实现这样的目的。
因此,要在Unity中实现屏幕后处理效果,过程通常如下:我们首先需要在摄像中添加一个用于屏幕后处理的脚本。在这个脚本中,我们会实现OnRenderImage函数来获取当前屏幕的渲染纹理。然后,再调用Graphics.Blit函数使用特定的Unity Shader 来对当前图像进行处理,再把返回的渲染纹理显示到屏幕上。对于一些复 杂的屏幕特效,我们可能需要多次调用Graphics.Blit 函数来对上一步的输出结果进行下-步处理。
但是,在进行屏幕后处理之前,我们需要检查一系列条件 是否满足,例如当前平台是否支持渲染纹理和屏幕特效,是否支持当前使用的Unity Shader 等。为此,我们创建了一个用于屏幕后处理效果的基类,在实现各种屏幕特效时,我们只需要继承自该基类,再实现派生类中不同的操作即可。
PostEffectsBase.cs主要代码如下:
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
[RequireComponent (typeof(Camera))]
public class PostEffectsBase : MonoBehaviour {
// Called when start
protected void CheckResources() {
bool isSupported = CheckSupport();
if (isSupported == false) {
NotSupported();
}
}
// Called in CheckResources to check support on this platform
protected bool CheckSupport() {
if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false) {
Debug.LogWarning("This platform does not support image effects or render textures.");
return false;
}
return true;
}
// Called when the platform doesn't support this effect
protected void NotSupported() {
enabled = false;
}
protected void Start() {
CheckResources(); //检查各种资源和条件是否满足
}
// Called when need to create the material used by this effect
//第一个参数制定了该特效需要使用的shader,第二个参数则是用于后期处理的材质
protected Material CheckShaderAndCreateMaterial(Shader shader, Material material) {
if (shader == null) {
return null;
}
if (shader.isSupported && material && material.shader == shader)
return material;
if (!shader.isSupported) {
return null;
}
else {
material = new Material(shader);
material.hideFlags = HideFlags.DontSave;
if (material)
return material;
else
return null;
}
}
}
所有屏幕后处理效果都要绑定在某个摄像机上。
