http://www.tuicool.com/articles/Vruuqme

NGUI中的Button差点儿是最经常使用到的控件之中的一个,而且能够组合各种组件(比方UIButtonColor,UIButtonOffset,UITweenxx),方便设置Button的各种状态下的属性。差点儿能够满足我们的全部需求。

可是对于当Button的isEnabled属性设置为false时,依据设置的disableColor属性设置不可点击时的颜色时,尽管我们设置的灰色,但并非我们想象中的样子!

设置的是灰色,实际执行结果却还是彩色的,仅仅是暗了一点。并不可以非常好地表现出其“禁用”的状态!

1.原理

Unity3d中全部的渲染都是基于Shader的,而Shader绑定在Material上。打开一个NGUI样例中自带的Material,得到其使用Shader的文件

NGUI中大部分材质都使用的Unlit/Transparent Colored(PS:尽管在Unlit下,但并非Unity3d内置的,而是NGUI扩展的)

找到其片段着色器,代码例如以下:

  1. fixed4 frag (v2f i) : COLOR
  2. {
  3. fixed4 col = tex2D(_MainTex, i.texcoord) * i.color;
  4. return col;
  5. }
fixed4 frag (v2f i) : COLOR
{
fixed4 col = tex2D(_MainTex, i.texcoord) * i.color;
return col;
}

这个片段着色器非常easy,仅仅在“最简单的着色器”上多加了一步,即将从定点着色器中传出的顶点颜色属性乘到了纹理採样得到的像素上。

看到这个代码。就非常easy理解为什么是变暗,而不是变成灰色了

顶点的颜色数据是从UISprite之类的面板中传递进来的,其最大值是白色(255,255,255,255),而这里是正交化的,最大值白色相应(1.0,1.0,1.0,1.0)。这也是默认值,当採样得到的像素值x1.0,相当于採样得到的纹理值;假设设置一个其它的颜色。正交化后肯定会小于1.0,当採样得到的像素值乘以这个值后,像素值会比之前小,而最小值是(0,0。 0,0)即黑色,也就是说假设设置一个不是白色的颜色。就会使像素值更接近于黑色。这就是变暗的原因!



2.置灰

NGUI仅仅提供了这样一种变暗的功能,用来表现其“禁用”的状态,可是这并非最好的结果,假设须要介于黑白之间的灰色纹理,难道非要美术对每个可能会被置灰的纹理又一次制作一张纹理吗?

这就更糟了。游戏中纹理是非常占空间的。这样做相当于将UI资源翻了一倍!

还是从Shader方面入手吧。

想象一下。假设在着色器处理之前。传递一个bool值,当这个bool值为true时。正常绘制纹理;当这个bool值为false时。绘制灰色纹理。

(Unity3d的Shader中并不支持传递bool值,这里仅仅是举个栗子)

这样看似非常合理,也确实能够实现,可是会有一个问题,这个bool值肯定要在顶点着色器阶段传过去,而NGUI提供的“纹理打包”功能(即非常多纹理合并成一个Atlas,即节省空间,还能够有一些其它信息。比方九宫格拉伸的參数。。。),当这个bool值为false时,这个Atlas中所有的绘制即所有变为灰色,这是不符合逻辑的,当然能够每张小图单独处理,即相当于损失掉NGUI的“纹理打包”功能

3.解决方式

损失一个颜色值吧,作为“约定”!

选取一个颜色值,作为约定为置灰的标记,当片段着色器检測到这个颜色值之后,运行渲染灰色的shader!

这个颜色值能够随意选择。我这里选取纯黑色作为“约定颜色”,片段着色器代码例如以下:

  1. fixed4 frag (v2f i) : COLOR
  2. {
  3. fixed4 col;
  4. if (i.color.r < 0.001)
  5. {
  6. col = tex2D(_MainTex, i.texcoord);
  7. float grey = dot(col.rgb, float3(0.299, 0.587, 0.114));
  8. col.rgb = float3(grey, grey, grey);
  9. }
  10. else
  11. {
  12. col = tex2D(_MainTex, i.texcoord) * i.color;
  13. }
  14. return col;
  15. }
fixed4 frag (v2f i) : COLOR
{
fixed4 col;
if (i.color.r < 0.001)
{
col = tex2D(_MainTex, i.texcoord);
float grey = dot(col.rgb, float3(0.299, 0.587, 0.114));
col.rgb = float3(grey, grey, grey);
}
else
{
col = tex2D(_MainTex, i.texcoord) * i.color;
}
return col;
}

当中(0.299,0.587,0.114)为灰度公式的參数

我复制了一份NGUI样例的纹理和材质,将此Shader设置到材质中,渲染效果如图

(最上面两个是原始状态下的效果。中间两个是NGUI提供的禁用状态效果。最以下两个各自是改动后Shader渲染同一个Atlas得到的结果)

这才是我想要的灰色!

Unity图片变灰的方式的更多相关文章

  1. CSS使图片变灰

    为了悼念,各大网站都纷纷将自己的站点颜色调灰,就连图片也一样,到底如何实现的呢,请看下面的代码. 〈img src="http://hovertree.com/hvtimg/201512/f ...

  2. NGUI 图片变灰

    效果图 1.先准备好一个变灰shader.代码如下 Shader "Custom/Gray" { Properties { _MainTex ("Base (RGB), ...

  3. cocos2d-x图片变灰或者变亮

    //根据现有CCSprite,变亮和变灰 CCSprite* FlyLeaf::graylightWithCCSprite(CCSprite* oldSprite,bool isLight) {    ...

  4. c# winform 把彩色图片转换为灰色的图片,变灰,灰度图片,速度很快,safe,unsafe

    把彩色图片转换为灰色的图片,直接用.net接口遍历每个像素点转换的效率非常低,800K的图片65万像素我的电脑要用5分钟,而用了unsafe,速度提高了几千倍,同样的图片只用了0.几秒 附一个常用的遍 ...

  5. unity 图片变纯色填充

    unity自带shader 即可

  6. JAVA彩色图片变灰处理

    File file = new File("F:/firefox.png"); File destFile = new File("F:/pic/" + Sys ...

  7. 图片变灰css3

    -webkit-filter: grayscale(100%); -moz-filter: grayscale(100%); -ms-filter: grayscale(100%); -o-filte ...

  8. css3图片变灰

    html{ filter:grayscale(100%); -webkit-filter:grayscale(100%); -moz-filter:grayscale(100%); -ms-filte ...

  9. CSS实现图片变灰色及透明度

    [图片变灰] 每当遇到哀悼日,很多网站快速变灰色,来看看实现方式吧: 方式一,仅支持ie) html{filter:progid:DXImageTransform.Microsoft.BasicIma ...

随机推荐

  1. akka监控

    使用akka系统时间就了,你就一定会想着监控的事儿.比如某个actor发送了多少消息.接收了多少消息.消息平均处理时间是多少,当前有多少个actor等等.本来我都用bytebuddy写了个简单的akk ...

  2. SS配置,Brook是什么?,Brook如何配置(Android篇)

    很长时间没有更新了,今天给大家分享一下什么是Brook,和SS有什么区别?写的不好,请勿见外,大佬绕过. Brook简单介绍 Brook 是一个高效的 Socks5 代理软件,官方支持Windows. ...

  3. .Net Core开源小工具mssql2mysql,从mssql生成mysql脚本

    Microsoft SQL Server to MySQL 这个工具用于从MSSQL生成MySQL脚本,生成的脚本包含表结构和数据 安装 这是一个.Net Core的具具,所以需要先安装.net co ...

  4. Java学习-异常2

    1.异常处理的第一种方式是:上抛[throws] 2.异常处理的第二种方式是:try....catch..如果不想让调用程序知道该异常发生了,被调用的程序应该使用try...catch..进行异常捕捉 ...

  5. ACM_三角形蛇形矩阵

    三角形蛇形矩阵 Time Limit: 2000/1000ms (Java/Others) Problem Description: 小铠觉得各类题型是要温故而知新的,所以他叫小发出一道类似做过的题. ...

  6. oracle 行转列函数pivot和unpivot

    今天接到业务部门的一个需求,需要对同一公司的不同财务指标进行排序,需要用到oracle的行转列函数unpivot. 财务报表的表结构为: 要实现业务部门的排序筛选功能,需要首先将行数据转为列数据: 使 ...

  7. sql语句优化:用join取代not in

    不要太多使用not in查询,最好用表连接来取代它.如: select ID,name from Table_A where ID not in (select ID from Table_B) 这句 ...

  8. MAC 中安装和使用express

    其实window系统和mac的操作在大致上其实是想同的,只是一些细节的区别,以下对在mac下安装和使用express做简要介绍,如有不妥之处请各位大神指教. 一.首先要测试node和npm是否已经正确 ...

  9. HDU_1285_拓扑排序(优先队列)

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  10. C# 获取当年的周六周日

    public void GetWMDay() { List<string> list = new List<string>(); "; DateTime counYe ...