很多時候,我们做游戏会遇到一种情况。比如一个技能图标,可以点的时候是正常的颜色,不能点的时候是灰色的。又比如一个功能,开放的时候是正常颜色,没开放的时候是灰色的。更常见的就是,比如你的QQ好友,不在线头像也会变成灰色的。
那么,上述种种情况就出现了一种需求,把一个图片变成灰色的。
首先,你不能说让美术出两套图,一套彩色一套灰色的吧。这样会增加资源占用。
那么我们只能想办法通过程序来处理。
那么我们要先搞清楚,灰色的图片是怎样的。
(彩色)
(灰化后)
看到“战队升级”那几个字和他们的背景,就是灰色的啦。
那怎样把一张图片变成灰色的,首先,颜色由RGB组成(你想说由CMYK、HSB、甚至索引色,我不会跟你争这个,毕竟,我是个有素养的人),我们看到的所谓灰色。就是R、G、B这三个值都一样。也就是说,我们要把图片原RGB值计算成一个新的RGB,这个新的颜色他的R=G=B。
那好,那RGB怎么计算成一个灰度值呢?
这里涉及到一个灰化的公式,这公式是一个经验公式,也就是说,这个公式是不固定的。只要你算出来之后,效果是灰色的,那就可以了。
比如,最简单的,你可以用公式:
k = (r + g + b) / 3
这样是对RGB取平均值。
还有个心理学公式:
k = r*.222 + g*.707 + b*.071;
这个公式是什么意思呢?大家可以发现,0.222+0.707+0.071 = 1
其实这个公式的意思就是觉得RGB所占比重不同,比如R占0.222。那么他把RGB值分别乘以对应的比重,就得到一个新的值。而公式1,其实也就认为RGB所占比重是一样的。
这些公式最后得到的都是灰色图片(因为你R=G=B=k),只不过看起来视觉效果不同。你也可以自己试试其他的比重。
说那么多,不如动手来撸几行代码。
思路就是修改NGUI的Transparent Colored这个shader。我们通过丢失一个颜色来处理。把(0,0,0)作为启用灰度的开关。
Transparent Colored代码如下:
Shader "Unlit/Transparent Colored" { Properties { _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {} } SubShader { LOD 100 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Cull Off Lighting Off ZWrite Off Fog { Mode Off } Offset -1, -1 Blend SrcAlpha OneMinusSrcAlpha Pass { 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 100 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Cull Off Lighting Off ZWrite Off Fog { Mode Off } Offset -1, -1 ColorMask RGB AlphaTest Greater .01 Blend SrcAlpha OneMinusSrcAlpha ColorMaterial AmbientAndDiffuse SetTexture [_MainTex] { Combine Texture * Primary } } } }我们在vert中计算设置的颜色(下面那个图为设置的地方)是否全为0
如果全为0,则在frag中应用灰化公式。
就这样完成了修改了。
为了对softclip起做用,请一起修改
Transparent Colored 1.shader、Transparent Colored 2.shader、Transparent Colored 3.shader为如下代码:
网上可能很多文章没说到上面3个shader的修改,导致很多开发者在softclip中使用灰化的时候不起效果。
Shader "HIDDEN/Unlit/Transparent Colored 1" { Properties { _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {} } SubShader { LOD 200 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Cull Off Lighting Off ZWrite Off Offset -1, -1 Fog { Mode Off } ColorMask RGB AlphaTest Greater .01 Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #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 factor float2 factor = (float2(1.0, 1.0) - abs(IN.worldPos)) * _ClipArgs0; // Sample the texture half4 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 100 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Cull Off Lighting Off ZWrite Off Fog { Mode Off } ColorMask RGB AlphaTest Greater .01 Blend SrcAlpha OneMinusSrcAlpha ColorMaterial AmbientAndDiffuse SetTexture [_MainTex] { Combine Texture * Primary } } } }
Shader "HIDDEN/Unlit/Transparent Colored 2" { Properties { _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {} } SubShader { LOD 200 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Cull Off Lighting Off ZWrite Off Offset -1, -1 Fog { Mode Off } ColorMask RGB AlphaTest Greater .01 Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #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 region float2 factor = (float2(1.0, 1.0) - abs(IN.worldPos.xy)) * _ClipArgs0.xy; float f = min(factor.x, factor.y); // Second clip region factor = (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 100 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Cull Off Lighting Off ZWrite Off Fog { Mode Off } ColorMask RGB AlphaTest Greater .01 Blend SrcAlpha OneMinusSrcAlpha ColorMaterial AmbientAndDiffuse SetTexture [_MainTex] { Combine Texture * Primary } } } }
Shader "HIDDEN/Unlit/Transparent Colored 3" { Properties { _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {} } SubShader { LOD 200 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Cull Off Lighting Off ZWrite Off Offset -1, -1 Fog { Mode Off } ColorMask RGB AlphaTest Greater .01 Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #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 region float2 factor = (float2(1.0, 1.0) - abs(IN.worldPos.xy)) * _ClipArgs0.xy; float f = min(factor.x, factor.y); // Second clip region factor = (float2(1.0, 1.0) - abs(IN.worldPos.zw)) * _ClipArgs1.xy; f = min(f, min(factor.x, factor.y)); // Third clip region factor = (float2(1.0, 1.0) - abs(IN.worldPos2)) * _ClipArgs2.xy; f = min(f, min(factor.x, factor.y)); // Sample the texture half4 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 100 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Cull Off Lighting Off ZWrite Off Fog { Mode Off } ColorMask RGB AlphaTest Greater .01 Blend SrcAlpha OneMinusSrcAlpha ColorMaterial AmbientAndDiffuse SetTexture [_MainTex] { Combine Texture * Primary } } } }
原文地址:http://blog.csdn.net/kakashi8841/article/details/45478433