OpenGL Shader – 3

Vertex Processor

버텍스 프로세서는 버텍스 쉐이더를 실행한다. 버텍스 쉐이더의 입력은 버텍스 데이터로써, 주로 버텍스의 위치, 색, 법선벡터 등으로써 OpenGL 어플리케이션이 보내준다.

다음 OpenGL 코드는 버텍스 프로세서에게 각 버텍스에 대한 색상, 위치 값을 전달해준다.

glBegin(...);
    glColor3f(0.2,0.4,0.6);
    glVertex3f(-1.0,1.0,2.0);

    glColor3f(0.2,0.4,0.8);
    glVertex3f(1.0,-1.0,2.0);
glEnd();

버텍스 쉐이더에서 다음과 같은 일을 할 수 있다.

  • 모델뷰 행렬과 프로젝션 행렬을 이용해서 버텍스의 위치를 이동
  • 노말 벡터의 변환, 그리고 필요하다면 노말 벡터의 정규화
  • 텍스쳐 좌표 생성과 변환
  • 버텍스에 대한 빛 또는 픽셀에 대한 빛 계산
  • 색상 계산

위의 모든 연산을 수행할 필요는 없다. 그러나 일단 버텍스 쉐이더를 만들었다면 버텍스 프로세서의 전체 기능을 버텍스 쉐이더가 대신하며, 따라서 법선 변환을 수행할 수 없고 고정 기능이 텍스쳐 좌표 생성을 수행하도록 할 수 없다. 버텍스 쉐이더가 사용될때 파이프 라인의 이 단계의 필요한 모든 기능을 버텍스 쉐이더가 대신하게 된다.

이전에서 설명했던 것처럼, 버텍스 쉐이더는 버텍스간 연결성 고려에 대한 정보를 가지고 있지 않다. 그러므로 위상 데이터를 필요로 하는 연산은 버텍스 쉐이더에서 수행할 수 없다. 예를들어서, 버텍스 쉐이더가 뒷면 제외를 할 수 없는데, 버텍스 쉐이더는 버텍스 단위 연산이지 버텍스가 이루고 있는 면에 대한 연산을 할 수 없기 때문이다. 면을 알려면 버텍스간의 연결 정보를 알아야 한다. 이러한 연결정보가 바로 위상 데이터의 하나이다. 버텍스 프로세서는 개별적인 버텍스 하나 하나를 처리 하는 순간에 그 하나 이외의 나머지 버텍스를 알지 못한다.

버텍스 쉐이더는 최소한 gl_Position 이라는 변수를 변경해야만 한는데, 이 변수는 보통 모델뷰 행렬과 프로젝션 행렬을 이용한 변환이다.

버텍스 프로세서는 OpenGL 상태에 접근할 수 있어서, 예를 들어 빛을 포함하고 재질을 사용하는 연산을 수행할 수 있다. 또한 텍스쳐에 대한 정보도 접근할 수 있는데 이것은 최신 그래픽 카드에서만 허용한다. 하지만 프레임 버퍼에는 접근할 수 없다.

OpenGL Shader – 2

다음 그림은 매우 단순화된 파이프라인 다이어그램이며 데이터가 어떤 식으로 파이프 라인을 타는지를 보여준다. 매우 단순화시켰지만 쉐이더 프로그래밍에 대한 중요한 개념을 제공하고 있다. 이 부분에서는 파이프라인의 고정 기능을 제공한다. 파이프라인은 추상적이며 모든 각 단계에서 어떤 특정한 구현과 만날 필요가 없다는 점을 주의하기 바란다.
Vertex Transformation

여기에서 버텍스는 공간상의 위치, 색상, 노말벡터, 텍스쳐 좌표 등과 같은 속성들의 집합이다. 이 단계에서의 입력값들은 하나 하나의 버텍스 속성들이다. 이 고정 기능에 의해 수행되는 연산은 다음과 같다.

  • 버텍스의 위치 변환
  • 버텍스에 대한 광원 계산
  • 텍스쳐 좌표의 생성 및 변환

Primitive Assembly and Rasterization

이 단계에서의 입력값은 변환된 버텍스와 연결 정보이다. 연결정보라는 것은 버텍스들이 Primitive(삼각형 등과같은 기본 요소)를 이루기 위해 어떻게 연결되느냐이다. 이 단계에서 Primitive가 생성된다. 또한 이 단계는 뒷면제거나 뷰 절두체에 대한 클리핑 연산을 담당할 수 있다.

라스터라이징은 Fragment를 결정하고 Primitive의 픽셀 위치를 결정한다. 이 문맥에서 Fragment는 특정한 위치에서 프레임 버퍼의 픽셀을 변경하기 위해 사용될 데이터의 조각이다. 쉽게 말하자면 Primitive가 화면에 실제 렌더링될때 그려질 Pixel 값이다. Fragment는 색 뿐만이 아니라 수직벡터값과 텍스쳐 좌표 등과 같은 값들인데, 이러한 값들을 이용해서 실제로 화면상에 찍힐 픽셀의 새로운 색상을 계산하는데 쓰인다.

이 단계에서의 출력값은 다음과 같다.

  • 프레임버퍼 안의 Fragment들의 위치
  • 버텍스 변환 단계에서 계산된 속성에 대한 각 Framgment에 대한 보간된 값

버텍스 변환 단계에서 계산된 값은 버텍스 연결정보와 함께 조합되어 Fragment를 위한 알맞은 속성을 계산하는데 사용된다. 예를들어서 각 버텍스는 변환된 위치를 가지고 있다. 버텍스가 Primitive로 만들어지는데 사용될때 Primitive의 Fragment의 위치를 계산하는것이 가능하다. 또 다른 예는 색상의 사용이다. 만약 삼각형을 구성하는 각 버텍스가 각기 다른 색상을 가지고 있다면, 삼각형 안의 Fragment 색상은 각 버텍스의 상대적인 거리에의한 가중치를 받아 색상값들이 보간되어져 얻어진다.

Fragment Texturing and Coloring

이 단계에서의 입력값은 보간되어진 Fragment의 정보이다. 색상은 이미 이전 단계에서 보간을 통해 계산되어졌고, 이 단계에서는 텍셀(Texel, Texture element)값 결합과 같은 연산이 수행된다. 텍스쳐 좌표는 이전단계에서 보건되어진다. 안개도 역시 이 단계에서 적용된다. 고통적인 최종 출력값은 Fragment의 색상값과 깊이 값이다.

Raster Operations

이 단계에서의 입력값은 다음과 같다.

  • 픽셀의 위치
  • Fragment의 색상값과 깊이값

Fragment에 대해 수행되는 파이프라인의 마지막 연속 단계는 주로 다음과 같다.

  • Scissor Test
  • Alpha Test
  • Stencil Test
  • Depth Test

만약 테스트가 성공한다면, Fragment 정보는 현재의 블렌딩 모드에 따라 픽셀의 값을 변경하는데 사용된다.  블렌딩은 이 단계에서만 수행되는데, Fragment 텍스쳐링과 컬링 단계에서는 프레임 버퍼에 접근하지 못하기 때문이다. 프레임 버퍼는 오직 이 단계에서만 접근할 수 있다.

고정 기능에 대한 간단한 그림 설명

다음 그림은 위에서 설명한 각 단계에 대한 설명을 그림으로 다시 풀어높은 것이다.


Replacing Fixed Functionality

현재의 그래픽 카드는 프로그래머가 위에서 기술된 단계 중에 2개를 새롭게 정의할 수 있게 해준다.

  • 버텍스 쉐이더는 Vertex Transformation 단계를 작성하는데 사용된다.
  • 프레그먼트(Fragment) 쉐이더는 프레그먼트 텍스쳐링과 컬러링 단계의 고정 기능을 교체하는데 사용된다.

다음 섹션에서는 프로그래밍 가능한 단계, 즉 버텍스 처리기와 프레그먼트 처리기에 대해 설명할 것이다.