[Shader] NGUI and gray-based shaderngui
1. Gray demand
Many times, we may encounter a situation when playing games. For example, a skill icon can be a normal color when clicked, and gray when clicked. Another example is that the color is normal when it is open and gray when it is not open. More often, for example, your QQ friends, non-Online portraits will become gray.
Then, there is a need to turn an image into gray.
2. Gray and gray scale
First of all, you can't say that two sets of pictures are made of art, one set of colors and one set of gray ones. This will increase resource usage.
Then we can only find a way to process it through a program.
First, we need to figure out what the gray image looks like.
(Color)
(After being grayed out)
The words "Team upgrade" and their background are gray.
Then how can we make an image gray? First, the color is composed of RGB (you want to say that it is CMYK, HSB, or even index color. I won't argue with you about this. After all, I am a literate person), we see the so-called gray. The values R, G, and B are the same. That is to say, we need to calculate the original RGB value of the image into a new RGB value. The new color is R = G = B.
Well, how can we calculate RGB as a gray value?
Here it involves a gray formula, which is an empirical formula, that is, this formula is not fixed. After you calculate it, the effect is gray.
For example, you can use the formula:
K = (r + g + B)/3
In this way, the average value of RGB is obtained.
There is also a psychology formula:
K = r *. 222 + g *. 707 + B *. 071;
What does this formula mean? We can find that 0.222 + 0.707 + 0.071 = 1
In fact, this formula means that RGB accounts for different proportions, for example, R accounts for 0.222. Then, multiply the RGB values by the corresponding proportions to obtain a new value. In Formula 1, we actually think that RGB shares the same proportion.
The final result of these formulas is a gray image (because you R = G = B = k), but the visual effects are different. You can also try another proportion on your own.
3. NGUI gray-based practices
If there are so many lines of code, it is better to compile a few lines of code.
The idea is to modify the shader Transparent Colored of NGUI. We will deal with the loss of a color. Use (0, 0, 0) as the Enable grayscale switch.
The Transparent Colored code is as follows:
Shader "Unlit/Transparent Colored"{Properties{_MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}}SubShader{LOD 100Tags{"Queue" = "Transparent""IgnoreProjector" = "True""RenderType" = "Transparent"}Cull OffLighting OffZWrite OffFog { Mode Off }Offset -1, -1Blend SrcAlpha OneMinusSrcAlphaPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata_t{float4 vertex : POSITION;float2 texcoord : TEXCOORD0;fixed4 color : COLOR;};struct v2f{float4 vertex : SV_POSITION;half2 texcoord : TEXCOORD0;fixed4 color : COLOR;fixed gray : TEXCOORD1; };sampler2D _MainTex;float4 _MainTex_ST;v2f vert (appdata_t v){v2f o;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.texcoord = v.texcoord;o.color = v.color;o.gray = dot(v.color, fixed4(1,1,1,0));return o;}fixed4 frag (v2f i) : COLOR{ fixed4 col;col = tex2D(_MainTex, i.texcoord);if(i.gray == 0){float grey = dot(col.rgb, float3(0.299, 0.587, 0.114));col.rgb = float3(grey, grey, grey);}else{ col = col * i.color;}return col;}ENDCG}}SubShader{LOD 100Tags{"Queue" = "Transparent""IgnoreProjector" = "True""RenderType" = "Transparent"}Pass{Cull OffLighting OffZWrite OffFog { Mode Off }Offset -1, -1ColorMask RGBAlphaTest Greater .01Blend SrcAlpha OneMinusSrcAlphaColorMaterial AmbientAndDiffuseSetTexture [_MainTex]{Combine Texture * Primary}}}}
In vert, we calculate whether the set color (the figure below shows the set position) is all 0.
If all values are 0, apply the gray formula to frag.
This completes the modification.
4. Support for softclip
To use softclip, modify it together.
Transparent Colored 1. shader, Transparent Colored 2. shader, Transparent Colored 3. shader is the following code:
Many articles on the Internet may not mention the modification of the above three shader, which makes it ineffective for many developers to use Gray in softclip.
Shader "HIDDEN/Unlit/Transparent Colored 1"{Properties{_MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}}SubShader{LOD 200Tags{"Queue" = "Transparent""IgnoreProjector" = "True""RenderType" = "Transparent"}Pass{Cull OffLighting OffZWrite OffOffset -1, -1Fog { Mode Off }ColorMask RGBAlphaTest Greater .01Blend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;float4 _ClipRange0 = float4(0.0, 0.0, 1.0, 1.0);float2 _ClipArgs0 = float2(1000.0, 1000.0);struct appdata_t{float4 vertex : POSITION;half4 color : COLOR;float2 texcoord : TEXCOORD0;};struct v2f{float4 vertex : POSITION;half4 color : COLOR;float2 texcoord : TEXCOORD0;float2 worldPos : TEXCOORD1;};v2f vert (appdata_t v){v2f o;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.color = v.color;o.texcoord = v.texcoord;o.worldPos = v.vertex.xy * _ClipRange0.zw + _ClipRange0.xy;return o;}half4 frag (v2f IN) : COLOR{// Softness factorfloat2 factor = (float2(1.0, 1.0) - abs(IN.worldPos)) * _ClipArgs0;// Sample the texturehalf4 col = tex2D(_MainTex, IN.texcoord);if (dot(IN.color, fixed4(1,1,1,0)) == 0){ col = tex2D(_MainTex, IN.texcoord); col.rgb = dot(col.rgb, fixed3(.222,.707,.071));}else{ col = col * IN.color;} col.a *= clamp( min(factor.x, factor.y), 0.0, 1.0);return col;}ENDCG}}SubShader{LOD 100Tags{"Queue" = "Transparent""IgnoreProjector" = "True""RenderType" = "Transparent"}Pass{Cull OffLighting OffZWrite OffFog { Mode Off }ColorMask RGBAlphaTest Greater .01Blend SrcAlpha OneMinusSrcAlphaColorMaterial AmbientAndDiffuseSetTexture [_MainTex]{Combine Texture * Primary}}}}
Shader "HIDDEN/Unlit/Transparent Colored 2"{Properties{_MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}}SubShader{LOD 200Tags{"Queue" = "Transparent""IgnoreProjector" = "True""RenderType" = "Transparent"}Pass{Cull OffLighting OffZWrite OffOffset -1, -1Fog { Mode Off }ColorMask RGBAlphaTest Greater .01Blend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;float4 _ClipRange0 = float4(0.0, 0.0, 1.0, 1.0);float4 _ClipArgs0 = float4(1000.0, 1000.0, 0.0, 1.0);float4 _ClipRange1 = float4(0.0, 0.0, 1.0, 1.0);float4 _ClipArgs1 = float4(1000.0, 1000.0, 0.0, 1.0);struct appdata_t{float4 vertex : POSITION;half4 color : COLOR;float2 texcoord : TEXCOORD0;};struct v2f{float4 vertex : POSITION;half4 color : COLOR;float2 texcoord : TEXCOORD0;float4 worldPos : TEXCOORD1;};float2 Rotate (float2 v, float2 rot){float2 ret;ret.x = v.x * rot.y - v.y * rot.x;ret.y = v.x * rot.x + v.y * rot.y;return ret;}v2f vert (appdata_t v){v2f o;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.color = v.color;o.texcoord = v.texcoord;o.worldPos.xy = v.vertex.xy * _ClipRange0.zw + _ClipRange0.xy;o.worldPos.zw = Rotate(v.vertex.xy, _ClipArgs1.zw) * _ClipRange1.zw + _ClipRange1.xy;return o;}half4 frag (v2f IN) : COLOR{// First clip regionfloat2 factor = (float2(1.0, 1.0) - abs(IN.worldPos.xy)) * _ClipArgs0.xy;float f = min(factor.x, factor.y);// Second clip regionfactor = (float2(1.0, 1.0) - abs(IN.worldPos.zw)) * _ClipArgs1.xy;f = min(f, min(factor.x, factor.y));half4 col;col = tex2D(_MainTex, IN.texcoord);if (dot(IN.color, fixed4(1,1,1,0)) == 0){ col.rgb = dot(col.rgb, fixed3(.222,.707,.071));}else{ col = col * IN.color;}col.a *= clamp(f, 0.0, 1.0);return col;}ENDCG}}SubShader{LOD 100Tags{"Queue" = "Transparent""IgnoreProjector" = "True""RenderType" = "Transparent"}Pass{Cull OffLighting OffZWrite OffFog { Mode Off }ColorMask RGBAlphaTest Greater .01Blend SrcAlpha OneMinusSrcAlphaColorMaterial AmbientAndDiffuseSetTexture [_MainTex]{Combine Texture * Primary}}}}
Shader "HIDDEN/Unlit/Transparent Colored 3"{Properties{_MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}}SubShader{LOD 200Tags{"Queue" = "Transparent""IgnoreProjector" = "True""RenderType" = "Transparent"}Pass{Cull OffLighting OffZWrite OffOffset -1, -1Fog { Mode Off }ColorMask RGBAlphaTest Greater .01Blend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;float4 _ClipRange0 = float4(0.0, 0.0, 1.0, 1.0);float4 _ClipArgs0 = float4(1000.0, 1000.0, 0.0, 1.0);float4 _ClipRange1 = float4(0.0, 0.0, 1.0, 1.0);float4 _ClipArgs1 = float4(1000.0, 1000.0, 0.0, 1.0);float4 _ClipRange2 = float4(0.0, 0.0, 1.0, 1.0);float4 _ClipArgs2 = float4(1000.0, 1000.0, 0.0, 1.0);struct appdata_t{float4 vertex : POSITION;half4 color : COLOR;float2 texcoord : TEXCOORD0;};struct v2f{float4 vertex : POSITION;half4 color : COLOR;float2 texcoord : TEXCOORD0;float4 worldPos : TEXCOORD1;float2 worldPos2 : TEXCOORD2;};float2 Rotate (float2 v, float2 rot){float2 ret;ret.x = v.x * rot.y - v.y * rot.x;ret.y = v.x * rot.x + v.y * rot.y;return ret;}v2f vert (appdata_t v){v2f o;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.color = v.color;o.texcoord = v.texcoord;o.worldPos.xy = v.vertex.xy * _ClipRange0.zw + _ClipRange0.xy;o.worldPos.zw = Rotate(v.vertex.xy, _ClipArgs1.zw) * _ClipRange1.zw + _ClipRange1.xy;o.worldPos2 = Rotate(v.vertex.xy, _ClipArgs2.zw) * _ClipRange2.zw + _ClipRange2.xy;return o;}half4 frag (v2f IN) : COLOR{// First clip regionfloat2 factor = (float2(1.0, 1.0) - abs(IN.worldPos.xy)) * _ClipArgs0.xy;float f = min(factor.x, factor.y);// Second clip regionfactor = (float2(1.0, 1.0) - abs(IN.worldPos.zw)) * _ClipArgs1.xy;f = min(f, min(factor.x, factor.y));// Third clip regionfactor = (float2(1.0, 1.0) - abs(IN.worldPos2)) * _ClipArgs2.xy;f = min(f, min(factor.x, factor.y));// Sample the texturehalf4 col = tex2D(_MainTex, IN.texcoord);if (dot(IN.color, fixed4(1,1,1,0)) == 0){ col.rgb = dot(col.rgb, fixed3(.222,.707,.071));}else{ col = col * IN.color;}col.a *= clamp(f, 0.0, 1.0);return col;}ENDCG}}SubShader{LOD 100Tags{"Queue" = "Transparent""IgnoreProjector" = "True""RenderType" = "Transparent"}Pass{Cull OffLighting OffZWrite OffFog { Mode Off }ColorMask RGBAlphaTest Greater .01Blend SrcAlpha OneMinusSrcAlphaColorMaterial AmbientAndDiffuseSetTexture [_MainTex]{Combine Texture * Primary}}}}
Okay, it's done. Upload the test project later.