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. 如何自学编程,零基础适合学习Java或者Web前端吗,非科班的能学java吗?

    很多人都会选择自学Java或者前端,相信有在校的大学生,有正在上班想转行的,也有已经在自学的.下面通过几个问题我来给大家分析学习编程的难易程度. 编程是什么? 通俗的理解,编程就是编写程序,哪什么是程 ...

  2. javascript中for...in和for...of的区别

    for...of循环是ES6引入的新的语法. for...in遍历拿到的x是键(下标).而for...of遍历拿到的x是值,但在对象中会提示不是一个迭代器报错.例子如下: let x; let a = ...

  3. python自动化测试学习笔记-2-列表

    上次我们学习了python的基本概念,了解了python的变量及数据类型,并实战了条件判断,for/while循环,字符串输出,格式化输出的一些基本用法,接下来我们继续学习其他的一些数据类型. pyt ...

  4. mysql中类型转换

    MySQL 的CAST()和CONVERT()函数可用来获取一个类型的值,并产生另一个类型的值 CAST(xxx AS 类型), CONVERT(xxx,类型) 二进制,同带binary前缀的效果 : ...

  5. Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树

    思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用  lazy=0 没被覆盖过 els ...

  6. 363 Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  7. lua_string_pattern

    两大特点: 1. string库中所有的字符索引从前往后是1,2,...;从后往前是-1,-2,... 2. string库中所有的function都不会直接操作字符串,而是返回一个新的字符串. 库函 ...

  8. 【转】Java 集合系列06之 Vector详细介绍(源码解析)和使用示例

    概要 学完ArrayList和LinkedList之后,我们接着学习Vector.学习方式还是和之前一样,先对Vector有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它.第1部分 Vec ...

  9. MySQL 多表批量更新

    使用inner join 进行表更新sql 与mysql 的区别: SQL UPDATE W SET W.字段=新数据 FROM 表a W INNER JOIN 表B d ON W.wID=D.wid ...

  10. 超经典~超全的jQuery插件大全

    海量的jQuery插件帖,很经典,不知道什么时候开始流传,很早以前就收藏过,为了工作方便还是发了一份放在日志里面. 其中有些已经无法访问,或许是文件移除,或许是被封锁.大家分享的东西,没什么特别的可说 ...