[GPU프로그래밍] 11.Using Tessellation Shaders

jungizz_·2024년 6월 9일
0

GPU Programming

목록 보기
11/15
post-thumbnail

◾ Tessellation shader

  • primitive 단위로 진행
  • primitive를 생성하기 때문에 gs보다 먼저 진행
    • ex) control point의 정보를 사용해 곡선을 그릴 때, line을 쪼개서 점의 위치 계산하고 line segment 생성
  • 자동으로 geometry를 쪼개서 구성하기 때문에 Subdivide Geometry 기존 pipeline으로 들어간 geometry보다 밀도있는 geometry를 내보냄 (GPU내에서)
    • 쪼갤 정도는 levels of detail에 따라 자동으로 조절된다

TCS/TPG/TES

  • Tesselation shader의 진행 방식은 3단계로 나눠진다
  • TCS에서 쪼갤 방법 및 정도에 대해 지정하고, 그 정보에 따라 TPG가 쪼개고, 쪼개진 버텍스별로 TPG에서 계산

Patch Primitive

  • 실제로 렌더링되는 primitive는 아니고, 계산에 이용되는 추가 정보를 묶어서 TCS와 TES에 보내는 용도
  • 한 Patch당 몇 개의 버텍스를 묶을건지 직접 정해준다
    • ex) 삼각형은 3개, bezier curve는 4개
    • 주로 control points의 set 역할
  • Tessellation shader가 활성화되어있다면 GL_PATCHES 형태의 primitive만 사용해서 렌더링할 수 있다
  • 각 patch에 묶을 수 있는 최대 버텍스 개수 확인 (시스템에 따라 다름)

❗ TCS/TPG/TES

1. TCS (Tessellation control shader)

  1. parameter space상에서 얼마나 쪼갤 것인지 대한 변수값 설정
    • gl_TessLevelInner, gl_TessLevelOuter
  2. 같은 patch에 속한 vertex 정보를 가져올 수 있어서 (기존 vs와 차이점) 그 정보로 patch에 대한 계산해서 TES로 넘겨줌
  • 한 patch primitive의 각 vertex마다 실행

2. TPG (Tessellation primitive generator)

  • TCS에서 지정한 것에 대한 알고리즘을 따라 Input patch를 쪼개서 primitive 생성 코드X
  • parameter값 생성 및 연결 정보 결정
    • 각 버텍스는 parameter space에서의 위치 정보 u, v, w로 구성 -> [0, 1]
    • 이 정보는 TES에서 계산하는데 사용

3. TES (Tessellation evaluation shader)

  • 쪼개져서 생성된 primitive의 형태 지정
    • quads면 사각형 형태로, isolines이면 곡선 형태로, triangles면 삼각형 형태
  • primitive의 각 버텍스별로 정보(위치 등) 계산
    • ex) Bezier, B-spine 등...
  • TPG에서 생성된 parameter-space 버텍스마다 실행
👀 아래부터는 Geometry shader를 사용하는 예제 4가지

1. Bezier Curve

  • 4개의 control point
  • Cubic Bezier curve
  • TCS에서 outer tessellation level을 지정해서 line segments의 개수 정의
  • TES에서 u, v parameter와 patch의 버텍스 정보를 사용해 bezier curve 식 계산 (line이라 u, v 둘 중 하나만 쓰긴함)
  • OpenGL Application에서

📃 Code

OpenGL Application

  • 4개의 control points를 patch primitive로 묶어 pipeline으로 보냄
    • patch별 버텍스 개수 지정
    • patch primitive로 4개의 control points 그리기
  • Segments의 개수(LoD), isolines(같은 값을 연결한 선)의 개수, 라인 컬러 uniform variables 설정
    • 이 예제에서 isolines의 개수는 라인 하나니까 1

vertex Shader

  • 라인만 그리므로 2D
  • TES에서 계산할거라 변환도 X

tessellation control shader

  • gl_InvocationID: 현재 TCS를 부른 vertex가 patch내에서 몇번째 index인지
  • 들어온 patch vertex값을 그대로 내보냄
  • 쪼개질 정보 TPG로 전달

tessellation evaluation shader

  • 쪼개진 primitive의 형태가 결정되며 들어옴
  • parameteru 값과 patch의 vertex값으로 bezier 계산
  • 계산된 3D 좌표에 MVP를 곱해서 최종 position 계산

fragment shader

2. 2D Quad

Level parameter

  • TPG는 여섯개의 level parameter에 기반하여 (u, v) parameter space를 쪼갠다
    • Outer level 0~3 (4개)
    • Inner level 0~1 (2개)
    • 각각 gl_TessLevelOutergl_TessLevelInner 배열에 저장

Linear interpolation

  • 쿼드를 쪼갤 때, 쿼드의 4개의 버텍스를 interpolation해서 쿼드 위의 한 점u, v을 계산한다
  • TPG에서 parametric coordinate set이 결정되고, 이에 해당하는 위치는 TES에서 Interpolation해서 계산

📃 Code

OpenGL Application

  • Outer/Inner tessellation level은 유니폼 변수로 전달
  • 반시계 방향으로 네 개의 버텍스를 담은 patch primitive 세팅

vertex shader

tessellation control shader

  • 유니폼 변수로 받은 Outer/Inner tessellation level 내보내기

tessellation evaluation shader

  • quad patch를 equal_spacing(균일한 간격으로), counter clock wise 방향으로 받아오기
  • u, v parameter값과 patch의 버텍스로 linear interpolation하여 위치 계산
  • 계산된 3D 좌표에 MVP를 곱해서 최종 position 계산

geometry shader

  • 쪼개지는 것을 보기 위해 gs에서 테두리 그리기 (삼각형 면만 그리면 안보이니까)

fragment shader

3. 3D Surface

  • 여러개의 patch로 이루어진 3D surface를 쪼개보자
  • teapot에는 한 patch당 4x4개의 버텍스가 들어있으며, cubic Bezier surface를 구성하기 위한 16개의 control points로 사용된다
  • 보내는 정보 (4x4 vertex)는 똑같은데 다른 디테일을 가진 surface를 만들 수 있다
    -> ts를 사용하면 적은 정보로도 복잡한 모델을 만들 수 있고, 병렬연산으로 계산 속도도 빠르다

Cubic Bezier Surface Interpolation

  • 이전 2D와 동일한 원리로 가로/세로 방향으로 계산
  • 어떤 위치u, v에 있는지에 따라 control point로부터 받는 영향이 다른 것
    • Pij: control point

Normal vector

  • 쪼개진 surface마다 노말을 알아야 shading 계산 가능하므로 노말을 구해야함
  • 원래는 surface를 주변 삼각형의 노말들을 평균내서 구했음
  • 근데 지금은 surface에 대한 식(parametric bezier surface)이 있으므로, 이 식을 활용하여 노말을 구한다
    • u, v 방향으로 편미분하여 평면에 접하는 두 접선을 구하고, 두 접선을 외적하여 수직인 벡터=노멀을 구한다 -> 근사가 아닌 정확한 노말!

📃 Code

OpenGL Application

  • patch별 16개의 버텍스 개수 지정
  • 16-vertex patch primitive로 control points 그리기
    • but, control point가 매번 3D 모델에 주어지는게 아니라서 어려울 수 있음

tessellation control shader

  • 들어온 patch vertex값을 그대로 내보냄
  • 유니폼 변수로 받은 tessellation level 내보내기 (이 예제는 Outer/Inner 전부 같은 레벨)

tessellation evaluation shader

  • 한 patch의 16개의 vertex를 control point로 설정
  • bezier interpolation하여 나온 3D 위치
    • camera coordinate로 변환하고, surface식을 편미분하여 구한 normal도 cc로 변환해서 fs로 보냄 -> shading 계산
    • MVP를 곱해서 최종 위치 계산

geometry/fragment shader

  • 2. 2D Quad 예제와 거의 동일

4. Tessellating based on Depth

  • tessellation level의 값을 유니폼이 아닌 depth의 값으로 계산 (linear interpolation)

Level-of-detail (LOD)

  • 카메라와의 거리(또는 다른 요인)와 오브젝트의 지오메트리 복잡성을 연관시킴

📃 Code

OpenGL Application

  • tessellation level과 depth의 최대/최소값 설정 (유니폼 변수)
    • depth가 작으면 level이 최대
    • depth가 크면 level이 최소

tessellation control shader

  • 실제 depth를 구하려면 sqaure root를 사용하게 되고 계산양이 너무 많아짐..
  • 그래서 control point를 cc로 변환하고 z값으로 depth를 근사한다
  • [0, 1]범위의 depth로 tessellation level interpolation

❗issues

  • tessellation level은 patch마다 주어지는 값인데, ts에서 계산하면 patch의 vertex마다 즉, 16번 계산하게된다
    • 매번 depth값이 약간씩 달라서 그 안에서 level값이 차이날 수 있다 -> 그 중 하나 사용됨
  • patch끼리 이웃하는데, patch별로 level이 달라지면 어긋나보일 수 있음
    • level이 낮으면 틈이 벌어질 수 있음
profile
( •̀ .̫ •́ )✧

0개의 댓글