NGUI里有没有判断ngui spritee是否在屏幕内的方法

4788人阅读
Unity3D(38)
由于最近比较忙,所以很多我在其它地方发布的博文都没有同步到这里。我会在后面慢慢重新补回来。对各位关注我博客的读者也表示抱歉!版权所有,转载须注明出处!喜欢火影、喜欢Java、喜欢unity3D、喜欢游戏开发的都可以加入木叶村Q群:0、随便聊本人真正学习Shader的时间莫过于今年春节在家的两天时间,虽然短短两天。但是已经深深喜欢上Shader。深受其魅力吸引。但是平常主要做的还是服务端和客户端的开发,偏逻辑向。所以好久也没碰Shader了。但是昨天在一个群里有人讨论NGUI不能对Sprite进行裁剪。比如把一个方形的,显示成一个圆形的。如下图:这个应该是挺常见的,或许你会说,美术直接帮你裁成圆的不就可以吗。有时候可以,有时候不行。什么时候不行呢?当你在游戏中有些地方使用方形的,有些地方使用圆形的。这时候就不能让美术帮你裁了。不然不就有两份资源了。本文读者最好已经知道怎么使用NGUI创建图集,使用它的UISprite和UITexture。本文编写测试环境为:系统:Win7 X64引擎:Unity3D V4.3.3插件:NGUI 3.5.71、开始动手作为一个学习过两天Shader的人,我觉得,这应该难不倒我。因此,我立马在U3D的Project面板中噼里啪啦一阵狂搞。创建一个Shader。2、编写第一版Shader。双击我们上面创建的Shader。因为这个是给NGUI用的。然后我就依照NGUI的Shader命名,给我们的Shader命名为:Unlit/Transparent Colored MaskShader代码如下:Shader &Unlit/Transparent Colored Mask&
Properties
_MainTex (&Base (RGB), Alpha (A)&, 2D) = &black& {}
_Mask (&Mask Alpha (A)&, 2D) = &white& {}
&Queue& = &Transparent&
&IgnoreProjector& = &True&
&RenderType& = &Transparent&
Lighting Off
ZWrite Off
Fog { Mode Off }
Offset -1, -1
Blend SrcAlpha OneMinusSrcAlpha
#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 _MainT
sampler2D _M
float4 _MainTex_ST;
float4 _Mask_ST;
v2f vert (appdata_t v)
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = v.
o.color = v.
o.gray = dot(v.color, fixed4(1,1,1,0));
fixed4 frag (v2f i) : COLOR
col = tex2D(_MainTex, i.texcoord) * i.
col.a = col.a * tex2D(_Mask, i.texcoord).a;
&Queue& = &Transparent&
&IgnoreProjector& = &True&
&RenderType& = &Transparent&
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
}主要实现裁剪的代码为:fixed4 frag (v2f i) : COLOR
col = tex2D(_MainTex, i.texcoord) * i.
col.a = col.a * tex2D(_Mask, i.texcoord).a;
}相信大家很容易就看懂了,这里是把Mask贴图的Alpha通道的值和原图片的进行相乘。怎么用呢。新建一个UItexture。然后选择一个材质。用上我们上面的Shader。然后设置一个Mask。这个Mask图片为可以看到Alpha通道里面是一个白色的圆圈。记得这个Mask图片的导入设置如下:那么可以看看运行效果:3、欢呼,庆祝?貌似一切都挺顺利的。但是这个Shader能否对UISprite起效果呢?我们来试试。随便搞个图集。然后加个UISprite,然后修改这个图集的材质使用我们的Shader。额。。。效果咋成下面这样啦。。。不太对的赶脚4、停一停想一想难道这是NGUI的bug。。。啊!!!啊!!!!!不行,我要想想看。。。。。。。。。1分钟过去了。为什么col.a = col.a * tex2D(_Mask, i.texcoord).a这个公式对Sprite的效果是错误的呢。难道i.texcoord的范围不是0~1.这么一想,倒好像也有点道理。因为NGUI把要用到的图片做成了图集。因此,每次只是取图集中的一小个区域显示到UI的Mesh上。那么,我只要把i.texcoord的范围重新映射到0~1。然后用于取Mask上面的颜色,不就OK了吗?机智的我立马动起手来。Shader &Unlit/Transparent Colored Mask&
Properties
_MainTex (&Base (RGB), Alpha (A)&, 2D) = &black& {}
_Mask (&Mask Alpha (A)&, 2D) = &white& {}
_WidthRate (&Sprite.width/Atlas.width&, float) = 1
_HeightRate (&Sprite.height/Atlas.height&, float) = 1
_XOffset(&offsetX&, float) = 0
_XOffset(&offsetY&, float) = 0
&Queue& = &Transparent&
&IgnoreProjector& = &True&
&RenderType& = &Transparent&
Lighting Off
ZWrite Off
Fog { Mode Off }
Offset -1, -1
Blend SrcAlpha OneMinusSrcAlpha
#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 _MainT
sampler2D _M
float4 _MainTex_ST;
float4 _Mask_ST;
float _WidthR
float _HeightR
v2f vert (appdata_t v)
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = v.
o.color = v.
o.gray = dot(v.color, fixed4(1,1,1,0));
fixed4 frag (v2f i) : COLOR
col = tex2D(_MainTex, i.texcoord) * i.
col.a = col.a * tex2D(_Mask, float2((i.texcoord.x-_XOffset)/_WidthRate, (i.texcoord.y-(1-_YOffset))/_HeightRate)).a;
&Queue& = &Transparent&
&IgnoreProjector& = &True&
&RenderType& = &Transparent&
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
}好了。那么怎么使用这个Shader。我们需要多一个脚本来设置这个shader的参数。using UnityE
using System.C
[ExecuteInEditMode]
public class ScaleTexcoord : MonoBehaviour
private float offX;
private float offY;
private UIS
void Awake()
s = GetComponent&UISprite&();
wr = s.GetAtlasSprite().width * 1.0f / s.atlas.spriteMaterial.mainTexture.
offX = s.GetAtlasSprite().x * 1.0f / s.atlas.spriteMaterial.mainTexture.
hr = s.GetAtlasSprite().height * 1.0f / s.atlas.spriteMaterial.mainTexture.
offY = (s.GetAtlasSprite().y + s.GetAtlasSprite().height) * 1.0f / s.atlas.spriteMaterial.mainTexture.
public void Update()
s.atlas.spriteMaterial.SetFloat(&_WidthRate&, wr);
s.atlas.spriteMaterial.SetFloat(&_HeightRate&, hr);
s.atlas.spriteMaterial.SetFloat(&_XOffset&, offX);
s.atlas.spriteMaterial.SetFloat(&_YOffset&, offY);
}只要把这个脚本附在UISprite上即可。可以发现现在正常了。NGUI图集的材质变成了好了。这次真的可以好好庆祝下啦~~整个效果其实只用上面的Shader和那个ScaleTexcoord.cs即可。:
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:414493次
积分:5729
积分:5729
排名:第2568名
原创:79篇
译文:38篇
评论:383条
二次创业中
喜欢火影、喜欢Java、喜欢Unity3D、喜欢游戏开发的都可以加入木叶村Q群:NGUI所见即所得之UISprite - 推酷
NGUI所见即所得之UISprite
& & & & UISprite是NGUI最基础的组件,是UIWidget的子类,之前写过
&UIWidget,UIGeometry & UIDrawCall是NGUI的UI组件绘制的底层实现,UISprite等UI组件就把要绘制的材料——顶点,纹理,纹理UV,颜色值等传给底层,底层负责协调绘制渲染。
& & & & NGUI3.0.3d版本已经将UISprite,UIFillSprite,UISliceSprite,UITiledSprite整合在一个UISprite中,用Type来区分:
public enum Type
& & & & UISprite主要是重写(override)OnFill函数——把Vertices,UVs和Colors添加进UIGeometry中。在分析OnFill之前,先看下drawingDimensions的实现:
/// &summary&
/// Sprite's dimensions used for drawing. X = left, Y = bottom, Z = right, W = top.
/// This function automatically adds 1 pixel on the edge if the sprite's dimensions are not even.
/// It's used to achieve pixel-perfect sprites even when an odd dimension sprite happens to be centered.
/// &/summary&
Vector4 drawingDimensions
if (mSprite == null)
return new Vector4(0f, 0f, mWidth, mHeight);
int padLeft = mSprite.paddingL
int padBottom = mSprite.paddingB
int padRight = mSprite.paddingR
int padTop = mSprite.paddingT
Vector2 pv = pivotO
int w = mSprite.width + mSprite.paddingLeft + mSprite.paddingR
int h = mSprite.height + mSprite.paddingBottom + mSprite.paddingT
if ((w & 1) == 1) ++padR
if ((h & 1) == 1) ++padT
float invW = 1f /
float invH = 1f /
Vector4 v = new Vector4(padLeft * invW, padBottom * invH, (w - padRight) * invW, (h - padTop) * invH);
v.x -= pv.x;
v.y -= pv.y;
v.z -= pv.x;
v.w -= pv.y;
& & & & 其实drawingDimensions可以看成纹理贴图的x,y轴的区间,也就是说纹理在x轴区间为(v.x, v.z),y轴区间为(v.y,v.w)的矩形。注释中,说道如果drawingDimension不是偶数,则会添加一个像素,这个处理导致UISprite的类型是Tiled,有可能出现间隙,网上也有人通过设置一个像素的Border来解决这个问题,当然最本质就是纹理贴图像素是偶数的。
& & & & 下面给出OnFill函数,在代码中给出注释:
public override void OnFill (BetterList&Vector3& verts, BetterList&Vector2& uvs, BetterList&Color32& cols)
Texture tex = mainT
if (tex != null)
if (mSprite == null) mSprite = atlas.GetSprite(spriteName);
if (mSprite == null)
mOuterUV.Set(mSprite.x, mSprite.y, mSprite.width, mSprite.height);
mInnerUV.Set(mSprite.x + mSprite.borderLeft, mSprite.y + mSprite.borderTop,
mSprite.width - mSprite.borderLeft - mSprite.borderRight,
mSprite.height - mSprite.borderBottom - mSprite.borderTop);
mOuterUV = NGUIMath.ConvertToTexCoords(mOuterUV, tex.width, tex.height);
// Convert from top-left based pixel coordinates to bottom-left based UV coordinates.
mInnerUV = NGUIMath.ConvertToTexCoords(mInnerUV, tex.width, tex.height);
switch (type)
case Type.Simple:
SimpleFill(verts, uvs, cols);
case Type.Sliced:
SlicedFill(verts, uvs, cols);
case Type.Filled:
FilledFill(verts, uvs, cols);
case Type.Tiled:
TiledFill(verts, uvs, cols);
& & & SimpleFill最简单了,直接添加Verts,UVs,Colors,SimpleFill就只有四个顶点绘制贴图,SliceFill,TiledFill,FiledFill都是转换为SimpleFill的情况来绘制的。
protected void SimpleFill (BetterList&Vector3& verts, BetterList&Vector2& uvs, BetterList&Color32& cols)
Vector2 uv0 = new Vector2(mOuterUV.xMin, mOuterUV.yMin);
Vector2 uv1 = new Vector2(mOuterUV.xMax, mOuterUV.yMax);
Vector4 v = drawingD
verts.Add(new Vector3(v.x, v.y));
verts.Add(new Vector3(v.x, v.w));
verts.Add(new Vector3(v.z, v.w));
verts.Add(new Vector3(v.z, v.y));
uvs.Add(uv0);
uvs.Add(new Vector2(uv0.x, uv1.y));
uvs.Add(uv1);
uvs.Add(new Vector2(uv1.x, uv0.y));
Color colF =
colF.a *= mPanel.
Color32 col = atlas.premultipliedAlpha ? NGUITools.ApplyPMA(colF) : colF;
cols.Add(col);
cols.Add(col);
cols.Add(col);
cols.Add(col);
& & & SliceFill其实就是把矩形纹理切成九宫格,就是九个SimpleFill,贴出注释,详细看源码:
& & & & & & & & & & & & & & & & & & & & & &Sliced sprite fill function is more complicated as it generates 9 quads instead of 1.
& & & TiledFill可以简单的看成:(组件面积/纹理贴图面积 )个SimpleFill
& & & &FilledFill代码是很复杂,但是其实也是把扇形切割成四边形来SimpleFill
& & & &这种解决问题的方法很值得借鉴,记得高中的时候解数学难题一般都是将复杂问题分解成多个简单的问题,SimpleFill相当于是一个子问题,Slice,Tiled,Filed都是转化为Simple的情况来解决,这个点推到动态规划算法的方程一样,如果对问题理解好了,自然就迎刃而解。
& & & & 其实,UISprite很简单,不难,只是之前一直对Filed ,Slice,Tiled的实现很好奇,感觉很神奇,当然D.S.Qiu还有很多没有弄明白的:
& & & & & & & & 1.UVs是的作用是,
& & & & & & & & 2.在哪里指定材质Material或纹理
& & & & & & & & 3.Unity单位和屏幕分辨率以及像素大小的关系,现在感觉挺混乱的。
还是尽早去琢磨UIPanel吧。
& & & & 如果您对D.S.Qiu有任何建议或意见可以在文章后面评论,或者发邮件(gd.s.)交流,您的鼓励和支持是我前进的动力,希望能有更多更好的分享。
& & & & 转载请在文首注明出处:
更多精彩请关注D.S.Qiu的博客和微博(ID:静水逐风)
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
排版有问题
没有分页内容
视频无法显示
图片无法显示}

我要回帖

更多关于 ngui sprite 透明度 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信