zoukankan      html  css  js  c++  java
  • 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 }

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

     
  • 相关阅读:
    Java获取Linux系统cpu使用率
    jsoup 提取 html 中的所有链接、图片和媒体
    使用Spring定时任务并且通过AOP监控任务执行情况
    MySQL导出数据库、数据库表结构、存储过程及函数【用】
    linux下部署一个JavaEE项目的简单步骤
    MySQL 错误日志(Error Log)
    linux下程序JDBC连接不到mysql数据库
    linux下mysql登录报错“Access denied for user 'root'@'localhost' (using password: YES”)的处理方法
    Spring Boot的核心
    项目中菜单折叠问题
  • 原文地址:https://www.cnblogs.com/koshio0219/p/11131619.html
Copyright © 2011-2022 走看看