在Unity3D中实现后期效果

抽空写一下这个教程,之后可能会连续的发Havok Vision 的教程了。
就是这货。。

好了,进入正题,先上效果图
post_processing_final

主场景左侧Plane上显示的就是后期处理过的屏幕图形

流程如下
1.将主相机渲染出的纹理输出一个纹理
2.在主场景左侧创建一个Plane 使用材质 BlitMat
3.然后我们通过一个脚本,将相机渲染出来的纹理挂到材质 BlitMat上
4.通过BlitMat上的Shader 对整个场景的纹理进行处理,本例是灰度处理
5.将处理过的纹理还给主相机输出,或者如本例,放到一个Plane上输出

细节是这样的
先随便创建一个场景,差不多是这样
base_scenescene_build

主场景就一个 Plane地面, 一个Cube 一个Sphere

显示后期的Plane 叫 DisplayPlane
主相机 MainCamera
显示后期Plane的 Camera 叫 PostProcessingViewCamera

我们先编写后期处理用到的Shader如下
[cc language=”cpp”]
Shader “Custom/BlitShader” {
Properties {
_MainTex (“Diffuse Map”, 2D) = “diffuse” {}
}
SubShader {
ZTest Always Cull Off
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include “UnityCG.cginc”
sampler2D _MainTex;

struct vertInput{
float4 vertex : POSITION;
float2 tex : TEXCOORD0;
};

struct vertOutPut{
float4 pos : SV_POSITION;
float2 tex : TEXCOORD0;
};

vertOutPut vert(vertInput v)
{
vertOutPut o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.tex = v.tex;
return o;
};

float4 frag (vertOutPut i) : COLOR
{
float4 color = tex2D(_MainTex, i.tex);
float gray = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
return gray;
}
ENDCG
}

}
FallBack “Diffuse”
}
[/cc]

之后创建2个材质,都使用这个Shader 分别叫 BlitMat 用来后期处理 和 BlitMatDisplay 给Plane显示

然后编写脚本,将屏幕纹理赋予 BlitMatDisplay

[cc language=”csharpe”]
using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class Blit : MonoBehaviour {
public Material mat;
public Material displayMat;
public RenderTexture dstRT;
// Use this for initialization
void Start () {
dstRT = new RenderTexture(Screen.width, Screen.height, 16);
dstRT.wrapMode = TextureWrapMode.Repeat;
displayMat.SetTexture(“_MainTex”,dstRT);// 展示用材质
}

void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{
sourceTexture.wrapMode = TextureWrapMode.Repeat;
Graphics.Blit(sourceTexture, destTexture); //相机纹理原样输出 即 sourceTexture 拷贝到 destTexture
Graphics.Blit(sourceTexture, dstRT, mat); //材质纹理输出时,使用mat材质上的Shader进行处理后再输出
}

// Update is called once per frame
void Update () {

}
}
[/cc]

在Class前 写 [ExecuteInEditMode] 可以使代码在编辑器模式下运行
重点是这个 OnRenderImage 函数。 这个函数会在相机纹理全部绘制完毕后调用
其中 RenderTexture sourceTexture 是绘制好准备使用的相机纹理,RenderTexture destTexture 是相机将要用来输出的纹理
做后期效果就是在 sourceTexture->Shader->destTexture 中间的Shader做处理

然后将这个脚本挂到 MainCamera 上。
设置如图
main_camera_setting
这里有个细节,为了避免显示后期处理的Plane也被主相机捕获到,出现镜中镜的效果,我们将 DisplayPlane 的 Layer 设置为 UI,同时相机的 Culling Mask 把 UI 层剔除。这样主相机就看不到这个Plane了

然后是次相机设置 PostProcessingViewCamera
post_camera_setting
次相机只显示UI层的问题,同时设置投影方式为 正交投影。 这样看起来比较像个UI
ClearFlag 设置为 DepthOnly

最后运行场景,2个相机的纹理合并后,就是这样啦。

post_processing_final

发表评论

电子邮件地址不会被公开。 必填项已用*标注