KoreanFoodie's Study
[OpenGL ES] 18강 : GPU 테셀레이션(Tessellation), 변위 매핑(Displacement Mapping), 컨트롤 쉐이더, 테셀레이터, 생성 쉐이더, PN-삼각형 본문
[OpenGL ES] 18강 : GPU 테셀레이션(Tessellation), 변위 매핑(Displacement Mapping), 컨트롤 쉐이더, 테셀레이터, 생성 쉐이더, PN-삼각형
GoldGiver 2023. 5. 19. 17:50
이 강의는 유투브에 무료로 공개되어 있는 한정현 교수님의 컴퓨터 그래픽스 강좌를 정리한 글입니다. 자세한 내용은 강의를 직접 들으시거나 책을 구입하셔서 확인해 보세요. 강의 자료는 깃헙 링크에 올라와 있습니다.
요약 :
1. GPU 테셀레이션을 이용해 복잡한 표면을 실시간에 생성할 수 있는데, 대표적으로 변위 매핑(Displacement Mapping) 과 PN-삼각형이 있다. 실제로는 변위 매핑을 많이 사용한다.
2. 먼저, 컨트롤 쉐이더는 패치(patch) 정보를 받아, 테셀레이션을 얼마나 잘게 쪼개 진행할지를 테셀레이터에게 알려준다. 그럼 테셀레이터는 레벨에 맞게 패치를 쪼개 정의역(Domain) 을 생성한다. 생성 쉐이더는 2차원 메시의 각 정점마다 사각형 패치의 한 점을 생성한 후, 하이트 맵(Height map)의 정보를 받아 실제 변위를 변경한다.
3. PN-삼각형을 사용하면 Low Polygon Mesh 를 매끄럽게 렌더링할 수 있는데, 겹선형 패치와 무게 중심을 활용하여 계산한다.
GPU 테셀레이션(Tessellation)
GPU 파이프라인이 처리하는 기하학적인 개체를 프리미티브(Primitive) 라고 하는데, OpenGL ES 3.2 부터, 하드웨어 테셀레이션이 지원된다. 이 기능 덕분에, GPU 는 하나의 프리미티브를 여러 개의 작은 프리미티브로 쪼갤 수 있게 되었다.
이를 위해, 테셀레이션 컨트롤 쉐이더(이하 컨트롤 쉐이더) 와 테셀레이션 생성 쉐이더가 추가되었다. 또한 두 쉐이더 사이에는 하드웨어로 고정된 단계(hard-wired)인 테셀레이션 프리미티브 제네레이터(이하 테셀레이터)가 놓인다.
테셀레이션을 이용해 복잡한 표면을 실시간에 생성할 수 있는데, 변위 매핑(Displacement Mapping) 과 PN-삼각형이 있다.
PN-삼각형은 대중적인 기법이 아니므로 참고로 알아두기만 하자 😅
변위 매핑(Displacement Mapping)
변위 매핑은 메시의 오돌토돌한 표면을 '흉내'냈던 노멀 매핑과는 다르게, 실제로 정점 위치를 옮겨 오돌토돌한 표면을 만든다. 이제 그 과정을 알아보자 😄
컨트롤 쉐이더는 삼각형이나 사각형으로 이루어진 패치(patch)를 입력으로 받아, 이를 그대로 생성 쉐이더에게 넘긴다.
컨트롤 쉐이더는 이를 얼마나 잘게 나눌지를 결정해서 테셀레이터에게 알려주어야 하는데, 이를 테셀레이션 레벨이라고 한다. 테셀레이터는 컨트롤 쉐이더가 지정해준 대로 패치의 정의역(domain) 을 잘게 나눠 2차원 메시를 구성한다.
위 그림을 보면, 정사각형의 정의역이 2차원 메시로 변한 것을 확인할 수 있다.
2차원 메시의 각 정점에 대해 생성 쉐이더가 병렬로 실행되는데, 컨트롤 쉐이더가 건내준 사각형 패치를 겹선형 패치(bilinear path)로 가정하고, 테셀레이터가 건내준 (u, v) 좌표를 이용해 사각형 패치의 한 점을 생성한다.
GL 프로그램은 하이트 맵(Height map) 을 생성 쉐이더에게 건내주는데, 생성 쉐이더는 이로부터 높이 값을 추출하고 사각형 패치의 점을 높이만큼 올리게 되는 것이다! 😉
이제 버텍스 쉐이더를 다시 보자. 버텍스 쉐이더는 이제 gl_Position (클립 공간에서의 좌표)을 계산하지 않고 있다. 그 과정은 생성 쉐이더가 수행할 것이다.
v_position 과 v_texCoord 는, 정점 쉐이더가 출력하는 좌표인데...
위에 나와 있는 컨트롤 쉐이더의 코드를 보면, 정점 쉐이더의 출력을 입력으로 받는 것을 확인할 수 있다(v_position, v_texCoord). 각 버텍스의 ID 는 gl_InvocationID 에 저장된다.
마찬가지로, 테셀레이션 레벨도 gl_TessLevelOuter 와 gl_TessLevelInner 에 저장된다. 이때 Outer 는 패치의 경계를, Inner 는 패치의 내부를 분할하는데 사용된다.
실제 예시를 보면... Outer[0] 의 경우 7 로 되어 있는데, 실제로 7등분이 되어 있는 것을 확인할 수 있다.
반면 Inner[0] 는 8로 되어 있는데, 너비 부분이 8등분이 되어 있다.
변위 매핑을 위한 생성코드를 보자. layout(quads) in; 을 보면, 사각형 패치를 입력으로 받는 것을 확인할 수 있다.
테셀레이터가 만든 2차원 삼각형 메시의 각 정점마다 생성 쉐이더가 작동하는데, 정점의 (u, v) 좌표는 gl_TessCoord 라는 내장 변수에 저장되어 생성 쉐이더에게 전달된다. (main 함수의 1, 2번째 줄 참고)
겹선형 보간 방식은 정점의 Position 과 Texture 에 각각 적용되며, 그 이후 vertical displacement 가 진행된다. 즉, 하이트 맵을 이용해 높이가 바뀐다는 뜻이다.
눈여겨볼 것은, 이전에 정점 쉐이더가 담당했던 gl_Position 의 출력을 이제 생성 쉐이더가 수행한다는 것이다! 😉
폴리곤 메시를 렌더링하려면 드로우 콜을 해야 하는데, 위 그림은 그 과정을 거친 결과를 잘 보여준다!
PN-삼각형
PN-삼각형을 사용하면, 저해상도 메시를 부드러운 고해상도 메시로 바꿀 수 있다. 이는 여러 이점이 있는데...
저해상도 폴리곤 메시가 GPU 파이프라인에 입력되었다고 가정하자. 이는 우선 정점 쉐이 더에 의해 처리되는데, 정점 쉐이더는 다양한 애니메이션 혹은 물리 시뮬레이션을 메시의 각 정점에 적용할 것이다(13장에서 소개한 스키닝 애니메이션이 정점 쉐이더에 의해 구현 된다는 것을 상기하라). 그런데 애니메이션과 물리 시뮬레이션은 많은 시간을 소요하는 복잡한 알고리즘을 구현한 경우가 많다. 따라서 이를 저해상도 메시에 적용하는 것은 효율적인 선택이다. 이렇게 애니메이션 혹은 물리 시뮬레이션을 거친 물체를 테썰레이션을 통해 부드러운 고해상도 메시로 바꾸면 렌더링 품질이 높아질 것이다.
그런데 이게 어떻게 가능한 것일까..?
일단, PN-삼각형은 메시의 한 삼각형으로부터 유도한 베지어 삼각형이라고 정의할 수 있다. P 는 Point, N 은 Normal 을 의미하는데, 하나의 PN-삼각형은 다수의 작은 삼각형들을 만들고 이들은 원래의 삼각형을 대체한다.
엄... 책에 있는 설명을 보면, 컨트롤 포인트를 통해 베지어 삼각형을 만들게 되는데...
그림을 보면 직관적으로 이해가 조금 된다.
위의 그림을 보고... p300 과 p030 을 이용해 p120 과 p210 이 어떻게 만들어지는지를 추측해 보자. 사실 복잡한 건 없다. 그냥 코사인 법칙과, 반사광을 만들 때의 벡터 연산을 해 주면 된다.
그럼 경계의 점 말고, 내부의 점은 어떻게 만들까...? 그건... 아래의 수식을 이용하면 된다고 한다 😅
그렇다고 한다...! 절대 어려워서 설명을 하지 않는 건 아니고... 손목이 아파서 그렇다.. 😅
우리는 10개의 컨트롤 포인트를 모두 결정했다. 따라서 그림 18.10-(a)에 보인 바와 같은 3차 베지어 삼각형의 식 p(u,v,w)를 얻었다. 그러면 17강의 패치를 만드는 과정에서 설명한 것처럼, 균일하게 샘플한(u,v, w) 좌표들을 이용하여 베지어 삼각형을 테썰레이션할 수 있다. 즉, 각각의 (u,0,0)를 p(u,0,0)에 대입하여 3차원 정점 (x,y,z)를 얻는데, 이들 정점을 연결하여 고 해상도 삼각형 메시를 구성할 수 있다.
그런데 메시를 렌더링하기 위해서는 이러한 정점 위치만으로는 부족하다. 정점 노멀이 필요하다. 정점 노멀을 계산하는 가장 간단한 방법은, 입력으로 주어진 노멀 21, 22, 3의 무게 중심 조합(barycentric combination)을 택하는 것이다. 이 무게중심 조합을 n(u, v, w)라 표기 하자. 그런데, 그림 18.10-(b)에 보인 바와 같이, n(u, v, w)는 결국 1 차 베지어 삼각형이다. 컨트롤 포인트와 대비되도록 우리는 {n1, n2, n3} 를 컨트롤 노멀이라 부른다.
두 점 사이의 컨트롤 노멀을 구하는 방식은 (a) 처럼 나타낼 수 있다. 그런데 (b) 의 경우처럼, 단순히 두 점의 중점으로만으로는 정확하지 않을 수 있다. 그럴 때는 (c) 처럼 더 세분화하여 노멀을 구해야 한다. 이는 선형 보간을 한 번 더 해주어야 함을 의미한다.
PN-삼각형의 구현 과정은 위와 같다.
삼각형 패치를 위한 테셀레이션도, 기존의 변위 매핑에서 Inner/Outer 에 테셀레이션 레벨이 저장된 방식과 유사하다.
TL (테셀레이션 레벨) 이 올라감에 따라, 삼각형이 어떻게 분할되는지를 보자.
오.. PN-삼각형은 대단해!