zoukankan      html  css  js  c++  java
  • Unity NGUI 多个UIPanel对粒子的剪裁

    之前写过一篇单个 UIPanel 对粒子的裁剪,地址是:https://www.cnblogs.com/jietian331/p/5075487.html

    但项目中有时会遇到多个UIPanel,如下面问题,UISprite 被剪裁了,但粒子未被剪裁:

     

    转载请注明出处:https://www.cnblogs.com/jietian331/p/10938837.html

    这时解决问题的思路是,找出所有的有剪裁功能的 UIPanel,并求出它们剪裁区域的交集然后传到shader中,效果如下:

      

    代码如下:

      1 using System.Collections.Generic;
      2 using UnityEngine;
      3 
      4 namespace Modules.UI
      5 {
      6     // 对子节点下所有的粒子和模型进行剪裁,且支持多个 UIPanel
      7     public class EffectClip : MonoBehaviour
      8     {
      9         List<Material> m_materials;
     10         List<UIPanel> m_uiPanels;
     11         UIRoot m_uiRoot;
     12 
     13 
     14         #region Properties
     15 
     16         UIRoot ObjUIRoot
     17         {
     18             get
     19             {
     20                 if (!m_uiRoot)
     21                     m_uiRoot = GetComponentInParent<UIRoot>();
     22                 return m_uiRoot;
     23             }
     24         }
     25 
     26         // 找到所有粒子,模型的material
     27         List<Material> Materials
     28         {
     29             get
     30             {
     31                 if (m_materials == null)
     32                 {
     33                     m_materials = new List<Material>();
     34 
     35                     // particle system 的剪裁
     36                     var particleSystems = GetComponentsInChildren<ParticleSystem>();
     37                     for (int i = 0, j = particleSystems.Length; i < j; i++)
     38                     {
     39                         var ps = particleSystems[i];
     40                         var mat = ps.GetComponent<Renderer>().material;
     41                         string shaderName = mat.shader.name + " 1";     // 所用shader,重写一份带剪裁功能的
     42                         Shader shader = Shader.Find(shaderName);
     43                         if (shader)
     44                         {
     45                             m_materials.Add(mat);
     46                             mat.shader = shader;
     47                         }
     48                         else
     49                         {
     50                             Debug.LogError("Shader not found, name: " + shaderName);
     51                         }
     52                     }
     53 
     54                     // mesh 的剪裁
     55                     var renders = GetComponentsInChildren<MeshRenderer>();
     56                     for (int i = 0, j = renders.Length; i < j; i++)
     57                     {
     58                         var ps = renders[i];
     59                         var mat = ps.material;
     60                         string shaderName = mat.shader.name + " 1";     // 所用shader,重写一份带剪裁功能的
     61                         Shader shader = Shader.Find(shaderName);
     62                         if (shader)
     63                         {
     64                             m_materials.Add(mat);
     65                             mat.shader = shader;
     66                         }
     67                         else
     68                         {
     69                             Debug.LogError("Shader not found, name: " + shaderName);
     70                         }
     71                     }
     72                 }
     73                 return m_materials;
     74             }
     75         }
     76 
     77         List<UIPanel> Panels
     78         {
     79             get
     80             {
     81                 if (m_uiPanels == null)
     82                 {
     83                     // 获取所有开启剪裁的 UIPanel
     84                     m_uiPanels = new List<UIPanel>();
     85                     UIPanel[] panels = GetComponentsInParent<UIPanel>();
     86                     for (int i = 0; i < panels.Length; i++)
     87                     {
     88                         UIPanel p = panels[i];
     89                         if (p && p.clipping == UIDrawCall.Clipping.SoftClip)
     90                         {
     91                             m_uiPanels.Add(p);
     92                         }
     93                     }
     94                 }
     95                 return m_uiPanels;
     96             }
     97         }
     98 
     99         #endregion
    100 
    101 
    102         void Update()
    103         {
    104             var mats = Materials;
    105             if (mats != null && mats.Count > 0)
    106             {
    107                 for (int i = 0; i < m_materials.Count; i++)
    108                 {
    109                     Vector4 area = CalcClipArea();
    110                     m_materials[i].SetVector("_Area", area);
    111                 }
    112             }
    113         }
    114 
    115         // 整合所有 UIPanel 的剪裁区域
    116         Vector4 CalcClipArea()
    117         {
    118             var panels = Panels;
    119             float x = float.MinValue, y = float.MinValue, z = float.MaxValue, w = float.MaxValue;
    120 
    121             // 求所有 UIPanel 剪裁区域的交集
    122             for (int i = 0; i < panels.Count; i++)
    123             {
    124                 UIPanel p = panels[i];
    125                 Vector4 area = CalcClipArea(p);
    126 
    127                 // 求交集啊
    128                 if (area.x > x)
    129                     x = area.x;
    130                 if (area.y > y)
    131                     y = area.y;
    132                 if (area.z < z)
    133                     z = area.z;
    134                 if (area.w < w)
    135                     w = area.w;
    136             }
    137 
    138             return new Vector4(x, y, z, w);
    139         }
    140 
    141         // 计算单个 UIPanel 的剪裁区域
    142         Vector4 CalcClipArea(UIPanel p)
    143         {
    144             float h = 2;
    145             float temp = h / ObjUIRoot.activeHeight;
    146             Vector3 offsetV3 = new Vector3()
    147             {
    148                 x = p.clipOffset.x * temp,
    149                 y = p.clipOffset.y * temp,
    150             };
    151             Vector3 worldPos = p.transform.position + offsetV3;
    152             Vector4 clipRegion = p.finalClipRegion;
    153             Vector4 nguiArea = new Vector4()
    154             {
    155                 x = -clipRegion.z / 2,
    156                 y = -clipRegion.w / 2,
    157                 z = clipRegion.z / 2,
    158                 w = clipRegion.w / 2
    159             };
    160 
    161             return new Vector4()
    162             {
    163                 x = worldPos.x + nguiArea.x * temp,
    164                 y = worldPos.y + nguiArea.y * temp,
    165                 z = worldPos.x + nguiArea.z * temp,
    166                 w = worldPos.y + nguiArea.w * temp
    167             };
    168         }
    169 
    170 
    171     }
    172 }
    EffectClip
  • 相关阅读:
    [windows]清除访问共享的用户和密码信息
    Java架构搜集
    jsp、freemarker、velocity对比
    Spring MVC 了解WebApplicationContext中特殊的bean类型
    Web.xml配置详解之context-param
    <context:annotation-config/> 的理解
    使用@Controller注解为什么要配置<mvc:annotation-driven />
    web.xml配置之<context-param>详解
    @WebServlet
    正向代理与反向代理
  • 原文地址:https://www.cnblogs.com/jietian331/p/10938837.html
Copyright © 2011-2022 走看看