一般游戏中,字体贴图是游戏贴图压缩的一个重点,特别是对于中文的游戏。考虑的字体贴图的特殊性,一般我们输出的字体贴图是不含颜色信息的,所以正常情况下,我们输出的字体贴图RGBA每一个通道都是一样的。这样一来,就存在非常大的浪费。所以我们能够在RGBA四个通道中能够保存不同的字体,这样,我们的贴图的大小能够降低4倍。假设我们想使用ETC压缩的话,我们可还以直接不使用Alpha通道,仅仅在RGB三个通道中存储不同的文字(这样,假设我们要进行ETC压缩的话,不须要对Alpha通道做分离处理了,可是得到的ETC会比正常的图片压缩成ETC后的要模糊,这跟ETC的压缩机制(採样)有关,这跟AAA比ABB或者AWW压缩成ETC之后清晰是相同的道理,有兴趣也能够研究下)。由于不同的通道中包括了不同的文字,所以我们须要使用NGUI一个特殊的Shader,Unlit/Transparent
Colored (Packed)。要理解这个shader,我们首先来看一下一般我们使用多通道字体贴图的时候,fnt文件里包括的信息

在这里这个chnl就是表明当前这个文字是存储在哪一个通道,R、G、B、A分别相应1,2,4,8. 然后我们来看一下Shader的核心代码

half4 frag (v2f IN) : COLOR
{
half4 mask = tex2D(_MainTex, IN.texcoord);
half4 mixed = saturate(ceil(IN.color - 0.5));
half4 col = saturate((mixed * 0.51 - IN.color) / -0.49); mask *= mixed;
col.a *= mask.r + mask.g + mask.b + mask.a;
return col;
}

乍一看,感觉非常奇怪的样子,特别是这里有两个比較特别的数字5.1和0.49.事实上这里跟NGUI的处理机制有关系,NGUI主要通过变换传入的顶点颜色(IN.color)来进行处理。那么我们IN.color的取值是怎么设定的呢?这里我们简单来推导一下这里的公式,首先摆在我们眼前的问题是,我们在shader中要知道当前的文字是要读取RGB的哪一个通道,那我们怎样得知呢?一个简单的办法,我们能够变换IN.color的RGB,使得,当前通道的色值>0.5,而其它的通道小于0.5.那么我们在shader中就能够简单的通过

half4 mixed = saturate(ceil(IN.color - 0.5));//假设值在0-0.5区间,那么结果为0,假设值为0.5-1,值为1

来得到当前文字所在的通道了(为1的就是当前的通道)。那么我们怎么使得其它的通道的颜色值<0.5呢?我们知道RGB默认的取值范围为0-1,那么我们能够简单的乘以0.49,这样范围就在0-0.49之间了(即满足<0.5),我们如果NGUI设置的UIlabel的颜色为X,那么通过上面的处理,IN.color = X * 0.49。如今,全部通道的颜色范围都在0-0.49之间,而我们须要我们当前通道的颜色>0.5,所以我们能够简单的对当前通道的色值加上0.51,那么当前通道的颜色值取值范围就到了0.51-1,从而满足了条件。这时候IN.color
= X *0.49 + M *0.51(当中M中当前通道的值为1,其它通道的值为0,如当前如R通道的话,M=(1,0,0),事实上这里M取值就相当于上线的mixed)。这个时候,我们仅仅要依据文字设置的颜色所在的通道设置In.color的值就能够了。那么,反过来,我们在Shader中怎样还原字体的颜色值X呢?依据IN.color = X *0.49 + M *0.51,我们能够非常easy的得到X = (M*0.51-In.color)/0.49.相信到这里,大家都应该明确了,这就是shader中代码

half4 col = saturate((mixed * 0.51 - IN.color) / -0.49);

的由来。

文字的颜色我们设置OK了,那么剩下的仅仅须要得到文字的轮廓就好了。也就是设置相应的col的alpha值。比方说假设当前通道为R,那么我的col.a 设置成R通道的值就能够了,这样R通道中有文字的地方(a>0)就会显示出来,其它地方就不会显示(a=0)。也就是说我们得到的是R通道中文字的轮廓,代码例如以下

<pre name="code" class="csharp">half4 mask = tex2D(_MainTex, IN.texcoord);
mask *= mixed;            //处理后,mask中仅仅保留了当前通道的颜色值,其它通道为0,如红色通道(R,0,0)
col.a *= mask.r + mask.g + mask.b + mask.a; //col.a = 当前通道的颜色值


注:1、关于怎样得到多通道贴图(这里我们使用BFont)

2、得到的贴图演示样例

3、相对于直接使用Alpha8的长处

a、假设使用Alpha8贴图的话,假设文字无法恰好填满一个标准大小时,会存在浪费(主要内存占用大小)。如一张1024*1024的贴图

假设放RGB三个通道就会好非常多。

b、相对于Unity中使用Alpha,多通道贴图还能够进一步压缩,比方说压缩成RGB565(16Bit)。而Alpha8贴图是无法这样处理的。

NGUI字体贴图压缩以及相关Shader解读的更多相关文章

  1. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图 代码工程地址: https://github.c ...

  2. WebGL 利用FBO完成立方体贴图。

    这篇主要记录WebGL的一些基本要点,顺便也学习下如何使用FBO与环境贴图.先看下效果图(需要支持WebGL,Chrome,火狐,IE11). 主要实现过程如下,先用FBO输出当前环境在立方体纹理中, ...

  3. mui开发app之多图压缩与上传(仿qq空间说说发表)

    欲实现效果图 提出需求点: 用户可自由添加删除替换多张图片,并且显示相应缩略图,限制为8张 用户可选择压缩图或直接上传原图功能 返回提醒用户会丢失填写的信息 下面一个个实现上述需求,从简单到复杂: 需 ...

  4. OpenGL 核心技术之立方体贴图

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家.特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  5. Unity Shaders and Effects Cookbook (4-1)(4-2)静态立方体贴图的创建与使用

    開始学习第4章 - 着色器的反射 看完了1.2节,来记录一下.反射主要是利用了 Cubemap 立方体贴图. 认识Cubemap 立方体贴图.就如同名字所说.在一个立方体上有6张图.就这样觉得吧. 假 ...

  6. 立方体贴图(Cubemap)

    http://blog.csdn.net/asdjy123/article/details/51190643 点击打开链接 好东西保存方便查看 立方体贴图(Cubemap) 原文 Cubemaps 作 ...

  7. OpenGL+OpenCV实现立方体贴图

    我屮艸芔茻,转眼就7月份了. 今天试了一下立方体贴图,比较简单,大概说下和平面贴图的区别. 1. 平面贴图需要的是纹理坐标vec2:立方体贴图需要的是一个方向向量vec3,长度没有关系,重要的是方向, ...

  8. threejs立方体贴图产生边缘锯齿问题

    threejs立方体贴图产生边缘锯齿问题 立方体贴图边缘锯齿 解决后 经过试验测试发现, textureGrass.wrapS和 textureGrass.wrapT属性导致的. 解决方法1: 删掉t ...

  9. PAT甲级 图的遍历 相关题_C++题解

    图的遍历 PAT (Advanced Level) Practice 图的遍历 相关题 目录 <算法笔记>重点摘要 1021 Deepest Root (25) 1076 Forwards ...

随机推荐

  1. JAVA GUI学习 - JList列表、JScrollPane滚动条组件学习

    /** * 本例结合JList和JScrollPane共同使用 * @author Wfei * */ public class JListKnow extends JFrame { JList jL ...

  2. [编程语言][java][java se]java泛型中? T K V E含义(学习)

    ? 表示不确定的java类型,类型是未知的. T  表示java类型. K V 分别代表java键值中的Key Value. E 代表Element,特性是枚举. 1.意思     jdk中的K,V, ...

  3. Linux 内核的编译系统

    Linux  的编译使用 GNU make 工具来检查整个系统的文件和调用 gcc 工具以及脚本完毕编译源码生成 image 等操作.要了解整个编译系统,我们首先要了解 Linux 内核的 Makef ...

  4. Android 中文API (66) —— BluetoothClass.Device

    前言 本章内容是android.bluetooth.BluetoothClass.Device,为Android蓝牙部分的章节翻译,版本为Android 2.3   r1,翻译来自中山大学的" ...

  5. GDI+入门——带你走进Windows图形的世界

    一.GDI+基础 1.GDI+简单介绍 GDI+是微软的新一代二维图形系统,它全然面向对象,要在Windows窗口中显示字体或绘制图形必需要使用GDI+.GDI+提供了多种画笔.画刷.图像等图形对象, ...

  6. 解决shell脚本中 echo 怎么写入换行到文件

    測试环境:ubuntu12.04 LTS版本号 echo >> file.txt就可以, 这样的方法对于脚本开头是bash和sh效果都一样, 而echo -e >> file. ...

  7. HYSBZ1588 营业额统计【Splay】

    转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4366582.html   ---by 墨染之樱花 [题目链接]http://www.lydsy ...

  8. SharePoint 2010以其他用户身份登录的弹出代码

    在SharePoint 2010平台中,可以在当前用户登录系统的情况下使用其他用户身份登录,以达到在同一浏览器中切换用户身份的目的. 每个用户登录SharePoint系统之后都会在系统右上角将用户的名 ...

  9. .net平台是什么?.net平台的组成,.net平台的好处

    1..net(dotnet)平台是什么? .net平台是微软公司设计的一个用于开发各种应用的"框架"和程序的运行环境. 2..net平台的组成: a..net Framework( ...

  10. 基于百度地图api + AngularJS 的入门地图

    转载请注明地址:http://www.cnblogs.com/enzozo/p/4368081.html 简介: 此入门地图为简易的“广州大学城”公交寻路地图,采用很少量的AngularJS进行inp ...