NGUI裁剪粒子的实现,完全仿照原有的NGUI SoftClip逻辑思路,可多层裁剪
来源:互联网 发布:国外网络安全设备品牌 编辑:程序博客网 时间:2024/05/22 06:15
参照http://blog.csdn.net/tkokof1/article/details/52107736 这一篇博客
但是他只实现了单层panel的裁剪,虽然他的算法和NGUI的思路是一致的,但是由于传入Shader的值不同,所以不太好移植成多层Panel裁剪。我重新对他的思路进行整理了,并且将值统一为NGUI的规则,传入的值都用_ClipRange0和_ClipArgs0表示。首先是C#端代码
void UpdateClip(UIPanel panel) { if (mCam == null) return; UIPanel currentPanel = panel; Vector4 cr = new Vector4(); //计算距离最近的父Panel的中心点 这个点存着 如果有多层的话 就可以用panelCenter,这样不需要重复计算了 var panelWorldCorners1 = panel.worldCorners; var leftBottom1 = mCam.WorldToViewportPoint(panelWorldCorners1[0]); var topRight1 = mCam.WorldToViewportPoint(panelWorldCorners1[2]); var panelCenter = Vector3.Lerp(leftBottom1, topRight1, 0.5f); //遍历所有的父Panel(所以支持嵌套的Soft Clip) for (int i = 0; currentPanel != null;) { //如果父Panel节点有裁剪 if (currentPanel.hasClipping) { //这个里面计算裁剪范围和父Panel和当前DrawCall所属的Panel的角度 float angle = 0f; //Vector4 cr = currentPanel.drawCallClipRange; // 与NGUI逻辑不同的第一处 这里将坐标统一为ViewPort坐标系 var panelWorldCorners = currentPanel.worldCorners; var leftBottom = mCam.WorldToViewportPoint(panelWorldCorners[0]); var topRight = mCam.WorldToViewportPoint(panelWorldCorners[2]); var center = Vector3.Lerp(leftBottom, topRight, 0.5f); cr.x = panelCenter.x; cr.y = panelCenter.y; cr.z = (topRight.x - leftBottom.x) / 2; cr.w = (topRight.y - leftBottom.y) / 2; //如果有多重Soft Clip的话 就会走到这里 // Clipping regions past the first one need additional math if (currentPanel != panel) { //这里的计算方式其实是完全一样的 只不过计算的值统一为ViewPort坐标系了 Vector3 pos = panelCenter - center; //Vector3 pos = currentPanel.cachedTransform.InverseTransformPoint(panel.cachedTransform.position); cr.x -= pos.x; cr.y -= pos.y; Vector3 v0 = panel.cachedTransform.rotation.eulerAngles; Vector3 v1 = currentPanel.cachedTransform.rotation.eulerAngles; Vector3 diff = v1 - v0; //其实这个函数就是 把角度限制在-180和180之间 diff.x = NGUIMath.WrapAngle(diff.x); diff.y = NGUIMath.WrapAngle(diff.y); diff.z = NGUIMath.WrapAngle(diff.z); if (Mathf.Abs(diff.x) > 0.001f || Mathf.Abs(diff.y) > 0.001f) Debug.LogWarning("Panel can only be clipped properly if X and Y rotation is left at 0", panel); //因为是界面 所以角度是平面的 只有Z是有效角度 angle = diff.z; } var soft = currentPanel.clipSoftness; var sharpness = new Vector2(1000.0f, 1000.0f); if (soft.x > 0f) { sharpness.x = panel.baseClipRegion.z / soft.x; } if (soft.y > 0f) { sharpness.y = panel.baseClipRegion.w / soft.y; } //这里就是真正设置裁剪的地方了,我们看看这里的各个参数的意义吧。 //如果只是单层Soft Clip的话 // i = 0, // cr就是this.panel的 drawCallClipRange,而这个drawCallClipRange的各个参数意义是这样的: x:中心点X坐标 y:中心点Y坐标 z:panel width的一半, w:panel height的一半 // currentPanel.clipSoftness 软裁剪设置的渐变边缘 // angle 与父Panel的角度 如果 是单层shader的话,这个角度是0(而且shader里面也不会用到) // Pass the clipping parameters to the shader for (int j = 0; j < _materials.Count; ++j) SetClipping(_materials[j], i, cr, sharpness, angle); ++i; } currentPanel = currentPanel.parentPanel; } } void SetClipping(Material material, int index, Vector4 cr, Vector2 soft, float angle) { angle *= -Mathf.Deg2Rad; if (index < ClipRange.Length) { material.SetVector(ClipRange[index], new Vector4(-cr.x / cr.z, -cr.y / cr.w, 1f / cr.z, 1f / cr.w)); material.SetVector(ClipArgs[index], new Vector4(soft.x, soft.y, Mathf.Sin(angle), Mathf.Cos(angle))); } }
具体的算法注释上写了 应该和NGUI的代码90%是相似的 ,分析可以参照我的上一篇SoftClip分析:http://blog.csdn.net/nxshow/article/details/72864419
接下来是一层裁剪panel的时候用到的Shader
Shader "Custom/Particles/Additive 1"{Properties{_TintColor("Tint Color", Color) = (0.5,0.5,0.5,0.5)_MainTex("Particle Texture", 2D) = "white" {}}Category{Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }Blend SrcAlpha OneCull Off Lighting Off ZWrite Off Fog{ Color(0,0,0,0) }SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;fixed4 _TintColor;float4 _ClipRange0 = float4(0.0, 0.0, 1.0, 1.0);float2 _ClipArgs0 = float2(1000.0, 1000.0);struct appdata_t {float4 vertex : POSITION;fixed4 color : COLOR;float2 texcoord : TEXCOORD0;};struct v2f {float4 vertex : SV_POSITION;fixed4 color : COLOR;float2 texcoord : TEXCOORD0;float2 worldPos : TEXCOORD1;};float4 _MainTex_ST;v2f vert(appdata_t v){v2f o;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.color = v.color;o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);// 统一成ViewPort坐标系float2 clipSpace = o.vertex.xy / o.vertex.w;clipSpace = (clipSpace.xy + 1) * 0.5;o.worldPos = clipSpace * _ClipRange0.zw + _ClipRange0.xy;return o;}fixed4 frag(v2f i) : SV_Target{fixed4 c = 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);// Softness factor float2 factor = (float2(1, 1) - abs(i.worldPos)) * _ClipArgs0.xy;c.a *= clamp(min(factor.x, factor.y), 0.0, 1.0);return c;}ENDCG}}}}
只改了一个地方,就是将坐标统一成ViewPort坐标系
接下来是有两层Panel裁剪的Shader,一样的
Shader "Custom/Particles/Additive 2"{Properties{_TintColor("Tint Color", Color) = (0.5,0.5,0.5,0.5)_MainTex("Particle Texture", 2D) = "white" {}}Category{Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }Blend SrcAlpha OneCull Off Lighting Off ZWrite Off Fog{ Color(0,0,0,0) }SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;fixed4 _TintColor;float4 _ClipRange0 = float4(0.0, 0.0, 1.0, 1.0);float4 _ClipArgs0 = float4(1000.0, 1000.0, 0.0, 1.0);float4 _ClipRange1 = float4(0.0, 0.0, 1.0, 1.0);float4 _ClipArgs1 = float4(1000.0, 1000.0, 0.0, 1.0);struct appdata_t {float4 vertex : POSITION;fixed4 color : COLOR;float2 texcoord : TEXCOORD0;};struct v2f {float4 vertex : SV_POSITION;fixed4 color : COLOR;float2 texcoord : TEXCOORD0;float4 worldPos : TEXCOORD1;};float4 _MainTex_ST;float2 Rotate(float2 v, float2 rot){float2 ret;ret.x = v.x * rot.y - v.y * rot.x;ret.y = v.x * rot.x + v.y * rot.y;return ret;}v2f vert(appdata_t v){v2f o;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.color = v.color;o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);// 统一成ViewPort坐标系float2 clipSpace = o.vertex.xy / o.vertex.w;clipSpace = (clipSpace.xy + 1) * 0.5;o.worldPos.xy = clipSpace * _ClipRange0.zw + _ClipRange0.xy;o.worldPos.zw = Rotate(clipSpace, _ClipArgs1.zw) * _ClipRange1.zw + _ClipRange1.xy;return o;}fixed4 frag(v2f i) : SV_Target{fixed4 c = 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);// First clip regionfloat2 factor = (float2(1.0, 1.0) - abs(i.worldPos.xy)) * _ClipArgs0.xy;float f = min(factor.x, factor.y);// Second clip regionfactor = (float2(1.0, 1.0) - abs(i.worldPos.zw)) * _ClipArgs1.xy;f = min(f, min(factor.x, factor.y));c.a *= clamp(f, 0.0, 1.0);return c;}ENDCG}}}}
阅读全文
0 0
- NGUI裁剪粒子的实现,完全仿照原有的NGUI SoftClip逻辑思路,可多层裁剪
- NGUI 粒子系统裁剪
- 对NGUI的UISprite和UITexture进行裁剪,圆形裁剪
- NGUI 圆形 裁剪
- 【解决方案】NGUI - UIPanel的Clipping功能无法裁剪子UIPanel
- [Shader]对NGUI的UISprite和UITexture进行裁剪
- [Shader]对NGUI的UISprite和UITexture进行裁剪
- NGUI UIPanel在softClip下不起作用的问题
- 模仿NGUI实现SoftClip(一)
- 模仿NGUI实现SoftClip(二)
- UGUI-仿照NGUI的事件监听机制
- 任意多边形裁剪圆的实现思路
- [Shader]对NGUI的UISprite和UITexture进行裁剪(scrollview + 遮罩)
- 粒子显示在ngui之间的方法
- NGUI与粒子系统的遮挡问题
- NGUI sprite 裁剪到其他图片sprite
- NGUI利用两个摄像机裁剪特效
- NGUI 图集解包的实现
- 一篇写的很好的XGBoost的博客(于简书转载)
- 哈希学习
- Android 封装工具类之吐司
- 简易航班订票系统
- 九九乘法表
- NGUI裁剪粒子的实现,完全仿照原有的NGUI SoftClip逻辑思路,可多层裁剪
- 认识“安卓”,于我,也于所有想学习安卓的人
- 面向对象程序设计的结构
- 【八中测试】平分石子
- Linux (centos7) 防火墙命令
- Android 封装工具类之共享参数
- bzoj2425 [HAOI2010]计数 组合数
- 转:SKLearn中预测准确率函数介绍
- Object-c Blocks的理解