어제 대표적인 2D 스켈레탈 애니메이션 프로그램인 Spine의 런타임 프로젝트에 풀리퀘를 넣었는데
성공적으로 머지가 되어 스파인 4.2버전에 제가 기여한 코드가 나오게 됩니다!
사실 처음부터 스파인 쪽 오픈소스 기여를 한번 해볼까? 라는 생각이 없었습니다…ㅋㅋ
어쩌다보니 운좋게 기여를 하게 되었는데 그 일대기를 작성해보고자 합니다.
얼마 전, 유니티 프로젝트에서 제게 한가지 의뢰(?)가 들어왔습니다.
바로 유니티에서 URP의 DOF가 스파인 캐릭터에게 제대로 먹히지 않는 문제였습니다.
무슨 문제점?
위 이미지는 URP 데모 프로젝트 위에 스파인 캐릭터를 올려놓은 상태입니다.
이 때 스파인은 URP 렌더링 환경에 재구성한 쉐이더를 통해 스파인의 렌더링을 구현하였습니다.
여기서 바로 DOF 효과를 적용하면 어떻게 될까요?
위 사진처럼 초점이 뒷배경에 있다고 가정해봅시다.
그렇다면 초첨보다 앞에 있는 오브젝트들은 흐려지는 효과를 받아야 정상입니다.
하지만 일부 환경에서는 위와 같이 흐린 효과가 정상적으로 처리되지 않습니다.
바로 이 문제가 제가 고쳐야 하는 숙제가 되었습니다. 과연 원인이 뭘까요?
깊이버퍼의 부재?
사실 문제가 되는 사진을 잘 보면 스파인 오브젝트만 깊이버퍼가 생략된 형태로 보여집니다.
그렇다면 깊이 버퍼 자체가 렌더링 되지 않은게 아닐까요?
하지만 프레임 디버거를 통해 확인한 깊이버퍼는 멀쩡했습니다…
사실 해당 쉐이더 상에서도 깊이에 대한 렌더링 파이프라인이 존재했습니다. 실제로 작동하는 것도 디버거를 통해 확인을 했죠.
그럼 뭐가 문제일까요…?
URP의 문제?
친구랑 함께 곰곰히 생각하면서 일반적인 URP 쉐이더와 스파인 쉐이더를 비교해보았습니다.
그리고 깊이 노멀 버퍼가 없다는 점을 발견했지만
‘과연 깊이 노멀의 부재가 DOF에 영향을 줄까?’ 의심하며 깊이 노멀도 생성해봤습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Pass
{
Name "DepthNormals"
Tags{"LightMode" = "DepthNormals"}
ZWrite On
Cull Off
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma vertex DepthNormalVertexSprite
#pragma fragment DepthNormalFragmentSprite
// -------------------------------------
// Material Keywords
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#define USE_URP
#define fixed4 half4
#define fixed3 half3
#define fixed half
#include "Include/Spine-Input-Sprite-URP.hlsl"
#include "Include/Spine-Sprite-DepthNormalsPass-URP.hlsl"
ENDHLSL
}
쉐이더는 다음과 같이 깊이 노멀도 렌더링 하도록 새로운 패스를 추가했습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#ifndef SPRITES_DEPTH_NORMALS_PASS_URP_INCLUDED
#define SPRITES_DEPTH_NORMALS_PASS_URP_INCLUDED
#include "Include/Spine-Sprite-Common-URP.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct AttributesSprite
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 vertexColor : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct VaryingsSprite
{
float4 positionCS : SV_POSITION;
float4 texcoordAndAlpha: TEXCOORD0;
float3 normalWS : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
VaryingsSprite DepthNormalVertexSprite(AttributesSprite input)
{
[...생략...]
}
half4 DepthNormalFragmentSprite(VaryingsSprite input) : SV_TARGET
{
fixed4 texureColor = tex2D(_MainTex, input.texcoordAndAlpha.xy);
clip(texureColor.a * input.texcoordAndAlpha.a - _Cutoff);
return half4(PackNormalOctRectEncode(TransformWorldToViewDir(input.normalWS, true)), 0.0, 0.0);
}
#endif
hlsl 단계의 픽셀 쉐이더 함수에서 노멀값을 반환하도록 해줍니다.
이렇게 구현한 결과…
놀랍게도 깊이 노멀 버퍼까지 렌더링하니 정상적으로 DOF가 먹혔습니다!
이렇게 나오다보니 제가 생각치도 못한 부분에 노멀값도 필요하구나 싶었고
관련해서 구글링을 해봤습니다.
알고보니 URP 12.0.0부터는 깊이 노멀 버퍼에 대해 많은 개선이 있었습니다.
(URP 12.0.0 업데이트 로그 링크)
깊이 노멀 버퍼 뿐만 아니라 DOF와 파티니 투영 등 사용되지 않는 깊이 관련 버퍼들을 생략했다는 로그도 있습니다.
따라서 URP를 최신버전으로 업데이트를 한다면 해당 문제는 발생하지 않고
정상적인 포스트 프로세싱을 적용할 수 있습니다.
스파인 프로젝트에 기여하게 된 계기
앞서 말했듯 URP를 업데이트 하기만해도 해결되는 문제라 굳이 해결하지 않아도 괜찮습니다.
하지만 종속성 문제가 있다면 말이 조금 달라집니다.
스파인 런타임에 돌아가는 URP 패키지의 종속된 버전은 12.0.0 아래 버전입니다.
이 종속된 URP 버전을 함부로 바꿀 수도 없기 때문에
제가 깊이 노멀 버퍼를 추가한 버전을 제안해보는 형식으로 PR을 넣게 되었습니다.
그 후 PR의 운명은…
성공적으로 머지가 되어서 스파인 4.2버전부터 제가 기여한 코드도 함께 배포됩니다! 머지되기 전 수정해야할 로직적인 부분이 있을 줄 알았는데 약간의 키워드 수정 후 바로 머지 되었습니다…!
아마 제가 제안한 수정 내용을 바로 받아준 것 같습니다.
지금까지 다른사람 PR 넣어서 기여하는건
목록 리스트에 뭔가 넣는거나 딱히 중요하지 않은 내용들 뿐이였는데
이렇게 중요 코드를 수정해서 기여하게 되는건 이번이 처음이라 뭔가 뿌듯하네요ㅎㅎ
앞으로도 프로젝트에 기여할 수 있는 기회가 많아졌으면 좋겠습니다!
최신 근황
2024년 5월부터 스파인 정식 버전이 4.2가 되면서 저도 정식 기여자가 되었습니다! 유니티 urp 스파인에 포스트 프로세싱 빵빵하게 넣고 많이 사용해주세요!