Unity/Rendering&Shader

[RENDERING] Planar Reflection, Render

김성인 2023. 10. 27. 23:02

[RENDERING] Planar Reflection, Render

 

정보 전달을 위한 글이 아닌, 개인적으로 잊지 않기 위해서 기록하였습니다.


1부 - 플레이너 리플렉션 기본

 1. 글의 기록 목적

 2. 사용 방법

 3. 구현 구조 

 4. 성능을 위한 기본 규칙

 

2부 - 플레이너 리플렉션을 사용하며 얻을 수 있는 부산물

 1. 플레이너 리플렉션과 렌더러

 2. RenderDoc에서...

 3. 컬링 기능으로 카메라 비활성화

 

3부 - 마치며...


1부 - 플레이너 리플렉션 기본


글의 기록 목적


 컴퓨터 그래픽스에서 반사 관련된 기술이 몇 가지 있는데, 그중 게임을 개발하며 흔하게 접하는 것이 리플렉션 프로브와 플레이너 리플렉션이다.

 

 대부분의 반사가 그렇듯 이 두 가지 방식도 카메라로 특정 오브젝트를 이미지로 촬영한 후, 그 이미지를 다시 다른 오브젝트에 투영시키는 방식을 취한다.

 

 그리고 이 둘은 차이점이 존재하는데, 리플렉션 프로브는 주위의 "조명과 색" 큐브 맵 형식으로 저장하여 환경 매핑에 중점을 두고 있어 조금이라도 더 자연스러운 배경을 만들기 위하여 용이하고, 플레이너 리플렉션은 카메라가 보는 특정 화면(이미지)을 렌더링 하고, 이 렌더링 한 이미지를 특정 오브젝트에 투영시킨다.  그렇기 때문에 거울 같은 특정 오브젝트에 사용하기 적합한 방식이다.

 

 이번에는 리플렉션 프로브의 경우 게임 개발을 할 때 흔하게 사용되어 많은 사람들이 알기 때문에, 플레이너 리플렉션에 대하여 기록해 본다.

 

 플레이너 리플렉션의 경우 거울, 호수에 비치는 산과 같은 비주얼을 만들어 내는데 매우 높은 퀄리티를 자랑한다.

 정확하게 현실의 반사를 만들어 낼 수 있다. 하지만 만능으로 사용하기에는 플레이너 리플렉션의 구조상 문제점이 존재하기도 한다.  이 부분은 뒤에서 다시 이야기하며, 우선 사용방법을 보자.  이 사용방법을 보면 구조상의 문제점이 예상될 것이다.

 

플레이너 리플렉션을 적용한 이미지


사용 방법

 

 1. 하이 라키에 카메라 생성 // 메인용 카메라가 아님

 2. 프로젝트에 렌더 텍스처 생성
 3. 1번에서 생성한 카메라의 Output/Output Texture에 2번에서 생성한 렌더 텍스처를 넣어준다.

 4. 플레이너 리플렉션을 적용할 오브젝트의 메테리얼에 입력할 텍스처에 2번에서 생성한 렌더 텍스처를 넣어 준다.


 구현 구조 

 

 간단하게 3D 공간에 오브젝트들이 배치되어 있고, 이것들을 카메라가 촬영하여 화면에 뿌려주는데, 여기서 카메라가 촬영한 프레임(이미지)을 원하는 오브젝트에 투영시키는 방법이다. 

 

 이 부분을 위의 사용방법과 함께 이야기하면 이렇다.

 

 1. 반사를 하기 위하여 타깃이 되는 프레임(이미지)를 만들어 내기 위한 카메라를 하나 생성한다.
 2. 1번에서 생성한 이미지를 저장하기 위한 버퍼(렌더 텍스처)를 생성한다.
 3. 1번의 결과물로 반사용 카메라에서 렌더링 된 이미지를 2번에서 생성한 버퍼(렌더 텍스처)에 넣어 준다.

 4. 3번까지의 과정을 거친 버퍼(렌더 텍스처)를 이미지 이용하여 원하는 오브젝트에 투영시킨다.

 위와 같이 너무나도 간단한 구조이다.  하지만 구조상의 문제점이 여기 1번에서 나온다.  반사용 카메라 또한 렌더링을 하는 과정을 거친다는 것이다.  무슨 말이냐면, 반사를 표현하기 위한 타깃 이미지를 만들기 위하여 한 번 더 렌더링을 하고 있다는 말이다.  이것은 유니티도, 언리얼도 똑같은 구조이다.

 그렇기 때문에 잘못 사용하면 엄청난 프레임 드랍이 일어 날 수 있고, 버퍼를 사용하기 때문에 렌더링이 이상하게 될 수도 있다.  물론 이런 문제점들을 최소화하는 방법들을 이용하여 최적화를 진행해야겠지만, 기본적으로 해주어야 할 룰 같은 게 존재한다. 


 성능을 위한 기본 규칙

 

 월드(유니티에서는 Scene이라고 생각하자)에 존재하는 플레이너 리플렉션을 최대한 적게 쓴다.

  > 하나의 반사용 카메라마다 오브젝트(카메라에 걸리는 모든 오브젝트)와 렌더러 피처들을 한 번씩 더 렌더링 한다.

 

 드로우콜 수를 최대한 낮춘다.
  > 위와 같은 이야기로 카메라마다 똑같은 렌더링을 반복하기 때문에, 드로우콜 수가 매우 늘어나게 된다.


2부 - 플레이너 리플렉션을 사용하며 얻을 수 있는 부산물


카메라의 위치와 시선

 

 거울에 반사되는 내 모습이나, 호수에 비치는 풍경을 보았을 때, 어딘가 왜곡되고 어색하다고 이상함을 느낀 적이 있을까? 아마 감정적인 부분에서의 왜곡이 아니라면 이상함을 느끼지 못했을 것이다. 하지만 내가 플레이너 리플렉션을 게임에 적용하면 이상한 부분들이 많을 것이다.

 

 특히 처음에는 수평선에 대칭이 되지 않는 반사를 보게 되는 경우가 많을 것이다. 답부터 말하면, 메인 카메라와 플레이너 리플렉션용 카메라를 기준(수평선, 반사를 투영할 오브젝트)을 중심으로 대칭으로 배치하지 않았거나, 카메라의 각도 값이 잘못되어 있을 것이다.

 

 위의 이미지와 같이 만들기 위해서 메인 카메라를 기준으로 리플렉션 카메라의 포지션 Y 값을 음수로(기준이 0일 경우), 로테이션 Z 값을 180회전, Y 값은 Flip 시킨다.


카메라의 FOV와 프레임 비율

 

 분명 위치와 시선을 맞췄지만, 소실점이 맞지 않는다? 그렇다면 메인 카메라와 리플렉션 카메라의 FOV가 맞지 않는 것이다.


 렌더링 되는 오브젝트가 기준점에 맞지 않고 하단의 이미지와 같은 상태이다? 프레임 비율이 맞지 않는 것이다.

 

 프레임 비율이 맞지 않는다는 것은, 렌더링 파이프라인의 공간 변환을 생각해 보자. 모델(스페이스 생략) > 월드 > 뷰 > 클립 > 스크린으로 변환 되는 과정 중, 모델, 월드, 클립, 스크린은 동일하지만 뷰 스페이스는 다를 것이다. 이부분을 맞춰줘야 한다.

 

 메인 카메라의 뷰는 지금 내가 보고 있는 게임 화면의 프레임이고, 반사 카메라의 뷰는 위에서 만들었던 버퍼(이미지, 리플렉션 텍스처)의 사이즈이다. 이 두 사이즈를 맞추면 베스트지만, 서로 정밀도가 달라야 한다면, 반드시 프레임 비율은 맞춰 주어야 문제가 없다.


플레이너 리플렉션과 렌더러

 

플레이너 리플렉션을 진행하며 최적화를 시도해 보기 위하여 렌더러를 수정해 보았다.

 

- "메인 카메라와 반사 카메라를 통합하면 중복 렌더링이 없을 수 있을 것 같다."라는 가설이 떠올라 확인 카메라를 통합하였다.  결과적으로 이것은 효과가 없었다.  프레임 디버거로 이 과정을 확인하였는데, 카메라가 통합되어 있어도, 같은 작업을 반복 수행하고 있었다.


- 다음으로 진행한 것은 각각의 카메라에 렌더러를 분리해 보았다.  그리고 이 역시 프레임 디버거로 잘 분리된 것을 확인하였다.  최종적으로 드로우콜은 위와 차이는 없었지만 좋은 선택이었다.

 

- 렌더러를 분리하니 리플렉션 이미지를 만들 때, 필요한 것만 렌더링 하도록 하였다.  프레임 디버거로 확인해 보니 필요 없는 과정은 거치지 않았다. 즉 기본 렌더링과 다르게 최적화가 가능한 부분이고 이 부분이 최적화 된 렌더러를 사용하는 핵심적인 이유이다.

 

- 마지막으로 혹시나 하는 마음에 렌더러를 분리하고, 카메라는 통합해 보았지만, 역시나 같은 결과일 뿐, 성능 면에서 이점은 없었다.


RenderDoc에서... 이건 추후에 다시 확인해 보아야 함.

 

 프레임 디버거의 경우 정확한 디버깅, 렌더링 과정을 보장할 수 없어, 렌더독으로 확인해 보았다.  그런데 놀라운 결과를 보게 되었다.  렌더독에서는 리플렉션 렌더링 과정이 나오지 않았다.  몇 번이고 스냅샷을 찍어 보았지만 결과는 같았다.  잘못된 결과일 확률이 크니 추후에 다시 한번 확인할 필요가 있다.


컬링 기능으로 카메라 비활성화

 

  유니티의 카메라 구조는 좀 비효율적인 면이 있다.  화면에 보이지 않더라도 씬에 존재만 하면 렌더링 과정을 거치고 있다.  이로 인하여 메인 카메라에 플레이너 리플렉션이 투영되는 오브젝트가 없더라도 리플렉션은 렌더링을 진행하고 있다는 것이다.

메인 카메라에 오브젝트를 렌더링 하지 않아도, 플레이너 리플렉션용 카메라는 렌덜링 하고 있다.

 그렇기 때문에 메인 카메라에 리플렉션을 투영한 오브젝트가 걸리지 않는다면 리플렉션 카메라들을 꺼버리는 스크립트를 적용 후, 프레임 디버거로 확인해 보니 잘 작동했다.


3부 - 마치며...


 플레이너 리플렉션은 상황에 따라 정말 좋은 효과를 얻을 수 있다.  하지만 계획없이 사용하면, 성능에 문제가 생길수 있다. 

 

 원활한 게임 플레이를 제공하기 위하여 상황에 맞춰서 사용하면 좋겠다.  실제로 내가 게임에 적용했을 때는 정말 필요하고 최대한 성능에 문제없는 상황에만 사용하였다.

 

 만약 MMORPG나 위와 같이 성능 면에서 문제가 있는 상황이라면 그럴싸하게 트릭을 사용하는 것을 추천한다. 

 

 그리고 야간의 배경씬 같은 경우 빛과 색만으로도 충분히 멋지게 나올 수 있기 때문에 리플렉션 프로브를 사용하길 추천한다. 


 스크립트

 

다음 글에는 플레이너 리플렉션을 확인하며 만들었던 스크립트들에 대해 기록해 본다.

 

1. 메인 카메라 <> 리플렉션 오브젝트 컬링 관련
2. 인 게임 내 간단한 이동
3. 메인 카메라 <> 플레이너 리플렉션 카메라 트랜스폼 값 자동 수정기