정점을 처리하는 단계를 지난 정점은 레스터라이제시션 단계로 넘어갑니다.
우선 정점들은 삼각형으로 묶여있는데 이 시점부터는 하나의 독자적 도형으로 처리가 됩니다.
우선 화면에 그려질 2차원 삼각형의 세 정점이 결정되면 다음과 같은 일이 일어납니다.
- 이 삼각형이 포함하는 모든 픽셀마다 Pixel Shader(fragment shader)가 실행된다.
- 삼각형의 세 정점에 할당 되었던 여러 데이터(pos, uv, normal, color)가 보간되어 삼각형 내부에 각 픽셀셰이더로 넘어옵니다.
DirectX에서 이러한 일련의 과정을 레스터라이제이션이라고 부르고 고정 파이프라인 단계로 프로그래머가 이러한 로직들을 임의 바꿀수 없는 파이프라인 단계이다. 자체 알고리즘으로 알아서 동작을 합니다.
[레스터라이제이션 알고리즘]
자체 알고리즘(레스터라이제이션 알고리즘)에 대해 알아보겠습니다.
// rasterization algorithm
for(each triangle in scene) {
// Step 1 : 삼각형의 세 꼭지점을 투사
Vec2f v0 = perspectiveProject(triangle[i].v0);
Vec2f v0 = perspectiveProject(triangle[i].v1);
Vec2f v0 = perspectiveProject(triangle[i].v2);
for(each pixel in image) { // canvas의 모든 pixel에 대해
// Step 2 : 이 pixel(x,y)이 삼각형안에 있는지 확인
if(pixelContainedIn2DTriangle(v0, v1, v2, x, y)) {
image(x,y = triangle[i].color;
}
}
}
삼각형이 포함하는 모든 픽셀마다 Pixel Shader가 실행된다고 했는데, 모든 픽셀에 대해 다 체크하면 시간이 너무 오래 걸립니다.
이 경우에 Bounding Box를 이용한 최적화가 일어납니다.
Bounding Box 는 세 꼭지점의 투사 점에 대한 최소값과 최대값을 구해서 박스의 범위를 설정합니다.
특정 픽셀이 삼각형의 내부에 있는지 외부에 있는지 확인하는 방법은 pixelContainedIn2DTriangle() 에서 일어납니다.
Edge() 함수를 사용해서 알아낼 수 있습니다.
Edge() 함수는 삼각형의 두 점 사이의 선분을 기준으로 왼쪽이면 -, 오른쪽이면 +를 반환하는 함수입니다.
만약 삼각형을 이루는 3개의 선분에 대해 Edge() 함수가 모두 + 를 반환하면 해당 포인트는 삼각형의 안에 있습니다.
Edge() 함수는 2차원 포인트 P를 v0(시작점), v1(끝점)으로 이루어진 선분을 테스트하는 함수입니다.
(v1-v0) 벡터와 (p-v0) 벡터의 외적(cross product)의 부호를 확인하는 함수입니다.
E(P) > 0 => 선의 오른쪽에 점이 존재
E(P) = 0 => 정확히 선 위에 점이 존재
E(P) < 0 => 선의 왼쪽에 점이 존재
이제 삼각형을 이루는 3개의 선분(edge)를 구하는 방법을 알아야 합니다.
단순하게 점과 점을 빼면 될 거 같지만 순서가 중요합니다.
위와 같이 CW의 경우에는 삼각형 내부가 양수, CCW의 경우에는 삼각형 내부가 음수가 되기 떄문입니다.
삼각형 내부의 점의 좌표와 속성을 구할때는 Barycentric Coordinates 를 사용하면 됩니다.
[대표적인 레스터라이제이션의 역할]
- 클리핑
- 원근 나눗셈(perpective division)
- 뒷면 제거(backface culling)
- 스캔 변환(ndc scan transform)
- 뷰포트 변환
<클리핑>
클리핑은 투영변환 이후의 클립공간 볼륨 바깥에 놓인 폴리곤들을 잘라내는 작업을 말합니다.
<원근 나눗셈>
현재 단계에서 투영변환을 통해 원근법이 적용된 3차원 물체들을 직육면체 클리핑 공간에서 정의되어 있습니다.
3차원에서 2차원으로 차원을 줄이면 됩니다. 바로 Z좌표로 모든 성분을 나눠버리면 됩니다.
투영변환을 마친 정점데이터는 (x, y, z, w = z 값 저장)에서 원근 나눗셈이 적용 된 이후에는 (x, y, z, w) -> (x, y, z) 의 좌표계로 변환되는데 이를 NDC(normailize device coordinate) 공간이라고 부릅니다.
여기서 정규화라는 이름이 붙는 이유는 이 좌표의 xy 범위는 [-1 ~ 1] z의 범위는 [0~1]이기 때문입니다.
<뒷면 제거>
카메라가 바라보고 있는 방향에 물체에 가려진 면적은 굳이 연산을 할 필요가 없습니. 외적(Cross product) 삼각형의 바라보고있는 면의 방향을 구하여 뒷면일 경우에 연산을 하지 않습니다.
<뷰포트 변환>
컴퓨터 화면상의 윈도우 스크린 공간을 갖는데 이 스크린 공간 내에 2차원 이미지가 그려질 뷰포트가 정의되는데 NDC공간의 물체들을 스크린 공간으로 이전시키는변환을 뷰포트 변환이라고 합니다.
<스캔 변환>
이전의 변환들은 자세한 사항을 몰라도 프로그래밍하는데 문제가 없었지만 이 스캔 변환은 렌더링 프로그램에서 직접적인 영향을 미치기 떄문에 꽤 중요합니다. 삼각형 하나가 내부에 차지하는 모든픽셀(fragment)들을 생성하는 작업이고, 이때 정점데이터에 들어온 데이터들은 보간(선형 보간)되어서 픽셀셰이더로 넘어갑니다.
'DirectX 11' 카테고리의 다른 글
DirectX 11 - Ouput merger (0) | 2024.05.31 |
---|---|
DirectX 11 - Fragment Shader(Pixel Shader) (1) | 2024.05.31 |
DirectX 11 - Geometry Shader (0) | 2024.05.31 |
DirectX 11 - Tesselator (0) | 2024.05.31 |
DirectX 11 - Vertex Shader (2) | 2024.05.31 |