原文:
Postprocessing Basics
Summary
目前为止,我将所有我实现的着色器应用到了模型上,并将其渲染到屏幕上。着色器还有一个常用的用途就是处理图片、以及我们刚渲染好的上一帧画面。我们对前面渲染好的画面进行处理的操作就叫做后处理。
后处理所使用的着色器在语法和结构上和之间介绍的着色器一样。所以我建议你先了解前面关于着色器的基础教程。
Postprocessing Shader
作为后处理的入门教程,这里我将展示如何实现简单的颜色取反效果。
因为整个脚本和其他着色器类似,所以我将直接使用着色器基础教程中的着色器脚本,并在此基础上进行修改。
当然,即便是最基础的着色器也有一些后处理用不到的变量,我们可以将它删除。例如这里的材质颜色、渲染标签Tags
、纹理参数。
然后我们还需要添加一些东西,使得我们的着色器更适用于后处理。例如在后处理中所有的属性变量都是通过脚本赋值的,所以在属性块中可以加入属性隐藏标签,另外后处理操作不应该对影响场景深度图,所以应该禁用深度写入等功能。
基于上述修改,最终的着色器如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| Shader "Tutorial/016_Postprocessing"{ Properties{ [HideInInspector]_MainTex ("Texture", 2D) = "white" {} }
SubShader{ Cull Off ZWrite Off ZTest Always
Pass{ CGPROGRAM #include "UnityCG.cginc"
#pragma vertex vert #pragma fragment frag
sampler2D _MainTex;
struct appdata{ float4 vertex : POSITION; float2 uv : TEXCOORD0; };
struct v2f{ float4 position : SV_POSITION; float2 uv : TEXCOORD0; };
v2f vert(appdata v){ v2f o; o.position = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; }
fixed4 frag(v2f i) : SV_TARGET{ fixed4 col = tex2D(_MainTex, i.uv); return col; }
ENDCG } } }
|
Postprocessing C# Script
上面我们已经准备好了用于后处理的着色器,接下来我们要实现C#脚本,来控制后处理过程。摄像机在执行后处理的时候会用到这个脚本。
新建的脚本是一个脚本组件,只有一个函数OnRenderImage
。这个函数有Unity在特定时间调用的。其中传递两个参数,一是后处理原图,一是后处理结果图。将一张图中的数据复制到另一张图,可以使用Blit
函数。
1 2 3 4 5 6 7 8 9 10 11
| using UnityEngine;
public class Postprocessing : MonoBehaviour {
void OnRenderImage(RenderTexture source, RenderTexture destination){ Graphics.Blit(source, destination); } }
|
到目前为止,整个后处理逻辑并不会产生什么特别的效果,因为从原图到结果图没有执行任何操作。我们可以再传第三个材质参数,那么在结果图写入前会执行该材质中的着色器脚本。所以这里我们给这个后处理脚本增加一个材质属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| using UnityEngine;
public class Postprocessing : MonoBehaviour { [SerializeField] private Material postprocessMaterial;
void OnRenderImage(RenderTexture source, RenderTexture destination){ Graphics.Blit(source, destination, postprocessMaterial); } }
|
当前面准备好后,我们创建需要的材质球,然后将该材质球和我们的后处理着色器绑定。
然后将我们的后处理脚本绑定到我们的摄像机物体上,并且将前面的材质球赋值给这个后处理组件。
Negative Colors Effect
做好这一切后,运行程序发现好像没啥特别的变化。要实现颜色取反的效果,我们还需要重新回到我们的后处理着色器中,在片段着色器函数中执行颜色取反的操作。
1 2 3 4 5 6 7 8
| fixed4 frag(v2f i) : SV_TARGET{ fixed4 col = tex2D(_MainTex, i.uv); col = 1 - col; return col; }
|
虽然颜色取反并不是我们常用的效果,但是它揭示了后处理的一般流程,为我们打开一个全新的后处理世界。在后面我会陆陆续续介绍其他常用的后处理效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| Shader "Tutorial/016_Postprocessing"{ Properties{ [HideInInspector]_MainTex ("Texture", 2D) = "white" {} }
SubShader{ Cull Off ZWrite Off ZTest Always
Pass{ CGPROGRAM #include "UnityCG.cginc"
#pragma vertex vert #pragma fragment frag
sampler2D _MainTex;
struct appdata{ float4 vertex : POSITION; float2 uv : TEXCOORD0; };
struct v2f{ float4 position : SV_POSITION; float2 uv : TEXCOORD0; };
v2f vert(appdata v){ v2f o; o.position = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; }
fixed4 frag(v2f i) : SV_TARGET{ fixed4 col = tex2D(_MainTex, i.uv); col = 1 - col; return col; }
ENDCG } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| using UnityEngine;
public class Postprocessing : MonoBehaviour { [SerializeField] private Material postprocessMaterial;
void OnRenderImage(RenderTexture source, RenderTexture destination){ Graphics.Blit(source, destination, postprocessMaterial); } }
|
希望本篇教程能够让你了解如何使用简单的后处理效果、能够独立实现一些后处理效果。
你可以在以下链接找到源码:
https://github.com/ronja-tutorials/ShaderTutorials/blob/master/Assets/016_Postprocessing/Postprocessing.shader
https://github.com/ronja-tutorials/ShaderTutorials/blob/master/Assets/016_Postprocessing/Postprocessing.cs
希望你能喜欢这个教程哦!如果你想支持我,可以关注我的推特,或者通过ko-fi、或patreon给两小钱。总之,各位大爷,走过路过不要错过,有钱的捧个钱场,没钱的捧个人场:-)!!!