그래픽스 파이프라인

MoOrY·2022년 12월 20일
0

그래픽스

목록 보기
1/1

렌더링 파이프라인:

오브젝트를 화면에 표현하기 위한 일련의 작업들

셰이더:

화면에 색을 칠하는 프로그램. 원래 그림자(shading) 계산목적이였다.
단순하고 병렬적으로 계산가능한 작업들을 gpu에서 계산할 수 있었는데 이를 쉐이더라고 함

렌더링 파이프라인의 일부를 유연하게 변경하는 프로그램
렌더링 파이프라인의 중간 파이프를 교체하는것이라 이해할 수 있다.

버텍스 셰이더:

버텍스(꼭지점)와 관련된 연산을 한다. 위치, 색, uv정보 등..
주어진 꼭지점(정점)에 대해서 대응되는 화면상의 정점을 출력하는 함수이자 프로그램
3D상의 위치를 2D 화면상의 위치로 변환한다.

프래그먼트 셰이더:

칠할 색을 결정
색을 결정하여 색을 채워넣는 역할을 한다고 생각할 수 있다.

쉐이더는 gpu의 병렬연결 구조를 사용한다.
화면에 3개의 점을 출력해야 한다면 한번에 한개의 점을 출력하는 함수 3개를 동시에 처리한다.

그래픽 API 초기화와 드로우 콜

그래픽스 API 초기화

렌더링 파이프라인을 구성할 수 있도록 먼저 그래픽스API에서 어떤 처리를 먼저 시작해야 한다.
먼저 그래픽스 api를 초기화해야 한다.
이 처리는 gpu에게 명령을 전달할 수 있는 수단을 만들고, 사용할 쉐이더를 셋업하는 단계이다.
대부분의 과정이 cpu에서 실행하게 된다.

1. GPU 디바이스 생성

현재 기기의 gpu를 표현하는 오브젝트
커맨드 큐로부터 커맨드를 받아들여 실행한다. 그래픽카드 그 자체

2. 커맨드 큐 생성

GPU에게 전달할 명령을 쌓아두는 곳이다.
한번만 생성, 하나만 존재하며 GPU디바이스로 이어진다. DX12에서부터 여러개 생성가능

커맨드 큐가 존재하는 이유는 CPU와 GPU가 직접통신을 하지 않기 때문(CPU와 GPU의 실행시간 차이로 인해)
CPU가 커맨드 큐에 커맨드 버퍼라는 것을 쌓게된다.(실행을 예약) 커맨드 버퍼는 각각의 커맨드들을 쌓아둔것.

커맨드들이 GPU에서 처리되기 시작하면, 처리에 필요한 데이터들을 ram에서 vram으로 복사하게 된다.
커맨드큐에 쌓인 커멘드 버퍼들은 먼저 쌓인 순서대로 하드웨어 언어로 번역되어 GPU에 전달된다.

3. 렌더링 파이프라인 상태 생성

렌더링 파이프라인의 상태를 표현하며 렌더링 파이프라인에서 사용할 속성들을 가진다.
여러개 생성 가능하다
여러개 생성하므로써 서로다른 오브젝트에 서로 다른 쉐이더를 적용 가능하다.

렌더링 파이프라인 상태 안에는 렌더링 파이프라인 서술자가 존재하는데,
이는 렌더링 파이프라인이 어떤식으로 동작할지 묘사하는 오브젝트이다.
정점서술자, 버텍스셰이더, 프래그먼트 셰이더 등이 포함된다.

정점 서술자
정점의 구성을 묘사하며 정점을 조립할 때 사용한다.

이후 사용할 데이터들을 메모리에 로드한다. ram에서 vram으로 전송될 데이터들이다.(모델, 텍스처 등)

정점
위치는 정점의 속성 중 하나이며 컬러,노말,텍스처 좌표 등의 다른 여러 속성들을 가지고 있다.
이를 정점속성이라 한다.
이 정점 속성들은 셰이더 안에서는 구조체로 다루지만
이것이 커맨드를 통해 gpu로 전달될땐 스트림 형태의 버퍼로 전달된다.
데이터의 앞뒤 구분이나 구조화된 단위 없이 그냥 일렬로 gpu로 들어온다.
(데이터의 종류에 따라 두개 이상의 스트림으로 쪼개서 보낼 수도 있다)
이후 정점 조립단계에서 정점 서술자에 의해 다시 구조체 형태로 구조화하게 된다.

드로우 콜 생성

드로우 콜이란 오브젝트를 한번 그리는데 필요한 명령들의 묶음이다
커맨드 버퍼에 GPU에 전달할 명령을 추가 = 커맨드 버퍼에 커맨드 버퍼에 커맨드들을 생성하여 추가

정점 조립

정점 버퍼들의 요소들을 정점 구조체로 조립
(gpu에 전달된 스트림 형태의 데이터를 다시 정점 구조체 형태로 만든다)

버텍스 셰이더

정점을 입력받아 다른 형태의 정점으로 변환
3D 공간 상의 정점위치를 클립 공간으로 옮기는 것을 투영이라 한다.
정점의 위치를 옮기기 위해 변환행렬을 사용한다.
이러한 변환 행렬은 모델행렬, 뷰행렬, 투영 행렬을 거치게 된다.

모델(월드)행렬:

오브젝트 공간(모델공간) * 모델행렬 -> 월드 공간
모델행렬을 거치기 전의 정점들은 오브젝트(모델)공간에 위치하게 된다.
이 공간은 스스로가 세상의 중심이며 3D모델의 피봇이 곧 원점이다.
모든 정점의 위치는 피봇에서 얼마나 떨어져 있냐로 결정되게 된다.

이 오브젝트 공간에 위치한 정점에 모델행렬을 곱하면 월드 공간 안의 월드 기준의 정점 위치로 변환이 된다.
즉 모델행렬의 역할은 오브젝트의 정점들을 월드 상의 위치로 옮기는것이다.

뷰 행렬:

월드공간 * 뷰 행렬 -> 카메라 공간

월드 상의 정점들을 카메라에 상대적인 위치로 옮기는 역할이다.
카메라의 위치와 방향이 세상의 중심인 공간을 카메라 공간이라고 한다.

같은 위치에 있는 물건도 카메라의 위치에 따라 다르게 보이므로 필요한 처리이다.
매번 카메라의 위치와 회전을 고려하는 것보다 카메라는 원점에 두고 오브젝트를 상대적으로 배치하는것이 간결하다.
월드상에 존재하는 정점에 뷰 행렬을 곱해주면 카메라 공간상의 위치로 변환된다.

화면 추려내기

폴리곤은 전면, 후면 두개의 면을 가지고 있는데, 일반적으로 후면은 절대 보여지지 않는다.
물체의 내부에 카메라를 넣는것이 허용되지 않기 때문

폴리곤의 후면을 볼 수 있는 경우에는 후면 추려내기가 작동하지 않는다.
카메라의 전면을 향하고 있는 폴리곤을 전면폴리곤, 후면을 향하고 있는 폴리곤을 후면폴리곤이라 하는데,
카메라에 보여지지 않는 후면 폴리곤을 추려냄으로써 성능의 이득을 보며
이 작업을 화면 추려내기라고 한다.

direct3D에서는 두르기 순서의 시계방향에(뷰 공간에서) 지정된 버텍스를 가진 폴리곤을 전면 폴리곤으로 취급하며
시계 반대방향에 지정된 버텍스를 가진 폴리곤을 후면폴리곤으로 취급한다.
어떤 폴리곤이 후면 폴리곤인지 확인하는 방법이다.

조명

광원은 월드공간에 정의되지만 뷰 공간 변환에 의해 뷰 공간으로 변환된다.
물체에 명암을 추가하여 장면에 사실감을 더해준다.

투영 행렬:

카메라 공간 * 투영행렬 -> 클립공간

카메라 공간에 위치한 정점카메라 시야에 위치한 정점으로 변환해준다.(화면 기준)
카메라 좌표계의 정점들을 클립 공간으로 옮기게 된다.

클립공간은 카메라가 보는 영역이며, 카메라의 시점을 반영하므로 시야와 원근감이 존재하게 된다.
카메라가 보는 영역(뷰포트)를 직육면체로 압축한 공간이며
x,y의 범위는 -1~1이며 z범위는 0~1이다.

클립 공간 외부의 폴리곤들은 NDC로 변환되는 과정에서 잘려나가 성능을 아낄 수 있으며,
이를 클리핑이라 한다.

NDC
정규화된 기기 좌표계
이며, 공간의 모든 xyz범위가 -1~1또는 0~1로 정규화된 좌표계를 뜻한다.
NDC는 클립 공간 외부의 좌표를 잘라내고,
동차좌표계(4차원)을 "w나누기"를 실행하여 3차원으로 변환하여 생성된다

클립공간과 NDC는 사실상 서로 같은 모습(뷰포트를 221 직육면체로 줄인 공간)이지만,
클립공간은 계산 편의를 위해 4차원 동차좌표계에 존재하고,
NDC는 클리핑 실행 후 원래 의도된 3차원 공간으로 변환된 것이다


NearClip보다 가까이 위치한 것
Far Clip보다 먼 곳에 위치한 좌표들을 잘라낸다.
피라미드의 머리부분을 잘라낸 모습이라 Frustum이라 부른다.


원근감이 존재하지 않는 직교카메라의 경우 직육면체 형태를 띄게 된다.


원근감이 있든 없든 카메라가 보는 시야공간을 정규화를 통해 직육면체 형태로 찌부러뜨리게 된다.
이때 x와 y는 -1~1사이의 값을 가지고, -1과 1은 각각 화면의 끝을 의미한다.
z는 0~1사이의 값을 가지는데, 이는 깊이을 표현한다.(카메라와 떨어진 위치)

far clip에 가까운 단면이 더 많이 쪼그라들고,
near clip에 가까운 단면이 덜 쪼그라들게 되어 원근감이 표현된다.
(멀리 있는 물체는 작게 보이고 가까이 있는 물체는 크게 보이니까)

정리:
오브젝트 공간 -> (모델행렬) -> 월드공간 -> (뷰 행렬)
-> 카메라 공간 -> (투영행렬) -> 클립공간 -> (클리핑, w나누기) -> NDC

래스터라이저

전달받은 정점들로 삼각형을 만들고,
그 삼각형을 채우는 프래그먼트를 만들어 프래그먼트 셰이더에 넘겨준다.

뷰포트변환

NDC -> 스크린 공간
221 크기의 직육면체에 있던 정점들을
스크린(윈도우 화면)에 대응되는 스크린 공간으로 옮겨준다. = 창의 해상도에 맞춰진다.

스크린의 크기가 500*500이라면 좌측상단이 0,0 우측하단이 500,500으로 맞춰진다.
단 Z는 0에서 1까지의 거리로 유지된다.

스캔변환

프리미티브(원시적인 도형)을 이루는 프래그먼트 생성
정점으로 이루어진 프리미티브를 채우는 프래그먼트를 생성한다.(소묘법을 위한 준비과정)
프래그먼트는 픽셀 후보라고 생각하면 된다.
현재 생성된 프래그먼트가 다른 프래그먼트와 경쟁하여 채용되지 못하고 탈락할 수 있다

보간

정점들의 값을 보간하여 프래그먼트의 속성 값들을 결정

초록색 정점과 파란색 정점 사이의 색은 선형보간으로 그 값이 결정된다.

래스터라이즈는 정점 컬러 이외에도 UV좌표, 노말 등 다른 정점 속성들도 보간한다.

프래그먼트 쉐이더

전달받은 프래그먼트에 어떤 색을 채울지 결정한다. 래스터라이저가 전달한 프래그먼트 수만큼 실행한다.
프래그먼트 쉐이더의 출력값은 프레임 버퍼에 쓰여질 컬러값과 깊이값(z)가 된다.

출력 병합

알파값과 깊이값을 통해 프래그먼트는 프레임 버퍼에 같은 위치의 픽셀과 경쟁하여
색을 정하거나 합침(두 도형이 겹친다면 깊이값으로 정함)

profile
필기용 블로그입니다.

0개의 댓글