사전 삼각형 세트
개념

삼각형 세트

gabury1고친 사람 github-actions[bot]

삼각형 세트는 삼각형을 한 장씩 따로 적어서 입체의 겉면을 그리게 합니다. 꼭짓점 세 개를 모으면 삼각형 하나가 됩니다. 삼각형끼리 이어져 있지 않아도 되므로 어떤 모양이든 담을 수 있습니다.

쉽고 빠른 이해

무슨 일을 하나 — 입체의 겉면을 서로 따로인 삼각형 여러 장으로 담습니다. 꼭짓점 여섯 개를 셋씩 끊으면 삼각형 두 장이 담깁니다.

왜 이렇게 하나 — 그래픽 칩은 꼭짓점을 한 줄로 받습니다. 어디서 삼각형 하나가 끝나는지 정해 두지 않으면 꼭짓점을 이을 수 없습니다. 셋씩 끊는 것이 가장 단순한 약속입니다.

어떻게 도나

  1. 프로그램이 꼭짓점을 차례로 늘어놓아 넘깁니다
  2. 그래픽 칩이 앞에서부터 셋씩 끊어 삼각형을 만듭니다
  3. 셋을 못 채운 꼭짓점이 끝에 남으면 버립니다

대가 — 이웃한 삼각형이 같은 꼭짓점을 써도 삼각형마다 다시 적습니다. 그래서 꼭짓점에 번호를 붙여 한 번만 적는 방식을 흔히 함께 씁니다. 띠처럼 이어진 모양이면 꼭짓점을 덜 넘기는 다른 묶음이 맞습니다. 모양이 제각각인 물체에는 이쪽이 맞습니다.

상세

모자이크 벽화는 색 조각을 한 장씩 붙여 그림을 만듭니다. 조각마다 어디에 붙일지만 정하면 됩니다. 옆 조각과 맞닿아도 되고 떨어져 있어도 됩니다.

삼각형 세트도 삼각형을 이렇게 한 장씩 따로 적습니다. 이 절은 꼭짓점을 어떻게 묶어야 삼각형 세트가 나오는지 봅니다. 번호 0부터 5까지의 꼭짓점 여섯 개를 줄곧 예로 씁니다. 뒤쪽 소절에서는 번호로 데이터를 아끼는 법, 다른 묶는 규칙과의 차이, 이 이름이 쓰이는 곳을 차례로 봅니다.

삼각형으로 겉면을 그리는 까닭

3D 화면에 보이는 물체는 대부분 겉면을 작은 삼각형 여러 장으로 나눠 그립니다. 이렇게 삼각형을 이어 만든 입체 모양을 메시라고 부릅니다. 둥근 캐릭터 얼굴도 가까이 보면 평평한 삼각형으로 나뉘어 있습니다.

삼각형을 쓰는 까닭은 세 점이 늘 한 평면 위에 놓이기 때문입니다. 점이 넷이면 비틀려서 한 평면에 안 놓일 수 있습니다. 평평한 조각이어야 화면에서 칠할 넓이가 하나로 정해집니다.

화면에 그리는 일은 그래픽 칩인 GPU(Graphics Processing Unit, 그래픽 처리 장치)가 맡습니다. 프로그램은 그릴 데이터를 GPU 에 넘기기만 합니다. 화면에 칠하는 일은 GPU 가 합니다.

GPU 가 한 번에 칠하는 가장 작은 도형을 프리미티브라고 부릅니다. 점·선·삼각형이 프리미티브입니다. 입체의 겉면을 칠할 때 쓰는 프리미티브가 삼각형입니다.

정점 배열을 셋씩 끊기

삼각형의 꼭짓점 하나를 그래픽스에서는 정점이라고 부릅니다. 이 글도 이제부터 정점이라고 씁니다. 정점은 위치 좌표를 기본으로 담은 값 묶음입니다. 색이나 표면 방향 같은 값을 함께 담기도 합니다.

프로그램은 정점을 배열 하나에 줄지어 담아 GPU 에 넘깁니다. 배열에는 정점만 이어져 있습니다. 어디까지가 삼각형 하나인지는 적혀 있지 않습니다.

그래서 프로그램은 「이 배열을 이렇게 묶어라」라는 규칙을 함께 넘깁니다. 이 묶는 규칙을 프리미티브 토폴로지라고 부릅니다. 삼각형 세트는 그 가운데 가장 단순한 규칙으로 묶어 낸 결과입니다. 그 규칙은 앞에서부터 정점을 셋씩 끊어 삼각형 하나로 삼습니다.

정점 여섯 개를 넘기면 삼각형 (0,1,2) 와 (3,4,5) 가 나옵니다. 정점 일곱 개를 넘기면 마지막 정점 6 은 셋을 못 채웁니다. 이렇게 남는 정점은 버립니다.

두 삼각형은 정점을 하나도 나눠 쓰지 않습니다. 삼각형 세트에서 삼각형끼리는 아무 관계가 없습니다. 모자이크 조각처럼 맞닿아 있든 멀리 떨어져 있든 같은 방식으로 적습니다.

아래 함수는 이 묶는 과정을 흉내 냅니다. 배열을 앞에서부터 셋씩 잘라 삼각형들을 배열로 돌려줍니다.

JavaScript
function tris(v) {
  const out = [];
  for (let i = 0; i + 2 < v.length; i += 3) {
    out.push([v[i], v[i + 1], v[i + 2]]);
  }
  return out;
}

tris([0,1,2,3,4,5]);   // [[0,1,2],[3,4,5]]
tris([0,1,2,3,4,5,6]); // [[0,1,2],[3,4,5]]

반복 조건 i + 2 < v.length 는 정점 셋을 다 채울 수 있을 때만 삼각형을 만듭니다. 둘째 호출에서 남은 정점 6 은 결과에 없습니다. 두 호출의 결과가 같습니다.

번호로 같은 정점을 다시 쓰기

삼각형 세트의 약점은 맞닿은 삼각형에서 드러납니다. 사각형 하나를 삼각형 둘로 나누면 두 삼각형이 대각선 변을 함께 씁니다. 그 변의 양 끝 정점 둘이 두 삼각형에 다 들어갑니다.

정점 배열을 셋씩 끊는 방식에서는 이 두 정점을 삼각형마다 다시 적습니다. 사각형 하나에 정점 넷이면 될 것을 여섯 개 적는 셈입니다. 정점마다 위치와 색 같은 값이 붙으므로 그만큼 데이터가 늘어납니다.

이 중복을 막으려고 정점마다 번호를 붙입니다. 정점은 한 번씩만 적습니다. 삼각형은 정점 번호 셋으로 적습니다. 이 번호를 인덱스라고 부릅니다.

번호도 배열 하나에 담아 GPU 에 넘깁니다. GPU 가 읽도록 넘기는 값 배열을 버퍼라고 부릅니다. 그래서 정점 배열은 정점 버퍼, 번호 배열은 인덱스 버퍼라는 이름으로도 불립니다. 이 글은 계속 정점 배열과 번호 배열이라고 씁니다.

인덱스를 쓰면 셋씩 끊는 규칙이 정점 배열이 아니라 번호 배열에 걸립니다. 앞의 함수에 번호 배열 0,1,2,2,1,3 을 넣어 봅니다.

JavaScript
tris([0,1,2,2,1,3]); // [[0,1,2],[2,1,3]]

삼각형 (0,1,2) 와 (2,1,3) 이 나옵니다. 번호 1 과 2 가 두 번씩 나와도 정점 데이터는 한 벌이면 됩니다. 아래 그림은 이 예에서 번호가 정점을 가리키는 모양입니다. 정점 1 과 2 에는 화살표가 둘씩 모입니다.

flowchart TD
    subgraph IB["번호 배열"]
        subgraph T1["삼각형 (0,1,2)"]
            I0["0"]
            I1["1"]
            I2["2"]
        end
        subgraph T2["삼각형 (2,1,3)"]
            I3["2"]
            I4["1"]
            I5["3"]
        end
    end
    subgraph VB["정점 배열"]
        V0["정점 0"]
        V1["정점 1"]
        V2["정점 2"]
        V3["정점 3"]
    end
    I0 --> V0
    I1 --> V1
    I2 --> V2
    I3 --> V2
    I4 --> V1
    I5 --> V3

정점은 네 개만 적었습니다. 번호는 정수 하나라서 정점 하나보다 훨씬 작습니다. 모양이 제각각인 물체는 흔히 인덱스로 삼각형 세트를 적어서 그립니다.

띠와 부채로 묶는 다른 규칙

정점을 아끼는 길이 하나 더 있습니다. 이웃한 삼각형이 정점을 나눠 쓰도록 묶는 규칙을 고르는 것입니다.

삼각형 스트립은 새 정점 하나가 바로 앞 정점 둘과 삼각형을 이룹니다. 이웃한 삼각형이 변 하나를 함께 쓰는 띠 모양이 나옵니다.

삼각형 팬은 새 정점 하나가 바로 앞 정점, 그리고 첫 정점과 삼각형을 이룹니다. 그러면 모든 삼각형이 첫 정점을 함께 씁니다. 첫 정점을 가운데 두고 삼각형이 부채처럼 둘러 펼쳐집니다.

아래 표는 삼각형 k 개를 그릴 때 넘기는 정점 수와 그릴 수 있는 모양을 견줍니다.

묶은 결과 삼각형 k 개에 넘기는 정점 그릴 수 있는 모양
삼각형 세트 3k 개 제약 없음
삼각형 스트립 k+2 개 한 줄로 이어진 띠
삼각형 팬 k+2 개 정점 하나를 둘러싼 부채

삼각형 100개라면 삼각형 세트는 정점 300개, 스트립은 102개입니다. 대신 스트립 하나로는 떨어진 두 조각을 그릴 수 없습니다. 삼각형 세트는 정점을 더 쓰는 대신 모양에 제약이 없습니다.

그래서 쓰임이 갈립니다. 지형이나 길처럼 원래 띠로 이어진 모양에는 스트립이 맞습니다. 모양이 제각각인 물체에는 인덱스를 붙인 삼각형 세트가 맞습니다.

이 이름이 쓰이는 곳

API(Application Programming Interface, 애플리케이션 프로그래밍 인터페이스)는 프로그램이 다른 소프트웨어에 일을 시킬 때 부르는 함수 묶음입니다. 그 가운데 GPU 에 그리기를 시키는 것을 그래픽스 API 라고 부릅니다. 정점을 묶는 규칙도 이 함수에 넘기는 값 하나로 고릅니다.

그래픽스 API 는 셋씩 끊는 규칙을 삼각형 목록이라고 부릅니다. 브라우저에서도 이 규칙을 상수 하나로 고릅니다. WebGL 은 gl.TRIANGLES 를, WebGPU 는 "triangle-list" 를 씁니다.

두 이름은 가리키는 대상이 다릅니다. 규칙에 붙은 이름이 삼각형 목록입니다. 그 규칙으로 묶어 낸 삼각형 모음에 붙은 이름이 삼각형 세트입니다.

glTF(GL Transmission Format, GL 전송 포맷)는 3D 모델을 담는 파일 포맷입니다. glTF 는 메시 하나를 여러 덩어리로 나눠 담습니다. 덩어리마다 정점을 묶을 규칙을 값 하나로 적습니다. 그 값으로 셋씩 끊는 규칙을 고르면 그 덩어리는 삼각형 세트가 됩니다.

메시는 삼각형을 이어 만든 입체 모양 자체입니다. 삼각형 세트는 그 겉면을 서로 따로인 삼각형들로 적어 둔 데이터입니다. 같은 메시를 스트립으로 적을 수도 있습니다.

관련 항목

삼각형 세트를 이루는 데이터

정점 · 정점 버퍼 · 정점 속성 · 인덱스 · 인덱스 버퍼 · 배열

삼각형 세트와 견주는 묶는 규칙

삼각형 스트립 · 삼각형 팬 · 프리미티브 토폴로지 · 프리미티브 재시작 · 퇴화 삼각형

삼각형 세트가 속하는 상위 분류

메시 · 프리미티브 · 그래픽스 · 3D 모델

삼각형 세트를 받아 그리는 파이프라인 단계

그래픽스 파이프라인 · 입력 어셈블러 · 프리미티브 조립 · 래스터화 · 감김 순서 · 컬링

삼각형 세트를 적는 포맷과 그래픽스 API

glTF · X3D · WebGL · WebGPU · OpenGL · Vulkan · Direct3D

삼각형 세트와 이름이 겹치는 이웃

삼각형 목록 · 삼각형 메시 · 삼각형 수프 · 폴리곤 메시

다른 이름: triangle set · TriangleSet · 삼각형 집합