1. 概述

一般来说,图形渲染引擎都会把帧缓冲(Framebuffer)技术封装成两个接口,其中之一就是后处理(Post-process)。直观来理解,后处理指的是场景在渲染完成之后,不进入屏幕的颜色缓冲区,而是暂时进入帧缓冲区;在对帧缓冲区的画面进行处理之后,再进入颜色缓冲区被屏幕显示出来。这个步骤只处理二维的画面,所以有点像图像处理的过程,或者可以看成对二维画面进行PS。

2. 详论

2.1. 实现

第一点需要明确的是,Unity后处理既不是写在脚本类MonoBehaviour的Start()中,也不是写在Update()中,而是写在专门的函数OnRenderImage()中。这是由内置渲染流水线决定的:在相机渲染整个场景完成之后,最后再进行全屏后期处理效果。因而,处理后处理的脚本,需要Camera组件。

在Unity中创建随意一个场景,创建一个脚本挂到Camera游戏对象上:

using UnityEngine;

[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class Note11Main : MonoBehaviour
{
public Material material; // Start is called before the first frame update
void Start()
{ } // Update is called once per frame
void Update()
{ } private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
Graphics.Blit(source, destination, material);
}
}

传入的材质使用的Shader为:

Shader "Custom/PostProcessingTest"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
}; struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
}; v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
} sampler2D _MainTex; fixed4 frag (v2f i) : SV_Target
{
if(i.uv.x>0.5f)
{
discard;
}
fixed4 col = tex2D(_MainTex, i.uv);
// just invert the colors
col.rgb = 1 - col.rgb;
return col;
}
ENDCG
}
}
}

最终的效果为:

2.2. 解析

需要理解的是,后处理的Shader虽然大部分都是在片元着色器中写,但是后处理本质上还是一个或者多个渲染指令,只要是渲染指令,就要经过从顶点着色器到片元着色器的过程。实际上,后处理的一个指令就是绘制了一个屏幕大小的矩形,纹理是帧缓冲中存储的场景画面。理解这一点,才能理解后处理是一个全屏幕操作,与具体的三维物体无关。

在这个例子中,在片元着色器中把颜色取反,所以最终整个屏幕的颜色RGB颠倒了;设置纹理坐标在X方向上的值大于一半时不显示,所以整个屏幕的右边就不显示颜色。

可以在Frame Debug中看到这个后处理指令:

代码地址

最新文章

  1. FineReport如何连接和使用MongoDB数据库
  2. linux网络配置命令
  3. PC安装了MAC,那么CMD键和OPTION键什么的在哪里?
  4. 如何让AutoCAD自动加载Arx,比如ArxDbg.arx
  5. POJ 2342 Label:树形dp
  6. jstl的mavin依赖
  7. 关于禁止ViewPager预加载问题【转】
  8. android开发学习 几个有用的学习资料~
  9. 关于cas server无法通过session持久化方式实现集群的问题
  10. 201521123012 《Java程序设计》第八周学习总结
  11. 谈谈序列化—实体bean一定要实现Serializable接口?
  12. MATLAB中a(:)和." ' "," ' "
  13. C 实现选择排序
  14. ESP8266 nodemcu
  15. Android无线调试_adbWireless
  16. linux下手动安装git教程
  17. java课设数据库打包报错
  18. img图片自适应宽和高[转]
  19. PHP-005
  20. 模块的封装之C语言类的封装

热门文章

  1. uniapp设置竖屏
  2. JNPF.java前后端分离框架,SpringBoot+SpringCloud开发微服务平台
  3. asp.net core系列 77 webapi响应压缩
  4. ARM学习1
  5. 当运行npm install 命令的时候带上ignore-scripts,会发生什么?
  6. 论文解读(GraphMAE)《GraphMAE: Self-Supervised Masked Graph Autoencoders》
  7. 如何删除wps在我的电脑入口中的云文档图标
  8. idea运行Tomcat出现 Address localhost:8080 is already in useAddress localhost:8080 is already in use
  9. 你难道不知道Vue-cookie?
  10. 手写一个虚拟DOM库,彻底让你理解diff算法