본문 바로가기
유니티 엔진

유니티5의 Occlusion은 어떻게 따로 연산되는가?

by 대마왕J 2015. 6. 29.

Occlusion 연구

오즈라엘이 내 질문에는 답 안해주면서 나보고는 질문하길래 만들어본 답변입니다.

오즈라엘이 내 질문에는 답 안해주면서

오즈라엘이 내 질문에는 답 안해주면서

오즈라엘이 내 질문에는 답 안해주면서

오즈라엘이 내 질문에는 답 안해주면서

오즈라엘이 내 질문에는 답 안해주면서

 

 

 

 

일단 유니티 PBS 강의에 보면, "Albedo는 Diffuse에서 Occlusion을 뺀 것" 이라는 말이 나옵니다.

그리고 따로 Occlusion을 집어 넣지요.

 

그러면 Occlusion은 어떻게 가동되게 되어 있는지 봅시다.

그냥 Albedo * Occlusion으로 계산되면, 사실 뺄 이유가 없잖아요? 뭔가 다르게 계산되니까 빠진거겠죠.

 

그래서 일단 커스텀 라이팅으로 Standard Metallic Shader를 구현해 보았습니다.

 

 

 

저 공과 플렌 모두 커스텀 라이팅 구문으로 만든 메탈릭 파이프라인의 스텐다드 쉐이더입니다.

 

 

 

 

쉐이더 구문이야 대충 위와 같고...

 

 

 

프로퍼티스는 심플하게 Albedo와 Occlusion이 있습니다.

지금은 둘 다 White가 들어가 있는거구요.

 

 

그럼 이런 텍스쳐를 하나 넣어서...

 

이 텍스쳐를 Albedo 항목에, 그리고 Occlusion 항목에 넣어서 비교해 보도록 하겠습니다.

 

 

 

 

이것이 Albedo Pass에 텍스쳐를 넣은 상태. 음... 뭐 BRDF의 효과는 보이지만 말그대로 그냥 텍스쳐입니다.

 

 

 

이것이 Albedo가 아닌 Occlusion Pass에 넣은 상태. 음? 뭔가 다릅니다. 특히 저 공은 어두운걸 보세요.

 

 

 

다시 한 번 돌려서 보면 이렇습니다.

Occlusion은, Albedo와는 다르게 빛과 반응하고 있습니다.

 

즉, 차폐되었다 하더라도 그 차폐된 곳이 그림자 안이냐 밖이냐에 따라 색상이 다르다는 말이지요.

뭐 이건 이렇습니다. AO라고 하는 것은 결국 '차폐되어서 주변보다 어두우냐' 라는 결과물이기 때문에

밝은 곳 보다는 어두운 곳에서 나타나는 AO가 더 어두울 수 밖에 없는 것입니다.

그리고 그게 계산되고 있는 것이고요

 

 

이 부분을 코드에서 보면

inline void LightingJP_GI (
    SurfaceOutputStandard s,
    UnityGIInput data,
    inout UnityGI gi)
   {
    gi = UnityGlobalIllumination (data, s.Occlusion, s.Smoothness, s.Normal);
    }

 

이 두 부분이 핵심인데요. GI 연산에 s.Occlusion이 들어가 있는 것을 보실 수 있으실 겁니다.

 

그리고 이 구문이

 

 inline half4 LightingJP (SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
   {
    s.Normal = normalize(s.Normal);

    half oneMinusReflectivity;
    half3 specColor;
    s.Albedo = DiffuseAndSpecularFromMetallic (s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);

    // shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
    // this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
    half outputAlpha;
    s.Albedo = PreMultiplyAlpha (s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);

 half4 c = half4(0,0,0,1);
 c = BRDFjp_Unity_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
   
    c.rgb += UNITY_BRDF_GI (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, s.Occlusion, gi);
   
    c.a = outputAlpha;
    return c;
   }

 

이렇게 사용되지요.

 

뭐 일단 지금까지는 GI 구문에 들어간다까지 분석은 되어 있는데,

이 부분에서 다음에 까 볼 부분은

 

LightingJP_GI 부분입니다.

 

유니티 5의 커스텀 라이트는 이전 커스텀 라이트와 같이

 

 half4 LightingJP (SurfaceOutputStandard s, half3 viewDir, UnityGI gi)

 

특정 라이트 이름 앞에 Lighting이란 구문을 붙여서 라이트 함수로 인식하게 하는데요,

여기에 5에서는 추가로 생긴 항목이 있습니다.

 

 void LightingJP_GI ( SurfaceOutputStandard s, UnityGIInput data, inout UnityGI gi)

 {
    gi = UnityGlobalIllumination (data, s.Occlusion, s.Smoothness, s.Normal);
   }
   이 함수인데요.

이 함수 부분을 연구하는게 Occlusion의 핵심이라 보여집니다.

이것의 내부 탐험은 바쁘니 다음 기회에...

반응형

댓글