본문 바로가기
Shader

파티클 커스텀 버텍스 스트림 : Particle Custom Vertex Streams

by 대마왕J 2017. 11. 29.

Particle System vertex streams and Standard Shader support

If you are comfortable writing your own Shaders, use this addition to the Renderer Module to configure your Particle Systems to pass a wider range of data into your custom Shaders.

만약에 커스텀 셰이더 만드는데 익숙하시다면, 이 렌더 모듈을 이용해서 파티클 시스템이 당신의 커스텀 셰이더에 데이터를 넣을 수 있게 해줄겁니당



There are a number of built-in data streams to choose from, such as velocity, size and center position. Aside from the ability to create powerful custom Shaders, these streams allow a number of more general benefits:

여기는 선택할 수 있는 많은 빌트인 데이터 스트림이 있습니다. 마치 속도나 사이즈, 센터 포지션 같은 말이죠 
이러한 강력한 커스텀 셰이더를 만들 수 있는 것 이외에, 이런 더 일반적인 이점들을 얻을 수 있게 됩니다. 

  • Use the Tangent stream to support normal mapped particles.
  • You can add the Tangent UV2 and AnimBlend streams to use the Standard Shader on particles.
  • To easily perform linear texture blending of flipbooks, add the UV2 and AnimBlend streams, and attach the Particles/Anim Alpha Blended Shader (see example screenshot below to see how to set this up).
    노말맵 파티클을 위해 탄젠트 스트림을 지원하게 할 수 있습니다. 
    탄젠트 UV2 와 에니메블렌드 스트림을 파티클에 있는 스텐다드 셰이더에 추가할 수 있씁니다. 
  • 플립북 리니어 블렌딩을 쉽게 만들려면 , UV2와 애니메블렌딩 스트림과, 그리고 파티클/애니메 알파 블렌드를 붙이십시오.  (아래에 어떻게 셋업하는지 보세요) 


There are also two completely custom per-particle data streams
여기에는 또한 두 개의 완전한 커스텀 퍼 - 파티클 데이터 스트림이 있슴다.
 (ParticleSystemVertexStreams.Custom1 and ParticleSystemVertexStreams.Custom2), which can be populated from script. Call SetCustomParticleData and GetCustomParticleData with your array of data to use them. There are two ways of using this:
(파티클시스템버텍스스트림.커스텀1 과파티클시스템버텍스스트림.커스텀1) 이건 스크립트에서 채울 수 있습니다. 셋커스텀파티클데이터와 겟파티클을 당신의 데이터 배열에 불러 쓸 수 있습니다. 이것은 두 개의 사용법이 있습니다. 


  • To drive custom behavior in scripts by attaching your own data to particles; for example, attaching a “health” value to each particle.
  • To pass this data into a Shader by adding one of the two custom streams, in the same way you would send any other stream to your Shader (see ParticleSystemRenderer.EnableVertexStreams). To elaborate on the first example, maybe your custom health attribute could now also drive some kind of visual effect, as well as driving script-based game logic.
    자신의 데이터를 입자에 첨부하여 스크립트에서 사용자 지정 동작을 수행하려면, 예를 들어 각 입자에 "health"값을 첨부 한다면.
    두 개의 사용자 정의 스트림 중 하나를 추가하여 이 데이터를 셰이더에 전달하려면 동일한 방식으로 다른 스트림을 셰이더에 보냅니다 (ParticleSystemRenderer.EnableVertexStreams 참조).
    첫 번째 예를 보자면,
     사용자 지정 health 속성이 이제 스크립트 기반 게임 로직을 제어할뿐만 아니라 시각적 효과를 유발할 수도 있습니다.


When adding vertex streams, Unity will provide you with some information in brackets, next to each item, to help you read the correct data in your shader:
버텍스 스트림을 추가할 때, 유니티는 괄호로 묶인 어떤 정보를 제공합니다. 각각의 아이템 뒤에. 쉐이더에서 알맞은 데이터를 읽을 수 있도록.  


Each item in brackets corresponds to a Vertex Shader input, which you should specify in your Shader. Here is the correct input structure for this configuration.
괄호로 묶인 각 항목은 버텍스 셰이더 인풋을 의미하며, 각각은 당신의 셰이더에서 정의되어야 합니다. 여기 이 환경을 위해 올바른 인풋 구조가 있습니다. 

            struct appdata_t {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                fixed4 color : COLOR;
                float4 texcoords : TEXCOORD0;
                float texcoordBlend : TEXCOORD1;
            };

Notice that both UV and UV2 are passed in different parts of TEXCOORD0, so we use a single declaration for both. To access each one in your shader, you would use the xy and zw swizzles. This allows you to pack your vertex data efficiently.

Here is an example of an animated flip-book Shader. It uses the default inputs (PositionNormalColorUV), but also uses two additional streams for the second UV stream (UV2) and the flip-book frame information (AnimBlend).

: UV와 UV2는  TEXCOORD0의 다른 파트에서 전달되므로, 그래서  두 가지를 위해 우리는 하나의 선언을 사용했습니다. 셰이더의 각 항목에 액세스하려면 xy 및 zw swizzle을 사용합니다. 이를 통해 정점 데이터를 효율적으로 패킹 할 수 있습니다.

다음은 애니메이션 플립 북 셰이더의 예입니다. 이것은 기본 입력 (position, normal, color, UV)을 사용합니다. 그렇지만 두 번째 UV 스트림 (UV2)과 플립 북 프레임 정보 (AnimBlend) 을 위해  두 개의 추가 스트림을 사용합니다.

Shader "Particles/Anim Alpha Blended" {
Properties {
    _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
    _MainTex ("Particle Texture", 2D) = "white" {}
    _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
}

Category {
    Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
    Blend SrcAlpha OneMinusSrcAlpha
    ColorMask RGB
    Cull Off Lighting Off ZWrite Off

    SubShader {
        Pass {
        
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0
            #pragma multi_compile_particles
            #pragma multi_compile_fog
            
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            fixed4 _TintColor;
            
            struct appdata_t {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
                float4 texcoords : TEXCOORD0;
                float texcoordBlend : TEXCOORD1;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
                float2 texcoord2 : TEXCOORD1;
                fixed blend : TEXCOORD2;
                UNITY_FOG_COORDS(3)
                #ifdef SOFTPARTICLES_ON
                float4 projPos : TEXCOORD4;
                #endif
                UNITY_VERTEX_OUTPUT_STEREO
            };
            
            float4 _MainTex_ST;

            v2f vert (appdata_t v)
            {
                v2f o;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); 
                o.vertex = UnityObjectToClipPos(v.vertex);
                #ifdef SOFTPARTICLES_ON
                o.projPos = ComputeScreenPos (o.vertex);
                COMPUTE_EYEDEPTH(o.projPos.z);
                #endif
                o.color = v.color * _TintColor;
                o.texcoord = TRANSFORM_TEX(v.texcoords.xy,_MainTex);
                o.texcoord2 = TRANSFORM_TEX(v.texcoords.zw,_MainTex);
                o.blend = v.texcoordBlend;
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            sampler2D_float _CameraDepthTexture;
            float _InvFade;
            
            fixed4 frag (v2f i) : SV_Target
            {
                #ifdef SOFTPARTICLES_ON
                float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
                float partZ = i.projPos.z;
                float fade = saturate (_InvFade * (sceneZ-partZ));
                i.color.a *= fade;
                #endif
                
                fixed4 colA = tex2D(_MainTex, i.texcoord);
                fixed4 colB = tex2D(_MainTex, i.texcoord2);
                fixed4 col = 2.0f * i.color * lerp(colA, colB, i.blend);
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG 
        }
    }   
}
}


It’s also possible to use Surface Shaders with this system, although there are some extra things to be aware of:
이것은 또한 서피스 셰이더에서도 사용할 수 있습니다. 뭐 조금 추가적 작업을 할 부분은 있지만요 : 

  • The input structure to your surface function is not the same as the input structure to the vertex Shader. You need to provide your own vertex Shader input structure. See below for an example, where it is called appdata_particles.
  • When surface Shaders are built, there is automatic handling of variables whose names begin with certain tokens. The most notable one is uv. To prevent the automatic handling from causing problems here, be sure to give your UV inputs different names (for example, “texcoord”).
    서피스 셰이더의 인풋 구조체는 버텍스 셰이더의 구조체와 다릅니다. 
    그래서 당신의 커스텀 버텍스 인풋 구조체를 제공해야 하죠. 아래 예를 보시면 appdata_particle 이라고 구조체가 보입니다. 
    서피스 셰이더가 빌트되면, 지정된 토근으로 시작되는 이름에 자동 처리가 행해지는 경우가 있습니다. 
    뭐 자주 쓰이는건 uv 뭐 이런거요. (주: uv_MainTex를 의미합니다) 
    이 자동처리 문제를 피하려면, 그래서 다른 이름으로 써야 합니다. (예를 들면 texcoord 같은거요)

Here is the same functionality as the first example, but in a Surface Shader:
여기 위의 셰이더와 같은 걸 서피스 셰이더로 짠 예제가 있습니다. 

Shader "Particles/Anim Alpha Blend Surface" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Tags {"Queue"="Transparent" "RenderType"="Transparent"}
        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite off
        LOD 200
        
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard alpha vertex:vert

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

         struct appdata_particles {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
            float4 color : COLOR;
            float4 texcoords : TEXCOORD0;
            float texcoordBlend : TEXCOORD1;
            };


        struct Input {
            float2 uv_MainTex;
            float2 texcoord1;
            float blend;
            float4 color;
        };


        void vert(inout appdata_particles v, out Input o) {
            UNITY_INITIALIZE_OUTPUT(Input,o);
            o.uv_MainTex = v.texcoords.xy;
            o.texcoord1 = v.texcoords.zw;
            o.blend = v.texcoordBlend;
            o.color = v.color;
          }


        half _Glossiness;
        half _Metallic;
        fixed4 _Color;


        void surf (Input IN, inout SurfaceOutputStandard o) {
            fixed4 colA = tex2D(_MainTex, IN.uv_MainTex);
            fixed4 colB = tex2D(_MainTex, IN.texcoord1);
            fixed4 c = 2.0f * IN.color * lerp(colA, colB, IN.blend) * _Color;
                 
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}


반응형

댓글