NGUI里3D粒子混用出现的剪切问题

本文介绍了一种解决NGUI中3D粒子剪切不佳问题的方法。通过在Awake/Start阶段获取ScrollView的值,并将其传递给粒子着色器进行裁剪。提供了ParticleSystemClipper脚本和定制的粒子着色器,实现粒子效果的区域裁剪。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近期 开始对项目的维护,因为项目用的是NGUI ,而NGUI里面,对3D粒子 的剪切支持不是很好,因此上网查了一下,发现很多人都有 遇到这个问题,应该是个,也有很多人都解决了,思路就是在awake/start 的时候获取scrollview里面的值,然后传进粒子的sharder里面做裁剪就可以了。
这边 就转下了,测试过了直接用 原作者的,也是可以的,也可以在其基础上做优化。

下面是原文
https://www.cnblogs.com/jietian331/p/5075487.html

这个脚本加在 scrollview上

using System;
using UnityEngine;

[RequireComponent(typeof(UIPanel))]
public class ParticleSystemClipper : MonoBehaviour
{
    const string ShaderName = "Bleach/Particles Additive Area Clip";
    const float ClipInterval = 0.5f;

    UIPanel m_targetPanel;
    Shader m_shader;

    void Start()
    {
        // find panel
        m_targetPanel = GetComponent<UIPanel>();

        if (m_targetPanel == null)
            throw new ArgumentNullException("Cann't find the right UIPanel");
        if (m_targetPanel.clipping != UIDrawCall.Clipping.SoftClip)
            throw new InvalidOperationException("Don't need to clip");

        m_shader = Shader.Find(ShaderName);

        if (!IsInvoking("Clip"))
            InvokeRepeating("Clip", 0, ClipInterval);
    }

    Vector4 CalcClipArea()
    {
        var clipRegion = m_targetPanel.finalClipRegion;
        Vector4 nguiArea = new Vector4()
        {
            x = clipRegion.x - clipRegion.z / 2,
            y = clipRegion.y - clipRegion.w / 2,
            z = clipRegion.x + clipRegion.z / 2,
            w = clipRegion.y + clipRegion.w / 2
        };

        var uiRoot = LuaUtils.UIRoot.GetComponent<UIRoot>();
        var pos = m_targetPanel.transform.position - uiRoot.transform.position;
        float h = 2;
        float temp = h / uiRoot.manualHeight;

        return new Vector4()
        {
            x = pos.x + nguiArea.x * temp,
            y = pos.y + nguiArea.y * temp,
            z = pos.x + nguiArea.z * temp,
            w = pos.y + nguiArea.w * temp
        };
    }

    void Clip()
    {
        Vector4 clipArea = CalcClipArea();
        var particleSystems = this.GetComponentsInChildren<ParticleSystem>();

        for (int i = 0; i < particleSystems.Length; i++)
        {
            var ps = particleSystems[i];
            var mat = ps.renderer.material;

            if (mat.shader.name != ShaderName)
                mat.shader = m_shader;

            mat.SetVector("_Area", clipArea);
        }
    }

    void OnDestroy()
    {
        CancelInvoke("Clip");
    }
}

下面的shader给粒子

Shader "Bleach/Particles Additive Area Clip"
{
    Properties
    {
        _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
        _MainTex ("Particle Texture", 2D) = "white" {}
        _Area ("Area", Vector) = (0,0,1,1)
    }

    Category
    {
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
        Blend SrcAlpha One
        AlphaTest Greater .01
        ColorMask RGB
        Cull Off
        Lighting Off
        ZWrite Off
        Fog { Color (0,0,0,0) }
        
        SubShader 
        {
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma multi_compile_particles

                #include "UnityCG.cginc"

                sampler2D _MainTex;
                fixed4 _TintColor;
                float4 _Area;
                
                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.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
                    o.color = v.color;
                    o.worldPos = mul(_Object2World, v.vertex).xy;
                    return o;
                }

                fixed4 frag (v2f i) : SV_Target
                {
                    bool inArea = i.worldPos.x >= _Area.x && i.worldPos.x <= _Area.z && i.worldPos.y >= _Area.y && i.worldPos.y <= _Area.w;
                    return inArea? 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord) : fixed4(0,0,0,0);
                }
                ENDCG 
            }
        }    
    }
}

感谢原文作者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值