Version: Unity 6.0 (6000.0)
언어 : 한국어
커스텀 셰이더의 파티클 시스템 GPU 인스턴싱 예시
빌트인 렌더 파이프라인의 Autodesk Interactive 셰이더

커스텀 버텍스 스트림을 사용하는 파티클 시스템 GPU 인스턴싱 예시

위 예시에서는 파티클에 대한 기본 버텍스 스트림 설정을 사용합니다. 여기에는 위치, 노멀, 컬러, UV 하나가 포함됩니다. 그러나 커스텀 버텍스 스트림을 사용하면 속도, 회전, 크기와 같은 다른 데이터를 셰이더로 전송할 수 있습니다.

다음 예제에서 셰이더는 특수 효과를 표시하도록 디자인되어 빠른 파티클은 밝게 나타나고 느린 파티클은 어둡게 나타납니다. 속도 버텍스 스트림을 사용하여 속도에 따라 파티클을 밝게 만드는 코드가 추가되어 있습니다. 또한 이 셰이더는 효과가 텍스처 시트 애니메이션을 사용하지 않는다고 가정하기 때문에 커스텀 스트림 구조체에서 생략됩니다.

완전한 셰이더는 다음과 같습니다.

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

그런 다음, 또 다른 줄이 인스턴싱 시스템에 애니메이션 프레임 스트림이 이 셰이더에 필요하지 않다고 알립니다. 이는 이 예제의 효과가 텍스처 시트 애니메이션을 사용하지 않기 때문입니다.

            #define UNITY_PARTICLE_INSTANCE_DATA_NO_ANIM_FRAME

세 번째로, 커스텀 스트림 데이터용 구조체가 선언됩니다.

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

이러한 오버라이드는 모두 UnityStandardParticleInstancing.cginc가 포함되기 전에 이루어지므로, 셰이더가 해당 정의에 고유 기본값을 사용하지 않습니다.

구조체를 작성할 때 변수는 파티클 시스템 렌더러 모듈의 인스펙터에 나열된 버텍스 스트림과 일치해야 합니다. 즉, 렌더러 모듈 UI에서 사용할 스트림을 선택하고 커스텀 스트림 데이터 구조체의 변수 정의에 동일한 순서로 추가하여 일치하도록 해야 합니다.

렌더러 모듈 UI에 표시된 커스텀 버텍스 스트림으로, 일부 인스턴스 스트림과 비인스턴스 스트림을 보여줌
렌더러 모듈 UI에 표시된 커스텀 버텍스 스트림으로, 일부 인스턴스 스트림과 비인스턴스 스트림을 보여줌

첫 번째 항목(위치)은 필수이므로 제거할 수 없습니다. 다른 항목들은 더하기 및 빼기 버튼으로 자유롭게 추가/제거하여 버텍스 스트림 데이터를 커스터마이즈할 수 있습니다.

뒤에 INSTANCED 가 붙은 목록 항목에는 인스턴스 데이터가 들어 있기 때문에 파티클 인스턴스 데이터 구조체에 반드시 포함해야 합니다. INSTANCED 단어 바로 뒤에 붙어 있는 숫자(예: INSTANCED0 의 0과, INSTANCED1 의 1)는 첫 ‘transform’ 변수 이후 변수가 구조체에 나타나는 순서를 뜻합니다. 뒤에 붙은 문자(.x, .xy, .xyz 또는 .xyzw)는 변수의 유형을 표시하며, 셰이더 코드에서 float, float2, float3 및 float4 변수 유형에 매핑됩니다.

목록에 나타나는 다른 버텍스 스트림 데이터는 생략할 수 있지만, 이 경우 파티클 인스턴스 데이터 구조체에서 뒤에 INSTANCED 단어가 붙어 있지 않습니다. 이는 셰이더에서 처리하는 인스턴스 데이터가 아니기 때문입니다. 이러한 데이터는 소스 메시(예: UV), 노멀 및 탄젠트에 속합니다.

예제를 완성하기 위한 마지막 단계는 버텍스 셰이더 내 파티클 컬러에 속도를 적용하는 것입니다.

#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 인스턴싱 예시
빌트인 렌더 파이프라인의 Autodesk Interactive 셰이더