【Unity&Shader】NGUI实现图集变灰功能
来源:互联网 发布:mac图片处理 编辑:程序博客网 时间:2024/05/21 23:34
原文地址:http://bbs.9ria.com/thread-434334-1-1.html
需求分析
- 直接调整Sprite或者Texture的Color值达不到美术所要的效果
- 节省资源,为了实现去色效果,美术不必提供另外一张PS处理过后的图集,只需要程序修改shader动态处理即可怎么做
- 修改NGUI使用的Shaders(新添加四个,为什么后文讲解)
- 制作XX_Gary图集
- 编写统一逻辑接口针对Sprite切换图集,针对UITexture切换Shader
注意下NGUI使用的默认shader,该例子使用的是NGUI3.6.6,NGUI默认使用的一系列shader为下图 1 2 3 结尾,稍微提前一点的版本shader下图(SoftClip)(AlphaClip)复制出来四个按照原来的规则修改名字,注意一定要前缀一致,因为NGUI内部实现裁剪是需要通过修改后缀找到相应的shader进行替换实现的,然后在修改四个shader的内容,找到每个Shader内容的frag函数,在最后都加上同一段代码即可(前面各种计算得到col,再返回前将最终的col结果在进行一次处理)
<font color=
"#000000"
>half4 frag (v2f IN) : COLOR
{
// ......
//For gray shader change rgb value
float
grey = dot(col.rgb, float3(0.299, 0.587, 0.114));
col.rgb = float3(grey, grey, grey);
return
col;
}</font>
游戏中针对需要置灰的元素图集需要重新制作一个额外的Gray图集,Normal图集和Gray图集使用同一个2DTexture,使用不同的材质
编写处理逻辑
统一的处理接口,基本原理是针对UISprite更换图集,针对UITexture更换Shader即可
具体的一种实现方式如下
<font color="#000000">using UnityEngine;using System.Collections;using System.Collections.Generic;public class GrayUIController : MonoBehaviour{ // UISprite : 更换图集(正常和置灰图集切换) // UITexture:更换Shader为正常Shader和置灰使用的Shader / 1.将同一个图集中的图片单独的变灰操作 2.将UITexture变灰去色 / // 维护一个图集List // 置灰图集 // 正常图集 public List grayAtlas; public List normalAtlas; public Hashtable shaderTable = new Hashtable(); public enum AtlasName { EM_AtlasName_None = -1, EM_AtlasName_CommonAtlas, } private static GrayUIController instance = null; public static GrayUIController GetInstance() { return instance; } void Awake() { instance = this; } /// /// 将制定GameObject存在的UITexture和UISprite去色,变灰 /// /// 目标物体 /// 是否变灰 /// 制定图集 public void ChangeObjectsToGray(GameObject targetObj, bool gray, AtlasName atlasName = AtlasName.EM_AtlasName_None) { UISprite[] sprites = targetObj.GetComponentsInChildren(); UITexture[] textures = targetObj.GetComponentsInChildren(); for (int i = 0; i < sprites.Length; i++) ChangeUISpriteToGray(sprites, gray, atlasName); for (int i = 0; i < textures.Length; i++) ChangeUITextureToGary(textures, gray); } public bool ChangeUISpriteToGray(UISprite targetSprite, bool toGray, AtlasName atlasName = AtlasName.EM_AtlasName_None) { bool toGarySucess = false; if (targetSprite != null) { List findAtlas = new List(); if (toGray) findAtlas = grayAtlas; else findAtlas = normalAtlas; UISpriteData findData = null; string spriteName = targetSprite.spriteName; // 如果指定图集,不用查找直接更换图集即可(高效方式) if (atlasName != AtlasName.EM_AtlasName_None) { findData = findAtlas[(int)atlasName].GetSprite(spriteName); if (findData != null) { targetSprite.atlas = findAtlas[(int)atlasName]; toGarySucess = true; } } else { // 未指定图集,需要从现有的图集中查找对应的图集 for (int i = 0; i < findAtlas.Count; i++) { findData = findAtlas.GetSprite(spriteName); if (findData != null) { targetSprite.atlas = findAtlas; toGarySucess = true; break; } } } } return toGarySucess; } /// /// 将UITexture置灰操作 /// /// /// public void ChangeUITextureToGary(UITexture texture, bool toGray) { Shader newShader = null; if (toGray) { // 保存UITexture原Shader if (!shaderTable.ContainsKey(texture)) shaderTable[texture] = texture.shader; newShader = Shader.Find("Unlit/GrayShader"); } else { // 恢复原Shader if (shaderTable.ContainsKey(texture)) newShader = (Shader)shaderTable[texture]; else newShader = Shader.Find("Unlit/Transparent Colored"); } texture.shader = newShader; } private bool changeToGray = true; public GameObject targets; public void TestChangeGray() { ChangeObjectsToGray(targets, changeToGray, AtlasName.EM_AtlasName_CommonAtlas); changeToGray = !changeToGray; }}</font>
问题
为何要复制出来四个shader,如果只复制出来一个基本shader而没有复制另外三个处理裁剪的shader,当你在ScrollView等还有裁剪的Panel中存在变灰元素的时候就会提示"找不到xxshader"的错误,具体随着错误就知道在UIDrawCall中进行了裁剪过程的Shader替换(UIDrawCall中的CreateMaterial函数)
<font color=
"#000000"
>
void
CreateMaterial ()
{
// .....
if
(shaderName.StartsWith(
"Hidden/"
))
shaderName = shaderName.Substring(7);
// Legacy functionality
const
string
soft =
" (SoftClip)"
;
shaderName = shaderName.Replace(soft,
""
);
if
(mClipCount != 0)
{
shader = Shader.Find(
"Hidden/"
+ shaderName +
" "
+ mClipCount);
if
(shader ==
null
) Shader.Find(shaderName +
" "
+ mClipCount);
// Legacy functionality
if
(shader ==
null
&& mClipCount == 1)
{
mLegacyShader =
true
;
shader = Shader.Find(shaderName + soft);
}
}
else
shader = Shader.Find(shaderName);
// ......
}</font>
如果创建了一个新的图集,会不会造成内存存在两张贴图,答案是不会,因为两个图集使用的同一张贴图,只不过材质球不一样而已,你可以在运行的时候打开Profiler查看图集引用的贴图,然后比对下内存使用情况即可
效果演示
Demo下载
(导入的DEMO,的NGUI文件夹可能有问题,请删除,重新导入正确的NGUI)
Unity3D学习笔记——NGUI之UIScrollView
- 【Unity&Shader】NGUI实现图集变灰功能
- Unity NGUI灰化Shader
- 【Unity】代码实现NGUI按钮监听功能
- 【Unity】用NGUI实现摇杆功能
- Unity基于NGUI实现拖拽功能
- [Unity] Unity中实现羽化功能的shader
- unity-使用NGUI 两个Button实现左右切换功能
- unity技术之NGUI的功能实现(1)
- unity技术之NGUI的功能实现(2)
- Unity NGUI实现技能冷却
- unity shader编写(一),漫反射shader实现
- 【Unity快速实现小功能】NGUI篇——实现点击有链接的文本
- 【Unity快速实现小功能】NGUI篇——快速实现一个可滑动列表
- 【Unity快速实现小功能】NGUI篇——实现点击有链接的文本
- 【Unity Shader】NGUI中图标的灰化处理
- unity遮罩_3(NGUI遮罩 UIPanel功能)
- Unity手游开发--NGUI实现冷却技能(CD)功能
- RPG 游戏 unity ngui 实现2D名字牌血条等功能
- 【每日一记】设计模式——备忘录模式
- vector容器类的使用
- 北纬数码专营店奇遇记
- APP测试方法总结
- 如何利用老域名SEO优化快速上百度首页
- 【Unity&Shader】NGUI实现图集变灰功能
- bzoj 3043: IncDec Sequence 差分
- 【codeforces 550D】Regular Bridge
- 微信公众号开发生成自定义菜单
- 数据库事务
- iOS ---- 混合模式(引导页)
- 网络是否可用的广播
- 杭电2013蟠桃记
- 代码整洁之道 命名 函数