반응형


Custom Data module이란?

Unity Particle System(Shuriken)에서 사용되는 모듈로 Custom Data의 핵심은 쉐이더와 파티클시스템이 연동되는 Parameter를 만들고 다루는 것입니다.

 

기존에 파티클 시스템에 넣은 마테리얼의 색 데이터만 변경가능했지만 해당 기능을 사용하면 여러가지 데이터를 조작하여 더 다양한 파티클을 만들 수 있게 됩니다.

 

이번 포스팅은 Unity Paritcle System(Shuriken)에서 Custom Data를 다루는 방법에 대해 작성합니다.

 

 

 


샘플 이펙트(프로젝트) 소개

CatDarks_CustomDataSample.7z
0.21MB

이번 포스팅을 위해 만든 간단한 이펙트입니다.

Custom Data를 활용한 부분은 위 이펙트의 연기 부분에 Dissolve 효과를 구현하기 위해 사용했습니다.

 

 

 


쉐이더(Vertex&Fragment)에서 Custom Vertex Stream 세팅하기

파티클 시스템에서 Renderer모듈에 Custom Vertex Streams를 체크하면 Custom Data를 사용하겠다는 것을 뜻하며, 이는 쉐이더와 연동이 된다는 뜻입니다.

 

 

당장 유니티 기본 파티클 마테리얼을 설정하면 위 처럼 문제가 없게 표기되겠지만

 

Shader "Unlit/ParticleAlphaBlend"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
	}
	SubShader
	{
		Tags { "Queue" = "Transparent" "RenderType" = "Transparent" } //! Alpha Blended로 세팅
		Blend SrcAlpha OneMinusSrcAlpha		//! Alpha Blended로 세팅
		ZWrite off	//! ZBuffer 사용하지 않음(Alpha Blend 쉐이더에서는 보통 ZBuffer사용하지 않음)

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata	//! Mesh나 파티클시스템에서 입력되는 정보 구조체
			{
				float4 vertex : POSITION;	//! Vertex 좌표 데이터
				float2 uv : TEXCOORD0;		//! Mesh UV 정보
				fixed4 color : COLOR;		//! Particle System에서 받는 색상값(파티클 시스템에서 설정한 색이 해당 변수로 입력됨)
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;			//! 텍스처 UV 데이터
				float4 vertex : SV_POSITION;	//! Vertex 좌표 데이터
				fixed4 color : COLOR;			//! Particle System에서 받는 색상값
			};

			sampler2D _MainTex;
			float4 _MainTex_ST; //! 텍스처 Tiling Offset 정보
			
			v2f vert (appdata v)
			{	//! 이곳은 Vertex 쉐이더 함수 Fragment 쉐이더 함수로 정보 넘기는 과정
				v2f o;
				o.color = v.color;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{	//! 이곳은 Fragment쉐이더, 픽셀을 담당하는 부분

				fixed4 col = tex2D(_MainTex, i.uv);	//! 텍스처를 float4로 변환
		
				float4 fFinalColor;
				fFinalColor.rgb = col.rgb * i.color;		//! 텍스처와 Particle System Color 곱하기
				fFinalColor.a = col.r;						//! 이 쉐이더의 알파는 텍스처의 R채널을 사용함
				return fFinalColor;
			}
			ENDCG
		}
	}
}

위 처럼 제가 Alpha Blended쉐이더를 만들어서 적용하면 

 

이렇게 에러가 발생합니다, 에러 내용의 핵심은 쉐이더의 input 구조체와 매칭이 되지 않는다고 합니다.

input 구조체란 

 

이 부분을 뜻하며 해당 구조체를 통해 Mesh의 버텍스좌표, 노멀정보 등 다양한 정보를 쉐이더로 입력받을 수 있습니다.

 

위 처럼 파티클 시스템의 Custom Vertex Stream 세팅과 쉐이더 내부의 input 구조체가 맞지가 않아 에러가 나지만

 

위 처럼 쉐이더 코드와 파티클 시스템의 Custom Vertex Stream와 매칭시키면 에러가 발생하지 않습니다.

 

파티클시스템의 Custom Vertex Stream를 위 +, -통해 새로 추가, 제거가 가능합니다.

 

Custom Vertex Stream에 위 처럼 여러가지 추가가 가능합니다, 이번 포스팅에서는 CustomData를 사용하기 때문에  위 처럼 Custom메뉴에서 하나 선택해야 합니다.

이번 포스팅에서는 Customdata를 1개만 사용할 것이기 때문에 Custom1.x를 추가합니다.

Customdata는 총 8개의 값까지 사용 할 수 있습니다.

 

 

 

 


Custom Data를 통해 쉐이더 조작하기

Dissolve Smoke는 우측 텍스처를 활용해 좌측 이펙트를 만들었습니다.

 

Shader "Unlit/ParticleAlphaBlend_Dissolve"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
	}

		SubShader
	{
		Tags { "Queue" = "Transparent" "RenderType" = "Transparent" } //! Alpha Blended로 세팅
		Blend SrcAlpha OneMinusSrcAlpha //! Alpha Blended로 세팅
		ZWrite off //! ZBuffer 사용하지 않음(Alpha Blend 쉐이더에서는 보통 ZBuffer사용하지 않음)

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata //! Mesh나 파티클시스템에서 입력되는 정보 구조체
			{
				float4 vertex : POSITION; //! Vertex 좌표 데이터
				float3 uv : TEXCOORD0;	  //! Mesh UV 정보
				fixed4 color : COLOR;	  //! Particle System에서 받는 색상값(파티클 시스템에서 설정한 색이 해당 변수로 입력됨)
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;        //! 텍스처 UV 데이터
				fixed4 color : COLOR;		  //! Particle System에서 받는 색상값
				float4 vertex : SV_POSITION;  //! Vertex 좌표 데이터

				float CustomData1 : TEXCOORD1;	//! CustomData 받을 변수
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;	//! 텍스처 Tiling Offset 정보

			v2f vert(appdata v)
			{	//! 이곳은 Vertex 쉐이더 함수 Fragment 쉐이더 함수로 정보 넘기는 과정
				v2f o;
				o.color = v.color;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv.xy = TRANSFORM_TEX(v.uv.xy, _MainTex);

				o.CustomData1 = v.uv.z;		//! CustomData에서 받아온 .z값을 설정함
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{//! 이곳은 Fragment쉐이더, 픽셀을 담당하는 부분

				float fCustomData1 = i.CustomData1;	//! uv.z로 받은 CustomData를 변수를 만들어서 할당

				fixed4 col = tex2D(_MainTex, i.uv);

				float4 fFinalColor;
				fFinalColor.rgb = i.color.rgb;
				fFinalColor.a = ceil(col.r - fCustomData1) * i.color.a;	//! 간단한 Dissolve공식 * ParticleSystem의 알파색상 곱하기
				return fFinalColor;
			}
			ENDCG
		}
	}
}

위는 Smoke 쉐이더 코드입니다.

 

 

이전에 Vertex Stream부분을 보시면 추가한 Custom1.x뒤에 TEXCOORD0.z라고 명시된 것을 확인 할 수 있습니다.

이는 쉐이더의 input 값으로 TEXCOORD0.z 로 값이 들어온다는 뜻입니다.

 

float3 uv :TEXCOORD0는 원래 float2였습니다만 Custom Vertex Stream에서 값을 받기 위해 float3로 바꿨고

 

Fragment 쉐이더로 보낼 구조체에 임의의 float1를 만들고

 

float3로 받아온 TEXCOORD0 uv변수의 z값을 임의로 만든 float1 변수에 넣습니다.

이렇게 코드를 작성하면 Fragment쉐이더로 CustomData1변수를 통해 파티클시스템의 CustomData값을 전달 할 수 있습니다.

 

핵심은 CustomData로 받아온 값을 ceil(올림)함수로 Dissovle를 구현했습니다.

만약 CustomData가 없었으면 파티클의 어떤 값으로 Dissolve의 강도를 조절할 수 있을까요?

 

 

이전에 Vertex Stream에서 Custom1.x를 사용한다고 등록했으니 Custom Data모듈에서 Custom1 부분만 Vector 혹은 Color로 설정하여 활성화합니다.

 

저는 X값에 그래프를 통해 0~1로 값이 변하는 그래프를 입력했습니다.

파티클 시스템에서 설정한 Custom1의 x값은 쉐이더로 입력될 것입니다.

 

 

반응형

WRITTEN BY
CatDarkGame
Technical Artist dhwlgn12@gmail.com

,