Grayscale (Unity 5.0 Shader)

一:Grayscale

  1.Grayscale也就是图像的灰度进行拉伸,这里的灰度可以理解为亮度。

  2.算法:通过像素点的RGB值得到亮度值Y(即RGB转YUV),然后将Y重新赋值回RGB。

    2.1 Y = 0.299 * R + 0.587 * G + 0.114 * B;

    2.2 R = Y; G = Y; B = Y;

 

  3.Unity Shader 实现

  3.1建立测试场景,三个红绿蓝的Sphere

  

 

  3.2 Shader脚本, Grayscale.shader

  

 1 Shader "Euler/Grayscale"
 2 {
 3     Properties
 4     {
 5         _MainTex ("Texture", 2D) = "white" {}
 6     }
 7 
 8     SubShader
 9     {
10         // No culling or depth
11         Cull Off ZWrite Off ZTest Always
12 
13         Pass
14         {
15             CGPROGRAM
16             #pragma vertex vert
17             #pragma fragment frag
18             
19             #include "UnityCG.cginc"
20 
21             struct appdata
22             {
23                 float4 vertex : POSITION;
24                 float2 uv : TEXCOORD0;
25             };
26 
27             struct v2f
28             {
29                 float2 uv : TEXCOORD0;
30                 float4 vertex : SV_POSITION;
31             };
32 
33             v2f vert (appdata v)
34             {
35                 v2f o;
36                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
37                 o.uv = v.uv;
38                 return o;
39             }
40             
41             sampler2D _MainTex;
42 
43             fixed4 frag (v2f i) : COLOR
44             {
45                 fixed4 col = tex2D(_MainTex, i.uv);
46 
47                 float y = col.r * 0.299 + col.g * 0.587 + col.b * 0.114;
48 
49                 col.r = y;
50                 col.g = y;
51                 col.b = y;
52 
53                 return col;
54             }
55             ENDCG
56         }
57     }
58 }

 

  3.3用于Main Camera的Image Effect的C#脚本 Grayscale.cs, 并将上一步的Shader赋值给Grayscale.cs的public变量shader

  

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class Grayscale : MonoBehaviour {
 5     public Shader shader;
 6 
 7     private Material _material;
 8 
 9     Material material
10     {
11         get
12         {
13             if(_material == null && shader != null)
14             {
15                 _material = new Material(shader);
16             }
17 
18             return _material;
19         }
20     }
21 
22     // Use this for initialization
23     void Start () {
24     
25     }
26     
27     // Update is called once per frame
28     void Update () {
29     
30     }
31 
32     void OnRenderImage(RenderTexture srcTexture, RenderTexture dstTexture)
33     {
34         if (material)
35         {
36             Graphics.Blit(srcTexture, dstTexture, material);
37         }
38         else
39         {
40             Graphics.Blit(srcTexture, dstTexture);
41         }
42     }
43 }

  3.5运行效果:

  

  这里是直接将物体(Y = 0.299 * R + 0.587 * G + 0.114 * B)亮度作为它的颜色, 算法反映的是人视觉对绿色比较敏感,

所以公式中绿色的权重也比较大,从效果看也是原来绿色的Sphere 在 Grayscale之后比较亮。

 

  4.修改, 不再把亮度直接作为颜色,而是把亮度作为阀值对原来的颜色做整体的线性调整。

  4.1修改后的Shader

  

Shader "Euler/Grayscale"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Grayscale("Grayscale", Range(0, 1)) = 0.5
    }

    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 = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = v.uv;
                return o;
            }
            
            sampler2D _MainTex;
            float _Grayscale;

            fixed4 frag (v2f i) : COLOR
            {
                fixed4 col = tex2D(_MainTex, i.uv);

                float y = col.r * 0.299 + col.g * 0.587 + col.b * 0.114;

                fixed4 finalCol = lerp(col, y, _Grayscale);

                return finalCol;
            }
            ENDCG
        }
    }
}

  4.2修改后的Grayscale.cs 脚本

  

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 [ExecuteInEditMode]
 5 public class Grayscale : MonoBehaviour {
 6     public Shader shader;
 7 
 8     [Range(0, 1)]
 9     public float scaleValue = 0.5f;
10 
11     private Material _material;
12 
13     Material material
14     {
15         get
16         {
17             if(_material == null && shader != null)
18             {
19                 _material = new Material(shader);
20             }
21 
22             return _material;
23         }
24     }
25 
26     // Use this for initialization
27     void Start () {
28     
29     }
30     
31     // Update is called once per frame
32     void Update () {
33         Mathf.Clamp(scaleValue, 0.0f, 1.0f);
34     }
35 
36     void OnRenderImage(RenderTexture srcTexture, RenderTexture dstTexture)
37     {
38         if (material)
39         {
40             material.SetFloat("_Grayscale", scaleValue);
41             Graphics.Blit(srcTexture, dstTexture, material);
42         }
43         else
44         {
45             Graphics.Blit(srcTexture, dstTexture);
46         }
47     }
48 }

 

  4.3效果

        

  从左到右  Grayscale的值为 0.5f, 0.8f, 1.0f

posted @ 2016-06-03 18:03  KbDaVinci  阅读(1535)  评论(0)    收藏  举报