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