OpenGL에서는 모든 것이 3D 공간에 있지만, 화면이나 창은 픽셀의 2D배열이므로 OpenGL 작업의 대부분은 모든 3D 좌표를 화면에 맞는 2D 픽셀로 변환하는 것입니다. 3D좌표를 2D 픽셀로 변환하는 프로세스는 OpenGL의 그래픽 파이프라인에서 관리합니다. 그래픽 파이프 라인은 크게 두 부분으로 나눌 수 있습니다. 첫 번째 부분은 3D좌표를 2D 좌표로 변환하고 두번째 부분은 2D좌표를 실제 색상 픽셀로 변환합니다. 이 장에서는 그래픽 파이프 라인에 대해 간략하게 설명하고 이를 사용하여 멋진 픽셀을 만드는 방법에 대해 설명합니다.
그래픽 파이프라인은 3D좌표 세트를 입력으로 받아, 이를 화면의 컬러 2D픽셀로 변환합니다. 그래픽파이프라인은 각 단계에서 이전 단계의 출력을 입력으로 요구하는 여러 단계로 나눌 수 있습니다. 이 모든 단계는 고도로 전문화 되어 있으며 (하나의 특정 기능이 있음) 병렬로 쉽게 실행할 수 있습니다. 병렬 특성으로 인해 오늘날의 그래픽카드에는 그래픽 파이프라인 내에서 데이터를 빠르게 처리할 수 있는 수천개의 작은 처리 코어가 있습니다. 프로세싱 코어는 파이프 라인의 각 단계에 대해 GPU에서 작은 프로그램을 실행합니다. 이러한 작은 프로그램을 셰이더라고 합니다.
이러한 셰이더 중 일부는 개발자가 구성할 수 있으므로 기존 기본 셰이더를 대체 할 자체 셰이더를 작성할 수 있었습니다. 이를 통해 파이프라인의 특정 부분을 훨씬 더 세밀하게 제어 할 수 있으며 GPU에서 실행하기 때문에 귀중한 CPU시간도 절약 할 수 있습니다.셰이더는 OpenGL 셰이딩 언어 (GLSL)로 작성되었으며 다음 장에서 더 자세히 살펴보겠습니다.
아래에서 그래픽파이프라인의 모든 단계에 대한 추상적인 표현을 찾을 수 있습니다. 파란색 섹션은 자체 셰이더를 삽입할 수 있는 섹션을 나타냅니다.
보시다시피 그래픽 파이프라인에는 버텍스 데이터를 완전한 렌더링 된 픽셀로 처리하기 위해 특정 부분을 각각 처리하는 많은 섹션이 포함되어 있습니다. 파이프라인의 각 부분을 단순화 된 방식으로 간략하게 설명하여 파이프 라인 작동 방식에 대한 좋은 예시를 보여드리겠습니다.
그래픽 파이프라인에 대한 입력으로 우리는 여기서 Vertex Data
라는 배열에서 삼각형을 형성해야 하는 3개의 3D좌표 목록을 전달합니다. 이 Vertex Data
는 버텍스들의 모음입니다. 버텍스는 3D 좌표 당 데이터 집합입니다. 이 버텍스의 데이터는 우리가 원하는 모든 데이터를 포함 할 수 있는 버텍스 속성(Vertex Attribute)을 사용 사용하여 표현되지만, 단순성을 위해 각 버텍스는 3D 위치와 일부 색상 값으로만 구성되어있다고 가정하겠습니다.
OpenGL이 좌표 및 색상 값 모음을 어떻게 만들지 알기 위해서는 OpenGL은 데이터로 어떤 종류의 렌더 유형을 형성 할 것인지 힌트를 요구합니다. 데이터가 점 집합, 삼각형 집합 또는 하나의 긴 선으로 렌더링 되길 원하시나요? 이러한 힌트를 프리미티브라고 하며 그리기 명령을 호출하는 동안 OpenGL에 제공됩니다. 히러한 힌트 중 하나가 GL_POINTS
, GL_TRIANGLES
및 GL_LINE_STRIP
입니다.
파이프라인의 첫 번째 부분은 단일 버텍스를 입력으로 받는 버텍스 셰이더입니다. 버텍스 셰이더의 주요 목적은 3D좌표를 다른 3D좌표를 변환하는 것이며(나중에 자세한 설명함) 버텍스 셰이더를 사용하면 버텍스 속성에 대한 몇 가지 기본 처리를 수행할 수 있습니다.
프리미티브 어셈블리 단계는 프리미티브를 형성하는 버텍스 셰이더에서 모든 버텍스 (또는 GL_POINTS
가 선택된 경우 버텍스)을 입력으로 취하고 주어진 프리미티브 모양의 모든 점을 조립합니다. 이번 예제에서는 삼각형을 생성합니다.
그런 다음 지오메트리 셰이더의 출력은 rasterization 단계로 전달되어 결과 프리미티브(들)를 최종 화면의 해당 픽셀에 매핑하여 프레그먼트 셰이더에 매핑하여 프레그먼트 셰이더가 사용할 프레그먼트를 만듭니다. 프레그먼트 셰이더가 실행되기 전에 클리핑이 수행됩니다. 클리핑은 뷰 외부에 있는 모든 조각을 삭제하여 성능을 향상시킵니다.
OpenGL의 프레그먼트는 OpenGL이 단일 픽셀을 렌더링하는 데 필요한 모든 데이터입니다.
프레그먼트 셰이더의 주요 목적은 픽셀의 최종 색상을 계산하는 것이며 일반적으로 모든 고급 OpenGL 효과가 발생하는 단계입니다. 일반적으로 프래그먼트 셰이더에는 최종 픽셀 색상 (예: 조명, 그림자, 조명 색상 등)을 계산하는 데 사용할 수 있는 3D 장면에 대한 데이터가 포함됩니다.
모든 해당 색상 값이 결정되면 최종 객체는 알파 테스트 및 블렌딩 단계라고 하는 한 단계를 더 통과합니다. 이 단계는 프레그먼트의 해당 깊이 (그리고 스텐실) 값 (나중에 얻을 것임) 을 확인하고 이를 사용하여 결과 프레그먼트가 다른 개체의 앞 또는 뒤에 있는지 확인하고 그에 따라 폐기해야 합니다. 스테이지는 또한 알파 값( 알파값은 개체의 불투명도를 나타냅니다.)을 확인하고 그에 따라 개체를 블렌딩(혼합)합니다. 따라서 픽셀 출력 색상이 프래그먼트 셰이더에서 계산 되더라도 여러 삼각형을 렌더링 할 때 최종 픽샐 섹상은 완전히 다를 수 있습니다.
보시다시피 그래픽파이프라인은 전체가 매우 복잡하고 구성 가능한 부분이 많이 포함되어 있습니다. 그러나 거의 모든 경우에 대해 버텍스 및 프레그먼트 셰이더로만 작업하면 됩니다. 지오메트리 셰이더는 선택 사항이며 일반적으로 기본 셰이더로 남아 있습니다. 여기에 설명하지 않은 테셀레이션 단계와 변환 피드백 루프도 있지만 이건 나중에 설명하겠습니다.
최신 OpenGL에서는 최소한 우리 자신의 버텍스 및 프레그먼트 셰이더를 반드시 정의해야 합니다. (GPU에는 기본 버텍스 / 프레그먼트 셰이더가 없습니다.) 이러한 이유로 첫 번째 삼각형을 렌더링하기 전에 많은 지식이 필요하기 때문에 최신 OpenGL 학습을 시작하기가 매우 어렵습니다. 이 장의 끝에서 마침내 삼각형을 렌더링하면 그래픽 프로그래밍에 대해 더 많이 알게 될 것입니다.
무언가를 그리기를 시작하기 위해선 먼저 OpenGL에게 버텍스 데이터를 입력해야 합니다. OpenGL은 그래픽라이브러리이므로 OpenGL에서 지정하는 모든 좌표는 3D입니다. (x
, y
그리고 z
좌표계) OpenGL은 모든 3D 좌표계를 너의 스크린에 맞는 2D 픽셀로 간단하게 변환되지 않습니다. OpenGL은 오직 3축을(x
, y
그리고 z
) -1.0
에서 1.0
사이의 범위에만 있을때 진행합니다. 모든 좌표계는 정규화된 기기 좌표 범위에만 너의 화면에 보입니다. (그 밖에 있는 부분은 보이지 않습니다.) 하나의 삼각형을 렌더링하기 위해 3D 좌표를 가지고있는 각각의 버텍스들을 변환해야합니다. 우리는 정규화된 장치 좌표를 float
배열로 정의하겠습니다.
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
OpenGL은 3D 공간에서 작동하므로 우리가 렌더링하는 2D 삼각형은 각각 버텍스들의 z
좌표는 0.0
을 가집니다. 이렇게 하면 삼각형의 깊이가 같아지므로 2D같이 보이게 됩니다.