专栏首页U3DUnity Shader 屏幕后效果——颜色校正

Unity Shader 屏幕后效果——颜色校正

屏幕后效果指的是,当前整个场景图已经渲染完成输出到屏幕后,再对输出的屏幕图像进行的操作。

在Unity中,一般过程通常是:

1.建立用于处理效果的shader和临时材质,给shader脚本传递需要控制的参数和变量

2.利用OnRenderImage函数抓取当前屏幕渲染纹理

OnRenderImage(RenderTexture source, RenderTexture destination){ }

第一个参数为处理前纹理,第二个为最终显示纹理

3.在OnRenderImage函数中调用Graphics.Blit方法对抓取的纹理进行具体的后期操作

Graphics.Blit(source, destination, material,-1);

material为需要处理的材质,-1为参数pass的默认值,表示对shader中所有的pass依次调用,这里也可以省略

为此,首先可以提前建立一个基类ScreenEffectBase,主要用于检查Shader并创建临时材质:

脚本如下:

 1 using UnityEngine;
 2 
 3 [ExecuteInEditMode]
 4 //屏幕后处理效果主要是针对摄像机进行操作,需要绑定摄像机
 5 [RequireComponent(typeof(Camera))]
 6 public class ScreenEffectBase : MonoBehaviour
 7 {
 8     public Shader shader;
 9     private Material material;
10     protected Material Material
11     {
12         get
13         {
14             material = CheckShaderAndCreatMat(shader, material);
15             return material;
16         }
17     }
18 
19     //用于检查并创建临时材质
20     private Material CheckShaderAndCreatMat(Shader shader, Material material)
21     {
22         Material nullMat = null;
23         if (shader != null)
24         {
25             if (shader.isSupported)
26             {
27                 if (material && material.shader == shader){ }
28                 else
29                 {
30                     material = new Material(shader){ hideFlags = HideFlags.DontSave };
31                 }
32                 return material;
33             }
34         }
35         return nullMat;
36     }
37 }

之后创建的屏幕后处理效果的控制脚本都可以继承自该基类,例如我们创建关于基本颜色校正的控制脚本:

 1 using UnityEngine;
 2 
 3 public class ColorCorrectionCtrl : ScreenEffectBase
 4 {
 5     private const string _Brightness = "_Brightness";
 6     private const string _Saturation = "_Saturation";
 7     private const string _Contrast = "_Contrast";
 8 
 9     [Range(0, 3)]
10     public float brightness = 1.0f;
11     [Range(0, 3)]
12     public float saturation = 1.0f;
13     [Range(0, 3)]
14     public float contrast = 1.0f;
15 
16     private void OnRenderImage(RenderTexture source, RenderTexture destination)
17     {
18         if (Material!=null)
19         {
20             Material.SetFloat(_Brightness, brightness);
21             Material.SetFloat(_Saturation, saturation);
22             Material.SetFloat(_Contrast, contrast);
23 
24             Graphics.Blit(source, destination, Material);
25         }
26         else
27             Graphics.Blit(source, destination);
28     }
29 }

其中,brightness,saturation,contrast分别为调整参数——亮度,饱和度和对比度,_Brightness,_Saturation,_Contrast为之后对应的shader中需要相应定义的属性参数。

这里利用构建的材质Material对shader的属性赋值并调用Graphics.Blit进行屏幕后效果的处理。

具体实现颜色校正的shader如下:

 1 Shader "MyUnlit/ColorCorrection"
 2 {
 3     Properties
 4     {
 5         //这里的参数主要用于展示在材质面板中进行调节,但因为这次是临时创建的材质,参数都已经放在了C#脚本中调整,因此相对应的参数都可以省略
 6         _MainTex ("Texture", 2D) = "white" {}
 7     }
 8     SubShader
 9     {
10         Tags { "RenderType"="Opaque" }
11 
12         Pass
13         {
14             //OnRenderImage的调用可能会发生在渲染透明物体之前,为了不影响之后透明物体的渲染,需要:开启深度测试+双面渲染+关闭深度写入
15             ZTest always
16             Cull off
17             ZWrite off
18 
19             CGPROGRAM
20             #pragma vertex vert
21             #pragma fragment frag
22             #pragma multi_compile_fog
23 
24             #include "UnityCG.cginc"
25 
26             struct appdata
27             {
28                 float4 vertex : POSITION;
29                 float2 uv : TEXCOORD0;
30             };
31 
32             struct v2f
33             {
34                 float2 uv : TEXCOORD0;
35                 UNITY_FOG_COORDS(1)
36                 float4 vertex : SV_POSITION;
37             };
38 
39             sampler2D _MainTex;
40             half _Brightness;
41             half _Saturation;
42             half _Contrast;
43 
44             v2f vert (appdata v)
45             {
46                 v2f o;
47                 o.vertex = UnityObjectToClipPos(v.vertex);
48                 //因为是临时创建的材质,这里不需要对纹理进行任何变换操作(无可操作的材质面板),直接传递即可,_MainTex_ST也不需要定义
49                 o.uv = v.uv;
50                 UNITY_TRANSFER_FOG(o,o.vertex);
51                 return o;
52             }
53 
54             fixed4 frag (v2f i) : SV_Target
55             {
56                 fixed4 col = tex2D(_MainTex, i.uv);
57 
58                 //亮度计算直接叠加
59                 fixed3 color = col.rgb*_Brightness;
60 
61                 //饱和度和灰度有关,先计算最低灰度系数下的图像,随后对原始的图像进行插值操作
62                 fixed3 gray = fixed3(0.2125, 0.7154, 0.0721);
63                 //点积得到最低灰度值,构成最低灰度图像
64                 fixed minGray = dot(gray, col.rgb);
65                 fixed3 grayColor = fixed3(minGray, minGray, minGray);
66                 //对灰度图像和原始图像插值操作以得到最终系数的显示图像
67                 color = lerp(grayColor, color, _Saturation);
68 
69                 //对比度效果类似,先计算最低对比度图像,即(0.5,0.5,0.5),随后插值操作
70                 fixed3 minContrast = fixed3(0.5, 0.5, 0.5);
71                 color = lerp(minContrast, color, _Contrast);
72 
73                 //得到所有处理完成后的图像颜色,但alpha保持不变
74                 fixed4 finColor = fixed4(color, col.a);
75 
76                 UNITY_APPLY_FOG(i.fogCoord, finColor);
77                 return finColor;
78             }
79             ENDCG
80         }
81     }
82     //关闭回调
83     fallback off
84 }

效果如下(随便调的不用在意~):

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Unity 通用透明物体漫反射Shader

    对于至今为止Shader学习内容的一个总结,算是一个比较综合通用的shader了,因为是漫反射所以暂时没有计算高光部分,之后再出一个带高光版本的。

    汐夜koshio
  • Unity ugui屏幕适配与世界坐标到ugui屏幕坐标的转换

    我们知道,如今的移动端设备分辨率五花八门,而开发过程中往往只取一种分辨率作为设计参考,例如采用1920*1080分辨率作为参考分辨率。

    汐夜koshio
  • Unity 小地图制作

    主要利用的原理是将一个单独摄像机的当前拍摄画面实时保存到一张渲染纹理图中,同时将这张纹理图更新显示到ugui中。

    汐夜koshio
  • CaffeLoss - FocalLossLayer

    基于 SoftmaxWithLossLayer 实现的 FocalLossLayer.

    AIHGF
  • Weex 中别具匠心的 JS Framework

    为了达到所有页面在用户端达到秒开,也就是网络(JS Bundle下载)和首屏渲染(展现在用户第一屏的渲染时间)时间和小于1s。

    一缕殇流化隐半边冰霜
  • Oracle逻辑结构学习笔记

    数据库(Database)由若干表空间(Tablespace)组成,表空间(Tablespace)由若干段(Segment)组成,段(Segment)由若干区(...

    SmileNicky
  • ListView的addHeaderView()方法相关问题

    听着music睡
  • AI、自动化来势汹汹,“码农”将何去何从?

    【编者按】:AI、自动化,这些技术进步不仅威胁到到了其他行业的工作,甚至有声音认为,连开发这些技术的程序员其自嘲的“码农”地位都将不保。比方说,OpenAI 前...

    机器人网
  • 干货分享 | 人工智能如何驱动未来教育发展?

    ABOUT 1月13日下午,在沪江北京研发中心、沪江智能学习实验室和CCtalk在京举办的“智能引擎,驱动教育”技术沙龙中,达观数据创始人&CEO陈运文作为受邀...

    达观数据
  • 不同的.Net版本客户端软件调用Java Web Service区别

    最近的系统中需要.Net开发的离线端软件通过Web Service技术和Java开发的在线系统进行数据交互。

    程序你好

扫码关注云+社区

领取腾讯云代金券