Graphics Programming

렌더링 챌린지 일지 1 본문

Season 2

렌더링 챌린지 일지 1

minseoklee 2020. 11. 10. 15:06

목적도 없이 토이 프로젝트를 만드니 진도가 잘 안 나가서 세운 계획이 있는데, 바로 인터넷에서 수집한 사진들을 따라 만들어보는 "렌더링 챌린지"다.

 

몇 가지 기준에 따라 챌린지에 적합한 사진들을 선택했다.

1. 구하기 힘든 고퀄리티 모델이 사진의 중요 구성 요소여서는 안 된다.

2. 내가 아직 만들지 않은 렌더링 테크닉을 구현하기에 적합해야 한다.

 

www.deviantart.com/antoinecollignon/art/Antigravita-825581711

그렇게 챌린지용 사진들을 추려내고 첫번째로 이걸 골랐다.

 

 

렌더링 챌린지를 시작하기 전의 내 프로젝트 상태. 갈 길이 멀다.

 

하늘 equirectangular map

먼저 하늘 텍스처를 절차적 생성한다. 별과 은하수를 넣고 싶어서 Shadertoy에서 적당한 코드(www.shadertoy.com/view/4ljcz1)를 찾았다. 원본 코드는 2D 버전인데 내 엔진은 하늘을 그릴 때 equirectangular map을 쓰기 때문에 3D 버전이 필요하다. 포팅을 시도했지만 잘 되지 않았다.

 

하늘 렌더링 결과

별이 왜곡되어 점으로 보이지 않고 은하수도 원본에 비해 많이 이상하다. 별을 잘 그리려면 구 표면에서 균일한 노이즈가 필요하고 은하수는 뭐 어떻게 잘 섞어야 하는데 나중에 고쳐보고 넘어간다.

 

사진에서는 가운데 발광하는 구가 있고 고리 구조물들이 그 주위를 회전하고 있다. 먼저 구 메시를 배치하고 고리 메시는 여러 크기의 원판을 만들고 적당히 구멍을 내는 식으로 절차적 생성한다.

 

고리에 입힐 텍스처가 필요한데, 예전에 구매하고 켜보지 않은 서브스탠스 디자이너가 생각났다. 유튜브에서 튜토리얼을 보고 적당히 만들었다. 별로 예쁘게 뽑히지 않아서 다시 만들어야겠다.

 

구가 발광할 수 있게 머티리얼에 emissive color를 추가했다. 그러면서 가로로만 퍼지던 블룸 패스를 고쳤다. 블러 핑퐁할 때 두 번 다 가로 블러만 쓰는 오타가 있었다.

 

원래는 화면과 해상도가 같은 블룸 텍스처를 썼는데 언리얼 코드를 보니 블룸은 다운샘플해서 쓰고 있었다. 나도 다운샘플해봤는데 가끔 화면에 큰 흰점이 깜빡이는 아티팩트가 생겼다. NaN 픽셀이 블러를 거치면서 생기는 현상 같은데 나중에 고쳐야 한다.

 

블룸을 구현하기 위해 단순히 two-pass 가우시안 블러를 썼는데 emissive color에 의한 블러가 너무 심하다. 블러 패스도 손봐야겠다.

 

구에서 고리로 이어지는 빌보드 라이트닝 파티클을 절차적 생성했다. 그런데 빌보드 계산이 이상해서 굵기가 일정하지 않다. 바깥쪽 고리에 연결되는 파티클은 안쪽 고리를 피해서 생성하고 지지직 거리는 애니메이션이 필요한데... 나중에 개선하고 넘어간다.

 

구 위치에 포인트 라이트를 추가해서 주변이 더 밝아보이게 만들었다.

 

지금까지는 원본 사진의 위치가 대기 밖 우주라고 생각하고 있었는데, 광원 주변의 허공이 밝은 것을 보고 대기 안이라는 것을 깨달았다. 허공이 밝으려면 미세입자가 광원에서 나온 빛을 내 눈으로 산란시켜야 한다. 언리얼로 치면 VolumetricFog에 의한 이펙트인데 우선순위를 마지막으로 미뤘다.

 

블렌더 튜토리얼을 보고 타워와 우주선을 만들었다.

 

모델들의 트랜스폼을 하드코딩으로 맞추고 있는데, 슬슬 블렌더에서 배치하고 커스텀 포맷으로 익스포트하는 게 편할 것 같다는 생각이 들기 시작했다.

 

우주선 배기구에 emissive color를 추가하고 타워에도 서브스탠스로 텍스처를 만들어 입혔다.

 

이제보니 포인트 라이트에 의한 그림자가 없어서 구현했다. 예전에 포워드 셰이딩일 때는 있었는데 디퍼드 셰이딩으로 바꾸면서 다시 만드는 걸 깜빡했다. 텍스처 바인딩 포인트 문제로 모든 omni shadow map을 하나의 큐브맵 텍스처 배열에 넣었는데, 이러면 모든 포인트 라이트의 shadow map이 같은 해상도를 가져야 한다. 아마 텍스처 아틀라스에 모든 섀도우 맵을 때려넣고 샘플링을 알아서 해야할 거 같은데... 귀찮아...

 

GPU Pro 7을 보고 볼류메트릭 클라우드를 구현했는데 해상도가 마음에 안 든다. 레이마칭, 구름 노이즈 샘플링, 스캐터링 계산 중 뭐 하나 제대로 되는 게 없다.

 

구름을 계속 고쳐봤지만 원하는 퀄리티가 나오지 않았다. 깃헙이나 Shadertoy에 샘플 코드가 많지만 구름의 분포 및 모양을 잡아주는 계산과 라이팅 계산이 대부분 야매여서 참고하기 어렵다. 나중에 레이마칭 최적화를 할 때 다시 고쳐야겠다.

 

하늘 -> G버퍼 순으로 그리는데 하늘을 그릴 때 구름을 합성했더니 구름이 항상 물체들 뒤에 보였다. 그래서 구름 렌더링을 G버퍼 이후로 미루고, 톤 매핑할 때 transmittance를 이용해 G버퍼와 구름을 합성하여 구름이 앞에 보일 수 있게 한다.

 

단순히 블렌딩 시점만 미루면 타워에 가리는 부분의 구름도 보이게 되는데, 구름 레이마칭할 때 scene depth와 비교해 오클루더가 있으면 루프를 종료한다. scene depth 텍스처만 따로 만들려고 뎁스 프리패스를 구현했는데, 생각해보니 구름을 G버퍼 이후에 그리기 때문에 사실 뎁스 프리패스를 따로 만들 필요가 없다. 나중에 다른 거 구현할 때 쓸모가 있겠지 -.- 아직 SSR과 하드웨어 오클루전이 없는데 아마 이것들 구현할 때 HiZ 때문에 필요할 것 같다.

 

레이마칭에 뭔가 문제가 있는데 구름 안으로 들어가보면 문제가 더 뚜렷해진다. 구름이 보여야 되는 곳이 비거나 세로로 이상한 층이 생긴다. 일단 완전 나이브하게 구현했더니 GTX 1660 super 기준 다른 패스들은 1.5 ms를 넘어가는 게 없는데 구름 패스만 13 ms가 나온다. empty-space optimization, Bayer filter, temporal reprojection 등 여러가지 최적화를 빡세게 해야 한다.

 

사진에 있는 요소들 중 남은 것은 Volumetric fog, 우주선 애니메이션, 우주선 비행 궤적 파티클 정도가 끝인 것 같다. 구색만 갖춰놓고 하나씩 퀄리티 업을 하면 되겠다.

 

목적 없이 만들던 때보다는 비교적 진도가 잘 나가고 사진을 점차 닮아가는 재미도 있다. 챌린지용 사진은 수십 장 있기 때문에 흥미만 잃지 않는다면 오랫동안 하게 될 것 같다. 레이트레이싱과 볼륨 렌더링 공부용 토이 프로젝트들도 있는데 몇몇 챌린지는 그것들로 해봐도 좋을 것 같다.

Comments