Computer Graphics/ShaderPixel

ShaderPixel - 3. 렌더링 전략 고민..

surkim 2024. 11. 13. 12:49

일단 과제에서 요구된 오브젝트 중 일부는 그냥 레이마칭으로 구현해야 하는 상황이었다.

평소처럼 메쉬 기반으로 버텍스 셰이더에서 판단해서 그리면 되는 게 아니라 레이마칭을 적용해야 해서.. 메쉬랑 같이 사용하려면 깊이 정보를 직접 계산해줘야 했다. 이게 메쉬 기반 오브젝트가 혼합되어 있는 상황이라 더 어려워진다.

 

 

특히 지금 레이마칭을 적용해야 하는 오브젝트들은 블렌딩이나 반투명 효과를 주는 상황이 많아서, 뒷배경에 있는 오브젝트가 보이도록 해야 한다는 게 또 문제다.

특히 반투명 구슬이나 구름 같은 오브젝트는 서로 영향을 주는 상호작용을 고려해야 한다.

예를 들어 구름 뒤에 보이는 반투명 구슬, 혹은 구슬에 비치는 구름처럼 보이도록 구현하려면, 같은 셰이더 안에서 계산해야 이런 상호작용이 쉬워진다. 각각의 셰이더로 따로 나눠서 작업하면 먼저 그려지는 오브젝트는 뒤에 그려질 걸 모르니깐 이런 처리가 불편하다는 점이 난관이었다.

 

 

당장은 두 가지 방법이 떠올랐는데..

첫 번째 방법은, Simple is the best.

모든 오브젝트를 한 셰이더에 통합하는 방법이다. 프래그먼트 셰이더가 1920x1080 해상도 전체에서 동작하는 방식이니 가장 단순한 방법이긴 하다.

단점이라면 한 셰이더에서 모든 오브젝트를 렌더링 하니 코드 가독성 관련 문제와 과연 그리는 기법이 다른데 같은 셰이더에 있어야하는지에 대한 찝찝함이 있다. 그래도 셰이더 안에서 최적화가 가능하다는 점에서 구현은 편할 듯 하다.

 

 

두 번째 방법은 오브젝트마다 셰이더를 따로 두는 대신, 렌더링 순서를 정렬해서 각 오브젝트를 그릴 때마다 프레임버퍼에 누적해 그리는 방법이다.

레이마칭 기반의 오브젝트를 그릴 때, 이 프레임버퍼에 저장된 깊이 정보를 참고해서 오브젝트가 겹치는 부분을 표현할 수 있다.

모든 오브젝트에 대해 1920x1080 해상도만큼 프래그먼트 셰이더에서 레이마칭을 적용하는 것은 비효율적이니, 오브젝트가 그려질 공간을 메쉬화해서 미리 그려질 픽셀을 버텍스 셰이더에서 정의하고 프래그먼트 셰이더로 연산으로 처리하는 것이다.

 

적다보니 두번째 방식이 끌리긴 하는데..

이 방법을 했을 때 지금 딱 생각나는 문제는 버텍스 셰이더를 사용했을때 그 오브젝트가 나올 부분을 3D 메쉬로 지정를 할테니 같은 픽셀에서 그 오브젝트가 두번 계산된다는 건데 이 부분은 간단한 트릭으로 해결할 수 있을 거 같고 (뒤에 오는 메쉬를 오브젝트 중앙과 비교해서 판단하여 처음부터 그리지 않는 방식으로?)

일단 프레임버퍼가 계속 쌓여가면서 그리는 방식이라 이게 한방에 그리는 것보다 효율적인지 모르겠다는게 가장 큰 문제이다.

셰이더 코드는 분리되서 좋긴한데.. 괜히 어려운 방식으로 했는데 효율이 똥이면 한 의미가 없지 않나..

 

우선 해보고 첫번째 방법은 두번째 방법에서 SDF 함수만 통합해서 그리면 될 거 같으므로

해보고 비교를 해봐야겠다..