반응형

개요

언리얼 엔진 디렉토리 내부에 있는 VertexAnimationTool.ms는 3dsMax에서 VAT 리소스를 생성하는 스크립트입니다.

해당 리소스는 언리얼 엔진에서 바로 사용 가능하지만, 유니티 엔진에는 축(Axis)가 일치하지 않는 이유로 사용 할 수 없습니다.

이 포스팅은 VertexAnimationTool.ms 스크립트를 유니티에서 사용할 수 있도록 수정하는 방법과 유니티 엔진 쉐이더 활용 예시를 작성합니다.

(맥스 스크립트 파일은 언리얼 설치 후 직접 획득합니다.)

 

VertexAnimationTool.ms 수정 내용

축 변경 외에 수정 사항 없습니다.

스크립트 외에 중요한 부분은 3dsMax에서 Import & Export 과정에서 Unit 기준을 Meter로 세팅해야합니다.

-- 기존 코드
oldnormal=((((normalize (getTheVertexNormal currentMorphTarget j))*[1.0,-1.0,1.0])+1.0)*0.5)*255.0
append CurrentMorphTargetNormalArray oldnormal
originalVertPos=originalMeshVertPositions[j]
currentModelVertPos=getVertPos currentMorphTarget j
if (captureAbsolutePositions.checked) 
then (
	currentOffset=currentModelVertPos
)
else (
	currentOffset=(currentModelVertPos-originalVertPos)
)
currentOffset=[currentOffset[1],-1.0*currentOffset[2],currentOffset[3]]
currentOffset*=255.0
append currentMorphVertexOffsetArray currentOffset


-- 변경 코드
oldnormal=((((normalize (getTheVertexNormal currentMorphTarget j))*[1.0,1.0,-1.0])+1.0)*0.5)*255.0
append CurrentMorphTargetNormalArray oldnormal
originalVertPos=originalMeshVertPositions[j]
currentModelVertPos=getVertPos currentMorphTarget j
if (captureAbsolutePositions.checked) 
then (
	currentOffset=currentModelVertPos
)
else (
	currentOffset=(currentModelVertPos-originalVertPos)
)
currentOffset=[currentOffset[1], currentOffset[3], -1.0*currentOffset[2]]
currentOffset*=255.0
append currentMorphVertexOffsetArray currentOffset

 

 

유니티 쉐이더 사용 예시

샘플링 코드는 언리얼 엔진 MS_VertexAnimationTools_NorphTargets 노드의 핵심 로직을 코드로 변환했습니다.

            float3 ConvertAxis(float3 v)
            {
               return v.xzy * float3(-1, -1, 1);
            }

			// Ref : UE MS_VertexAnimationTools_NorphTargets
            void GetVATData(float2 uv, out float3 positionOSOffset, out normalOS normalOSOffset)
            {
                float animFrameTotal = _AnimFrameTotal;
                float animFrameCurrent = lerp(0.0f, animTotalFrame, _AnimFrameAmount);

                float ceil_1 = 1.0f / ceil(animFrameTotal);
                float ceil_2 = ceil(animFrameCurrent);
                float mult_1 = ceil_1 * 0.5f;
                float mult_2 = ceil_2 * ceil_1;
                float add_1 = mult_1 + mult_2;
                float2 uv_VAT = float2(uv.x, 1.0f - add_1);
 
                float4 pos_Offset = SAMPLE_TEXTURE2D_LOD(_PositionVAT, sampler_PositionVAT, uv_VAT, 0);
                float4 nor_Offset = SAMPLE_TEXTURE2D_LOD(_NormalVAT, sampler_PositionVAT, uv_VAT, 0); 

                positionOSOffset = ConvertAxis(pos_Offset.xyz);
                normalOSOffset = ConvertAxis(nor_Offset.xyz);
            }
 
            Varyings vert(Attributes input)
            {
                Varyings output = (Varyings)0;
 
                float3 positionOSOffset = 0.0f;
                float3 normalOSOffset = 0.0f;
                GetVATData(input.uv_1, positionOSOffset, normalOSOffset);

                float3 positionOS = input.positionOS.xyz + positionOSOffset;
                float3 normalOS = normalOSOffset;
                output.positionCS = TransformObjectToHClip(positionOS);
                output.normalWS = TransformObjectToWorldNormal(normalOS);
                output.uv = input.uv_0;
                return output;
            }

 

 

 

 

 

반응형

WRITTEN BY
CatDarkGame
Technical Artist dhwlgn12@gmail.com

,