사전 프리미티브
개념

프리미티브

gabury1고친 사람 github-actions[bot]

프리미티브는 그래픽스에서 그래픽 칩이 한 번에 칠하는 가장 작은 도형입니다. 점을 몇 개 이어 선이나 삼각형을 만듭니다. 그 도형이 덮는 픽셀을 칠합니다. 화면 속 입체 모델도 결국 삼각형 수천 개를 하나씩 칠해 그린 것입니다. 프로그래밍의 다른 분야에서도 더 쪼개지 않고 쌓아 올리는 기본 부품을 이 이름으로 부릅니다.

쉽고 빠른 이해

프리미티브는 그래픽 칩에게 「이 점 셋을 이어 삼각형 하나를 칠해라」라고 건네는 도형 한 개입니다. 사각형 하나를 그리려면 삼각형 두 개로 나눠 건넵니다.

그래픽 칩은 곡면이나 복잡한 다각형을 바로 칠하지 못합니다. 모양을 점·선·삼각형 같은 단순한 도형으로 쪼개 두면 어떤 모양이든 같은 방법으로 빠르게 칠할 수 있습니다.

어떻게 도나:

  1. 프로그램이 점 좌표를 줄줄이 그래픽 칩에 넘깁니다. 이 점들을 몇 개씩 묶어 도형으로 볼지도 알려 줍니다
  2. 그래픽 칩이 점들을 묶어 삼각형 같은 도형을 만듭니다
  3. 도형마다 화면에서 덮는 픽셀을 찾아 칠합니다

대가가 있습니다. 둥근 표면도 평평한 삼각형으로 흉내 내야 합니다. 매끄럽게 보이려면 삼각형 수가 늘어납니다. 그만큼 그래픽 칩이 할 일도 늘어납니다.

상세

이 절은 그래픽스의 프리미티브가 무엇이고 그리는 과정의 어디쯤에서 만들어지는지를 봅니다. 사각형 하나를 삼각형 둘로 그리는 예를 줄곧 씁니다. 마지막 소절에서 다른 분야가 이 낱말을 어떤 뜻으로 쓰는지 가릅니다.

점 잇기 그림책을 떠올리면 가깝습니다. 번호 붙은 점을 정해진 순서로 이으면 그림이 나옵니다.

앞에서 그래픽 칩이라 부른 것을 GPU(Graphics Processing Unit, 그래픽 처리 장치)라고 합니다. 화면에 그릴 픽셀 값을 대량으로 계산하는 칩입니다. GPU 는 「자동차를 그려라」 같은 명령을 알아듣지 못합니다. 알아듣는 것은 「이 점들을 이런 도형으로 묶어 칠해라」뿐입니다. 이때 한 번에 칠하는 도형 하나가 프리미티브입니다.

정점으로 정해지는 도형

프리미티브는 정점으로 정해집니다. 정점은 도형의 꼭짓점 하나를 나타내는 데이터 묶음입니다. 위치 좌표가 기본입니다. 색이나 텍스처 좌표 같은 값이 함께 붙기도 합니다.

정점 몇 개로 도형 하나가 되는지는 종류가 정합니다. 흔히 쓰는 기본 종류는 셋입니다.

종류 정점 수 칠하는 것
점 1 정점 하나가 놓인 곳의 픽셀
선분 2 두 정점을 잇는 선 위의 픽셀
삼각형 3 세 정점이 둘러싼 안쪽 픽셀

종류마다 정점 수가 고정입니다. 사각형이나 원은 기본 종류에 없습니다. 이런 모양은 삼각형 여러 개로 나눠서 그립니다.

삼각형이 주인공인 까닭

입체 모델을 그릴 때 쓰는 프리미티브는 거의 삼각형입니다. 삼각형에는 다각형이 못 주는 성질이 둘 있습니다.

첫째, 점 세 개는 언제나 한 평면 위에 놓입니다. 점이 넷이면 네 번째 점이 평면에서 벗어나 면이 비틀릴 수 있습니다. 삼각형은 그런 일이 없어서 면이 어느 쪽을 향하는지가 하나로 정해집니다. 어느 쪽을 앞면으로 볼지는 뒤의 「감김 순서」 소절에서 다룹니다.

둘째, 삼각형은 늘 볼록합니다. 볼록한 도형은 「이 픽셀이 도형 안에 드나」를 변마다 한 번씩 물어 가릴 수 있습니다. 픽셀이 변 세 개 각각의 안쪽 편에 있는지 세 번 확인하고, 세 번 모두 안쪽이면 도형 안입니다.

오목한 도형에서는 이 방법이 틀립니다. 움푹 들어간 곳 근처에서는 도형 안의 픽셀이 어느 한 변의 바깥 편에 놓이기 때문입니다. 삼각형은 판정이 이렇게 단순해서 GPU 가 픽셀 수백만 개를 한꺼번에 처리할 수 있습니다.

어떤 다각형이든 삼각형 여러 개로 나눌 수 있습니다. 그래서 삼각형 하나만 빠르게 칠하면 모든 평면 모양을 칠할 수 있습니다. 곡면은 잘게 나눈 삼각형으로 흉내 냅니다. 이렇게 삼각형을 이어 만든 모양이 메시입니다.

정점을 묶는 규칙

GPU 는 정점을 긴 배열로 받습니다. 배열만 봐서는 어디서 도형이 끊기는지 모릅니다. 그래서 프로그램이 「이 배열을 어떤 규칙으로 묶어라」를 함께 알려 줍니다. 이 규칙을 프리미티브 토폴로지라고 부릅니다.

규칙에는 종류가 들어 있습니다. 규칙을 고르면 도형의 종류도 함께 정해집니다. 「삼각형 스트립」을 고르면 나오는 도형은 삼각형이고, 「선분 목록」을 고르면 선분입니다.

같은 종류라도 묶는 규칙이 여럿입니다. 정점을 n 개 넘겼을 때 도형이 몇 개 나오는지가 규칙마다 다릅니다.

규칙 묶는 방법 정점 n 개로
삼각형 목록 셋씩 끊어 하나씩 삼각형 n/3 개
삼각형 스트립 새 정점 하나가 앞의 둘과 삼각형을 이룸 삼각형 n−2 개
삼각형 팬 첫 정점을 모든 삼각형이 함께 씀 삼각형 n−2 개
선분 목록 둘씩 끊어 하나씩 선분 n/2 개
선분 스트립 앞 정점과 이어 꺾은선으로 선분 n−1 개
점 목록 하나씩 점 n 개

목록은 도형마다 정점을 따로 넘기니 정점이 많이 듭니다. 스트립과 팬은 이웃 도형이 정점을 나눠 써서 적게 듭니다. 대신 이어진 모양일 때만 쓸 수 있습니다.

아래 그림은 정점 다섯 개(0~4)를 스트립과 팬으로 묶었을 때 나오는 삼각형 셋입니다. 스트립은 앞 삼각형의 뒤쪽 정점 둘을 다음 삼각형이 물려받습니다. 팬은 정점 0 하나를 세 삼각형이 함께 씁니다.

flowchart TD
    subgraph S["삼각형 스트립 · 정점 0~4"]
        s1["삼각형 0,1,2"] -->|"정점 1,2 물려받음"| s2["삼각형 1,2,3"]
        s2 -->|"정점 2,3 물려받음"| s3["삼각형 2,3,4"]
    end
    subgraph F["삼각형 팬 · 정점 0~4"]
        f0(("정점 0")) --> f1["삼각형 0,1,2"]
        f0 --> f2["삼각형 0,2,3"]
        f0 --> f3["삼각형 0,3,4"]
    end
    S ~~~ F

사각형 하나를 그리는 두 방법

사각형 네 꼭짓점에 번호를 붙여 봅니다. 왼쪽 위가 0, 왼쪽 아래가 1, 오른쪽 위가 2, 오른쪽 아래가 3 입니다. 대각선 1-2 를 그어 사각형을 삼각형 둘로 나눕니다.

아래 그림은 두 삼각형이 어느 꼭짓점을 쓰는지 보입니다. 두 삼각형 모두 꼭짓점 1 과 2 를 가리킵니다. 둘이 함께 쓰는 변이 바로 대각선 1-2 입니다.

flowchart TD
    subgraph T["삼각형 둘"]
        T1["삼각형 ① · 0,1,2"]
        T2["삼각형 ② · 2,1,3"]
    end
    subgraph V["꼭짓점 넷"]
        V0["0 · 왼쪽 위"]
        V1["1 · 왼쪽 아래"]
        V2["2 · 오른쪽 위"]
        V3["3 · 오른쪽 아래"]
    end
    T1 --> V0
    T1 --> V1
    T1 --> V2
    T2 --> V2
    T2 --> V1
    T2 --> V3

이 네 꼭짓점을 가리키는 번호 배열을 두 규칙으로 적으면 다음과 같습니다.

JavaScript
const list  = [0,1,2, 2,1,3]; // 삼각형 2개
const strip = [0,1,2,3];      // 삼각형 2개

목록 규칙은 번호 여섯 개를 셋씩 끊어 (0,1,2) 와 (2,1,3) 을 만듭니다. 스트립 규칙은 번호 넷으로 (0,1,2) 와 (1,2,3) 을 만듭니다. 결과는 같은 사각형입니다. 드는 번호 수만 다릅니다.

위 배열의 숫자는 정점 데이터가 아니라 정점을 가리키는 번호입니다. 번호가 여섯 개여도 정점 데이터 자체는 넷뿐입니다. 번호로 가리키면 같은 정점을 여러 삼각형이 다시 쓸 수 있습니다. 이 번호 배열을 담는 곳이 인덱스 버퍼입니다.

번호를 쓰지 않고 정점 데이터를 목록 규칙으로 바로 넘기면 사정이 다릅니다. 두 삼각형이 함께 쓰는 꼭짓점 1 과 2 의 데이터를 한 번 더 넘겨야 합니다. 그래서 정점 데이터가 여섯 개 듭니다.

감김 순서

삼각형의 정점 세 개가 화면에서 시계 방향으로 도는지 반시계 방향으로 도는지를 감김 순서라고 부릅니다. 이 순서로 삼각형의 앞면과 뒷면을 가립니다.

앞뒤를 가리는 까닭은 일을 덜기 위해서입니다. 닫힌 입체에서 카메라를 등진 뒷면은 어차피 앞면에 가려 안 보입니다. 감김 순서로 뒷면을 골라 칠하기 전에 버리는 일이 뒷면 컬링입니다.

위 사각형 그림으로 따져 봅니다. (0,1,2) 는 왼쪽 위에서 왼쪽 아래로 내려갔다가 오른쪽 위로 가니 반시계 방향입니다. (2,1,3) 은 오른쪽 위에서 왼쪽 아래를 거쳐 오른쪽 아래로 가니 이것도 반시계 방향입니다.

스트립의 두 번째 삼각형 (1,2,3) 은 왼쪽 아래에서 오른쪽 위를 거쳐 오른쪽 아래로 가니 시계 방향입니다. 번호 순서대로 읽으면 첫 삼각형과 방향이 반대가 됩니다. 그래서 스트립 규칙은 짝수 번째 삼각형의 앞 두 정점 순서를 바꿔 (2,1,3) 으로 읽고 방향을 맞춥니다.

그리는 과정에서 프리미티브가 서는 단계

GPU 가 정점을 받아 픽셀을 칠하기까지 거치는 단계를 그래픽스 파이프라인이라고 부릅니다. 프리미티브는 이 흐름의 중간에서 만들어집니다.

아래 그림에는 셰이더라는 낱말이 두 번 나옵니다. 셰이더는 GPU 에서 도는 작은 프로그램입니다. 그림에 나오는 단계 이름은 그림 뒤 문단에서 하나씩 풉니다.

flowchart TD
    A["정점 배열"] --> B["정점 셰이더 · 정점마다 위치 계산"]
    B --> C["프리미티브 조립 · 정점을 도형으로 묶음"]
    C --> D["클리핑과 컬링 · 안 보이는 부분 버림"]
    D --> E["래스터화 · 도형이 덮는 픽셀 찾기"]
    E --> F["프래그먼트 셰이더 · 픽셀마다 색 계산"]

첫 단계인 정점 셰이더는 정점을 하나씩 따로 다룹니다. 이 단계에서는 아직 어느 정점이 어느 삼각형에 속하는지 모릅니다.

그다음 프리미티브 조립이 토폴로지 규칙대로 정점을 묶어 비로소 도형을 만듭니다. 도형이 생겨야 「화면 밖으로 삐져나갔나」와 「뒷면인가」를 물을 수 있습니다.

화면 밖으로 나간 부분을 잘라 내는 일이 클리핑입니다. 뒷면을 버리는 컬링도 이 무렵에 합니다. 둘 다 칠할 필요가 없는 것을 미리 덜어 뒷단계의 일을 줄입니다.

살아남은 도형은 래스터화로 넘어갑니다. 래스터화는 프리미티브 하나가 덮는 픽셀 칸을 찾는 절차입니다. 화면이 픽셀 칸으로 이뤄져 있으니 도형을 칸 단위로 바꿔야 칠할 수 있습니다.

래스터화가 찾은 칸마다 프래그먼트가 하나씩 생깁니다. 프래그먼트는 「이 픽셀에 칠할 후보」 하나입니다. 후보라고 부르는 까닭은 다른 도형에 가려 버려질 수도 있어서입니다.

마지막 프래그먼트 셰이더는 프래그먼트마다 색을 정하는 셰이더입니다. 정점에 붙어 온 색이나 텍스처 좌표를 받아 그 픽셀에 칠할 색을 계산합니다.

그래픽스 API 에서 만나는 이름

실제 코드에서는 토폴로지 규칙을 상수 하나로 고릅니다. 그리기 명령을 부를 때 이 상수를 넘깁니다. API(Application Programming Interface, 애플리케이션 프로그래밍 인터페이스)마다 이름이 조금씩 다르지만 가리키는 규칙은 같습니다.

아래 표의 OpenGL 과 Vulkan 은 GPU 에 그리기를 시키는 대표적인 API 입니다. 두 API 가 같은 규칙을 어떤 상수 이름으로 부르는지 나란히 놓았습니다.

규칙 OpenGL Vulkan
삼각형 목록 GL_TRIANGLES VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
삼각형 스트립 GL_TRIANGLE_STRIP VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
선분 목록 GL_LINES VK_PRIMITIVE_TOPOLOGY_LINE_LIST
점 목록 GL_POINTS VK_PRIMITIVE_TOPOLOGY_POINT_LIST

그래픽스 문서에서 「프리미티브 종류」나 「토폴로지」를 고르라는 인자를 보면 이 표의 규칙을 묻는 것입니다. 규칙을 고르면 종류는 따라 정해지므로 두 이름이 같은 인자를 가리킵니다.

다른 분야의 프리미티브

「프리미티브」는 영어로 「원시적인·가장 기본의」라는 뜻입니다. 그래서 그래픽스 밖에서도 더 쪼개지 않고 그 위에 다른 것을 쌓는 부품을 이렇게 부릅니다. 백엔드 개발자가 먼저 만나는 쪽은 오히려 이쪽입니다.

분야 흔히 부르는 이름 가리키는 것
프로그래밍 언어 원시 타입 정수·불리언처럼 언어가 기본으로 주는 값 타입
동시성 동기화 프리미티브 뮤텍스·세마포어처럼 스레드 사이 순서를 맞추는 기본 도구
암호학 암호 프리미티브 해시 함수·블록 암호처럼 암호 체계를 조립하는 기본 연산
그래픽스 프리미티브 점·선분·삼각형처럼 GPU 가 한 번에 칠하는 도형

네 뜻은 「기본 부품」이라는 뿌리만 같습니다. 서로 바꿔 읽을 수는 없습니다. 문서에서 이 낱말을 만나면 주변에 정점·셰이더가 나오는지, 스레드·잠금이 나오는지부터 보면 어느 뜻인지 가려집니다.

관련 항목

프리미티브를 정하는 구성 요소

정점 · 정점 속성 · 인덱스 버퍼 · 정점 버퍼 · 감김 순서 · 프리미티브 토폴로지

프리미티브의 하위 종류

점 · 선분 · 삼각형 · 패치 · 삼각형 스트립 · 삼각형 팬 · 선분 스트립

프리미티브가 거치는 처리 단계

그래픽스 파이프라인 · 정점 셰이더 · 프리미티브 조립 · 클리핑 · 컬링 · 래스터화 · 프래그먼트 · 프래그먼트 셰이더 · 테셀레이션

프리미티브를 모아 만드는 모양

메시 · 다각형 · 폴리곤 메시 · 3D 모델

프리미티브를 그리게 하는 API

OpenGL · Vulkan · Direct3D · WebGL · Metal

프리미티브가 속하는 상위 분류

그래픽스 · 렌더링 · GPU · 컴퓨터 그래픽스

같은 이름을 쓰는 다른 분야의 개념

원시 타입 · 동기화 프리미티브 · 암호 프리미티브 · 뮤텍스 · 세마포어 · 해시 함수

다른 이름: Primitive · 그래픽 프리미티브 · 기하 프리미티브 · 기본 도형