首页 > 解决方案 > Unity - 粒子效果:如何使着色器在所需的时间播放

问题描述

最近我一直在尝试 VFX 的运气。我遇到了我非常喜欢的效果,滚动着色器。

我以这篇文章为基础并设法与它的创建者取得了联系,所以向他大喊大叫,他引导我朝着正确的方向前进以达到预期的效果。

后来,我意识到我有一些错误,如果有人可以帮助我,我将不胜感激。

效果只是纹理在某个网格中滚动,并带有 alpha 纹理。

第一个问题:效果没有颜色......它旋转并且alpha蒙版固定但颜色不显示。

第二个问题:我正在使用这个着色器来完成效果的特定部分,使用粒子系统。我使用了 Color Over Lifetime 选项,但它仍然会在整个效果开始后立即激活。使用“启动延迟”选项,它可以工作。

在某种程度上,这个问题是通过这种方式解决的,尽管我想知道我怎么能慢慢地看起来像生命中的颜色。

最后的问题更像是一个奖金。

有没有办法让网格在着色器效果旁边从下到上慢慢出现?

当前着色器代码

Shader "Custom/ScrollingShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _AlphaMaskTex ("AlphaMask", 2D) = "white" {}
        _ScrollSpd ("Scroll Speeds", vector) = (-5, -20, 0, 0)
        [HDR] _Color ("Color", Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
        // No culling or depth
        Cull back ZWrite Off ZTest Always Blend SrcAlpha OneMinusSrcAlpha


        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float2 alphauv : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            float4 _MainTex_ST;
            float4 _AlphaMaskTex_ST;
            float4 _ScrollSpd;

            v2f vert (appdata v)
            {                
                /* v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex).xy + frac(_Time.y * float2(_ScrollSpd.x, _ScrollSpd.y));
                return o; */

                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex).xy + frac(_Time.y * float2(_ScrollSpd.x, _ScrollSpd.y));

                o.alphauv = TRANSFORM_TEX(v.uv, _AlphaMaskTex).xy;

                return o;
            }

            sampler2D _MainTex;
            sampler2D _AlphaMaskTex;
            float4 _Color;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                fixed4 colA = tex2D(_AlphaMaskTex, i.alphauv);

                col = tex2D(_MainTex, i.uv) * _Color;

                col.a = tex2D(_AlphaMaskTex, i.uv).r;

                col = tex2D(_MainTex, i.uv) * tex2D(_AlphaMaskTex, i.alphauv).r;

                return col;
            }
            ENDCG
        }
    }
}

与应用材料一起使用的网格:

在此处输入图像描述

在此先感谢您,如果您有不明白的地方,请把它带给我,以便我更好地解释。

非常感谢!!

标签: c#unity3dshaderparticle-system

解决方案


关于你的第一个问题:在第 68 行

col = tex2D(_MainTex, i.uv) * _Color;

您正在尝试通过将纹理与颜色相乘来设置颜色。在第 72 行

col = tex2D(_MainTex, i.uv) * tex2D(_AlphaMaskTex, i.alphauv).r;

您只是在覆盖现有的颜色值。因此,只要您的基础纹理是灰度的,效果中就不会有颜色。我猜你想要这样的东西:

col = tex2D(_MainTex, i.uv) * _Color;
//col.a = tex2D(_AlphaMaskTex, i.alphauv).r; //<-- Edit1
col.a = tex2D(_AlphaMaskTex, i.alphauv).r * _Color.a; //<-- Edit2 fade in

关于你的第二个问题:我不完全理解你想要达到的目标。我也不是粒子系统的专家。但是,只要您正在绘制粒子,着色器就会被执行,并且通过引用 _Time 它将被动画化。生命周期内的颜色可用作着色器的输入。所以你可以用它作为一个值来改变你的着色器行为。您可以做各种有趣的事情,例如,如果您想在一段时间后开始为粒子设置动画,您可以设置颜色在生命周期内从 0 alpha 混合到 1 alpha,然后检查着色器中的 alpha 值,如果它更大超过 0.5 你开始为你的 uv 设置动画。生命周期中的颜色功能似乎是将数据传递给着色器的好方法。

不幸的是,我并不真正了解您要达到的目标,因此我无法提供更多帮助。也许你可以详细说明你的第二个问题?

关于你的第三个问题:

这是完全可能的。在片段着色器中,您可以将 uvs 视为从下到上和从左到右的渐变。因此,如果您使用 uv.y 并将其与您的 alpha 颜色相乘,您将混合您的粒子。现在,您可以使用从颜色随时间变化函数中获得的颜色对其进行动画处理。我还没有尝试过,但你可以这样做:

col.a = clamp(col.a * i.uv.y + _Color.a, 0.0f, 1.0f); //<- Edit

就像我说过的,我没有对此进行测试,您最喜欢为此添加一些偏移量。如果您正在苦苦挣扎,我可以看看是否可以给您一个运行示例。


推荐阅读