版本:Unity 6 (6000.0)
语言:英语
自定义着色器中粒子系统 GPU 实例化的示例
将 C# Job 系统集成到粒子系统工作流程中

使用自定义顶点流进行粒子系统 GPU 实例化的示例

以上示例仅使用粒子的默认顶点流设置。这包括位置、法线、颜色和一个 UV。但是,通过使用自定义顶点流,您可以将其他数据发送到着色器在 GPU 上运行的程序。 更多信息
参见 术语表
,例如速度、旋转和大小。

在下一个示例中,着色器被设计为显示特殊效果,使速度更快的粒子看起来更亮,而速度更慢的粒子看起来更暗。有一些额外的代码使用速度顶点流根据粒子的速度来使它们变亮。此外,由于此着色器假设该效果不会使用纹理表动画,因此它从自定义流结构体中省略了。

以下是完整的着色器

Shader "Instanced/ParticleMeshesCustomStreams"
{
    Properties
    {
        _MainTex("Albedo", 2D) = "white" {}
    }
    SubShader
    {
        Tags{ "RenderType" = "Opaque" }
        LOD 100
        Pass
        {
            CGPROGRAM
#pragma exclude_renderers gles
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_instancing
            #pragma instancing_options procedural:vertInstancingSetup
            #define UNITY_PARTICLE_INSTANCE_DATA MyParticleInstanceData
            #define UNITY_PARTICLE_INSTANCE_DATA_NO_ANIM_FRAME
            struct MyParticleInstanceData
            {
                float3x4 transform;
                uint color;
                float speed;
            };
            #include "UnityCG.cginc"
            #include "UnityStandardParticleInstancing.cginc"
            struct appdata
            {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };
            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
            };
            sampler2D _MainTex;
            float4 _MainTex_ST;
            v2f vert(appdata v)
            {
                v2f o;
                UNITY_SETUP_INSTANCE_ID(v);
                o.color = v.color;
                o.texcoord = v.texcoord;
                vertInstancingColor(o.color);
                vertInstancingUVs(v.texcoord, o.texcoord);
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
                UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
                o.color.rgb += data.speed;
#endif
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                half4 albedo = tex2D(_MainTex, i.texcoord);
                return i.color * albedo;
            }
            ENDCG
        }
    }
}

着色器包含 UnityStandardParticleInstancing.cginc,其中包含当未使用自定义顶点流时的默认实例化数据布局。因此,在使用自定义流时,您必须覆盖该头文件中定义的一些默认值。这些覆盖必须放在包含之前。上面的示例设置了以下自定义覆盖

首先,有一行告诉 Unity 使用名为“MyParticleInstanceData”的自定义结构体来表示自定义流数据,使用 UNITY_PARTICLE_INSTANCE_DATA 宏

            #define UNITY_PARTICLE_INSTANCE_DATA MyParticleInstanceData

接下来,另一个定义告诉实例化系统在此着色器中不需要 Anim Frame 流,因为此示例中的效果并非用于纹理表动画。

            #define UNITY_PARTICLE_INSTANCE_DATA_NO_ANIM_FRAME

第三,声明自定义流数据的结构体

            struct MyParticleInstanceData
            {
                float3x4 transform;
                uint color;
                float speed;
            };

这些覆盖都位于包含 UnityStandardParticleInstancing.cginc 之前,因此着色器不会对这些定义使用自己的默认值。

在编写结构体时,变量必须与InspectorUnity 窗口,显示有关当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。 更多信息
参见 术语表
粒子系统一个组件,通过在场景中生成和动画大量小的 2D 图像来模拟液体、云和火焰等流体实体。 更多信息
参见 术语表
渲染器模块中列出的顶点流匹配。这意味着您必须在渲染器模块UI(用户界面) 允许用户与您的应用程序交互。Unity 目前支持三个 UI 系统。 更多信息
参见 术语表
中选择要使用的流,并将它们添加到自定义流数据结构体中的变量定义中,并保持相同的顺序,使其匹配

The custom vertex streams shown in the Renderer module UI, showing some instanced and some non-instanced streams
渲染器模块 UI 中显示的自定义顶点流,显示了一些实例化流和一些非实例化流

第一个项目(位置)是必需的,因此您无法删除它。您可以使用加号和减号按钮自由添加/删除其他条目,以自定义您的顶点流数据。

列表中后面跟着INSTANCED的条目包含实例数据,因此您必须将它们包含在您的粒子实例数据结构体中。直接附加到单词INSTANCED后面的数字(例如INSTANCED0中的零和INSTANCED1中的 1)表示变量必须出现在结构体中的顺序,初始“transform”变量之后。尾随字母(.x .xy .xyz 或 .xyzw)表示变量的类型,并映射到着色器代码中的 float、float2、float3 和 float4 变量类型。

您可以从粒子实例数据结构体中省略列表中出现的任何其他顶点流数据,但没有 在后面跟着单词INSTANCED,因为它不是要由着色器处理的实例化数据。这些数据属于源网格Unity 的主要图形基元。网格构成了您 3D 世界的很大一部分。Unity 支持三角形或四边形多边形网格。NURBS、NURMS、细分曲面必须转换为多边形。 更多信息
参见 术语表
,例如 UV、法线和切线。

完成示例的最后一步是在顶点着色器在渲染 3D 模型时,对 3D 模型的每个顶点运行的程序。 更多信息
参见 术语表
内部将速度应用到粒子颜色。

#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
                UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
                o.color.rgb += data.speed;
#endif

您必须将所有实例化代码包装在对 UNITY_PARTICLE_INSTANCING_ENABLED 的检查中,以便它可以在未使用实例化时编译。

此时,如果您想将数据传递到片段着色器,则可以像使用其他着色器数据一样将数据写入 v2f 结构体。

此示例描述了如何修改自定义着色器以用于自定义顶点流,但您可以将完全相同的方法应用于表面着色器一种简化的方式,用于为内置渲染管线编写着色器。 更多信息
参见 术语表
以实现相同的功能。

自定义着色器中粒子系统 GPU 实例化的示例
将 C# Job 系统集成到粒子系统工作流程中