본문 바로가기
유니티 엔진

유니티 신기능 LPPV (라이트 프로브 프록시 볼륨 : Light Prove Proxy Volume)

by 대마왕J 2016. 9. 16.

유니티 신기능 LPPV(라이트 프로브 프록시 볼륨 : Light Prove Proxy Volume) 의 사용법에 대한 설명입니다. 

4.5 이상부터 적용되어 있죠. 


에또... 


뭐 일단 아래처럼 라이트 프로브를 Bake 했다고 치죠. 

바닥이야 당연히 Static이고 , Static 라이트 4개를 만들어 구웠습니다. 노릇노릇. 

Baked Lightmap을 만든거죠. 

겸해서 라이트 프로브도 같이 구워줬습니다. 





즉 이제 라이트는 사실상 필요 없는 상태. 

라이트를 지워도 라이트가 있는것처럼 구워져 있으니 말입니다. 





이제 여기에 동적 오브젝트인 캡슐을 하나 던져놓고 돌아다녀 보면 , 라이트 프로브의 영향을 받아서 마치 진짜 빛이 있는 것인양 색이 변합니다. 뭐 여기까지는 라이트 프로브의 매우 일반적인 사용법... GIF 잔상은 짜증나는군요... 






그런데... 만약 아래처럼 너어어어어얿은 동적 판떼기가 들어갔다면 어케 되는 걸까요? 














기존대로라면, 이렇게 피봇점에 해당되는 포인트 하나가 라이트 프로브를 적절히 받아서 오브젝트의 전체 색이 변하게 됩니다. 라이트 프로브는 아무래도 SH(구면조화함수) 라이트이기 때문에, 면의 노말 방향에 따라 대충 색이 연산되기 때문이기도 하고, 참조하는 라이트 프로브의 포인트가 한 부분인 이유가 가장 크지요. 
 그리고 이건 라이트 프로브의 분명한 한계였습니다. 










그래서 여기쯤 해서 라이트 프로브 프록시 볼륨을 써 보는 겁니다. 

저 너어어어얿은 판떼기에 


라이트 프록시 볼륨을 붙이고 




라이트 프로브 설정도 프록시 볼륨으로 바꿔줍니다. 




짜잔


라이트 프로브를 멀티로 받습니다! 



라이트 프로브를 숨기고, LPPV만 보이게 하면 이렇게 보입니다. 

오브젝트에 라이트 프로브 같은 것이 달려 있군요!!! 

이것이 이 오브젝트에 '멀티로 라이트 프로브를 받게 ' 해 주는 것입니다. 




Density 를 바꾸면 이 LPPV의 정밀도를 바꿀 수 있습니다. 

뭐...라이트 프로브의 특성상 저걸 올린다고 꼭 결과가 좋아지는건 아니긴 하지만 말입니다 ㅎㅎ 




자동으로 밀도를 바꿀 수 있는가 하면, 아래처럼 수동으로 갯수를 조절할 수도 있습니다. 





코너에 생기게 할거냐, 중심에 생기게 할거냐도 정할 수 있습니다. 







Refresh Mode는 뭐 말그대로이고.. 

바운딩 박스의 월드 / 로컬 모드는 어떤 물체의 서브 오브젝트가 LPPV를 받을때 적용하는 기능입니다.








그리고 추가로 재미있는건, 파티클도 LPPV가 적용된다는 거지요. 

사실 뭐 파티클에서 사용하려면 기존의 파티클 셰이더가 아닌, 라이트 프로브를 받는 파티클 셰이더를 따로 만들어 써야 한다는 문제가 있지만 말이죠. 여기서는 일단 스탠다드 셰이더를 써 보았습니다. 






그리고 파티클도 프록시 볼륨 옵션을 켜면 동일하게 작동하는 것을 볼 수 있습니다. 


아 이놈의GIF 잔상 적은 프로그램 없나요 







마지막으로, 애석하게도 이 기능은 꽤 무거운 기능이며... Shader Model4  이상에서야 동작하는 기능이라는 것이 아쉽네요 모바일에서 쓰기에는 꽤 애매할 듯 합니다. 뭐 나중엔 쓰겠죠?



그리고 LPPV를 받는 이펙트용 Additive 셰이더는 

아래처럼 짜면 됩니다. 

출처 : https://blogs.unity3d.com/kr/2016/02/03/light-probe-proxy-volume-5-4-feature-showcase/


핵심 부분은 ShadeSHPerPixel 함수이지용 

#include "UnityStandardUtils.cginc"

로 저 함수에 접근할 수 있게 됩니다. 

당연히 

#pragma target 3.0

이상인걸 잊으면 안되고 말이지요.

Multi나 알파 블렌딩 셰이더들도 블렌딩 옵션만 바꿔주면 얼마든지 짤 수 있으니 매우 쉽지요 :) 





Shader "Custom/ParticleAddLPPV" {
Properties
{
_MainTex ("Particle Texture"2D) = "white" {}
_TintColor ("Tint Color"Color) = (0.5,0.5,0.5,0.5)
}

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

SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_particles
#pragma multi_compile_fog
// Don’t forget to specify the target
#pragma target 3.0

#include "UnityCG.cginc"
// You have to include this header to have access to ShadeSHPerPixel
#include "UnityStandardUtils.cginc"

fixed4 _TintColor;
sampler2D _MainTex;

struct appdata_t
{
float4 vertex : POSITION;
float3 normal : NORMAL;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
};

struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_FOG_COORDS(1)
float3 worldPos : TEXCOORD2;
float3 worldNormal : TEXCOORD3;
};

float4 _MainTex_ST;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.color = v.color;
o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}

fixed4 frag (v2f i) : SV_Target
{
half3 currentAmbient = half3(000);
half3 ambient = ShadeSHPerPixel(i.worldNormal, currentAmbient, i.worldPos);
fixed4 col = _TintColor * i.color * tex2D(_MainTex, i.texcoord);
col.xyz += ambient;
UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0,0,0,0)); // fog towards black due to our blend mode
return col;
}
ENDCG
}
}
}
    FallBack off
}

반응형

댓글