1. 앤티 에일리어싱
: 평면 사각형 텍셀을 곡면으로 사상한 결과는 더 이상 평면 사각형이 아니다. 곡면으로 바뀔 뿐만 아니라 면적도 확대되거나 축소된다. 고로, 앤티 에일리어싱이 나타날 수 있다.

정사각형에 원근 투상을 가한결과 위 그림 (b)처럼 될 수도 있다. (b)의 각 화소 중앙점이 텍스처에서 (a)의 위치에 해당하면 점 샘플링 결과는 (c)처럼 나타난다.
- 축소 관계와 확장 관계

확장 관계(Magnification)는 위 그림에서 텍셀보다 작은 크기의 텍스처가 한 화소로 매핑되는 것이고, 축소 관계(Minification)는 여러 텍셀에 걸친 텍스처가 한 화소로 매핑되는 것이다.
두가지 모두 에일리어싱이 발생할 수 있다. 확장 관계에서는 주로 양방향 선형보간을 사용해서 앤티 에일리어싱 한다.

양방향 선현보간은 위 그림처럼 텍셀 정 중앙에 있는 점을 대표 점으로 간주하고 어떤 화소의 중앙점이 (b)의 p로 매핑되었다고 하면 양반향 선형 보간을 이용해 색의 값을 결정하는것을 말한다.
양방향 선형필터는 대부분 그래픽 카드의 드라이버가 표준으로 채택하는 방법이다.
그러나 양방향 선형 필터는 단점이 있다. 실제 텍스처는 (a)에서 보듯이 텍셀 경계선을 기준으로 색 값이 급변한다. 그런데 양방향 선형 필터를 사용하면 보간으로 인해 경계션이 흐려지는 현상, 즉 블러링(Blurring)이 발생한다.
축소 관계에서는 텍스처 사각형 내부의 텍셀을 가중 평균하여 해당 화소의 색을 결정할 수 있다. 이를 계산할 때 각 텍셀의 색값의 평균을 구해서 해당 화소의 값을 결정한다. 이에 대한 계산을 미리수행해 저장함으로써 처리 속도를 높인 것이 밉 매핑(MIP Mapping, Multum in Parvo, Many Things in s Small Place)이다.
이 방법은 R, G, B별로 텍스처를 미리 저장하되, 해상도별로 평균치를 계산하여 하나의 텍스처 맵에 저장한다. 이 방법은 미리 텍스처를 저장한다는 의미에서 사전 필터링(Pre-Filtering) 이라고도 부르며, 해상도별로 여러 텍스처를 저장한다는 의미에서 다해상도 텍스처(Multi-Resolution Texture) 라고도 한다.

위 그림은 밉맵의 구성 방법을 나타낸다. 지도의 가운데를 원점으로 볼때, 오른쪽 위를 Green, 왼쪽 위를 Red, 오른쪽 아래를 Blue로 분리하여 텍스처를 그린다. 지도의 왼쪽 아래는 다시 그 자체를 4개의 상한으로 나누어 R, G, B 값을 담고 있다.
이처럼 밉맵을 저장해 높으면 바르게 앤티 에일리어싱을 할 수 있다. 경우에 따라서는 해상도에 해당하는 밉맵이 저장되어 있지 않을 수도 있다. 그럴 경우 다른 해상도의 밉맵을 보간하여 새로운 밉맵을 계산하여 사용한다.
이 경우는 새로운 밉맵을 만들기 위해 이미 1번 보간을 했고 이를 다시 양방향 선형 보간을 이용해서 픽셀 평균값을 계산해야 되기 때문에 3방향 선형 보간(Tri-Linear interpolation)이라 한다.
2. GL의 텍스터 매핑
: GL의 텍스처를 가하려면 5가지의 작업이 필요하다. 이들 각가에 대해 알아보자>
1) 텍스처 기능 활성화(Enable Texturing)
: GL의 텍스처 기능을 활성화 하려면 glEnable(GL_TEXTURE_2D) 함수를 호출하고, 비활성화 하려면 glDisable(GL_TEXTURE_2D)를 호출한다.
void glEnable(GLenum mode);
void glDisable(GLenum mode);
GL은 1, 2, 3 차원 텍스처를 모두 지원한다. 1차원 텍스처는 선으로 등고선을 그려내는 데 사용할 수 있으며, 3차원 텍스처는 이후 설명할 부피 가시화(Volume Rendering)에 주로 사용된다.
2) 텍스처 영상 명시(Specify Texture Images)
: 텍스처 영상은 배열 형태로 메인 메모리에 로드해야 한다.
Glubyte MyTexture[width][height][3];
이처럼 배열로 표현된 영상을 텍스처 영상으로 사용하기 위해서는 다음 함수를 호출해야 한다.
void glTexImage2d(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texture);
여기서 파라미터 target은 GL_TEXTURE_1D, GL_TEXTURE_2D 등의 텍스처 타입을 의미한다.
파라미터 level은 텍스처의 밉맵 레벨로, 사용하지 않을 경우에는 0으로 설정한다.
파라미터 width, height는 텍셀 단위로 텍스처 폭과 높이를 나타낸다.
파라미터 border는 윤곽선 두께를 몇 텍셀로 할 것인지를 의미한다. 이 윤곽선은 주어진 텍스처를 둘러싸는 선이다.
파라미터 internalformat은 텍셀을 기술하는 데 사용된 요소를 의미하는 것으로, 아래 표와 같다.

위에 나열한 내부 형식을 포함하여 GL이 지원하는 텍셀 형식은 모두 38개다.
예를들어 GL_R3_G3_B2는 Red, Green에 3, Blue에 2 비트를 할애한 텍셀을 말한다.
파라미터 format, type은 텍스처 영상의 데이터 포맷, 타입을 나타낸다.

특수한 경우를 제외하고는 format은 internalformat과 동일한 것을 사용하면 된다.
함수 호출 예는 다음과 같다.
glTexImage(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSiGNED_BYTE, MyTexture);

위 그림은 래스터 변환을 전후한 GL 파이프라인을 나타낸 것이다.
프로세서 메모리에 있는 영상은 필요한 용량을 줄이기 위해 압축되어 저장된다. 따라서 이 영상에 압축풀기가 가해지고, 이어서 필요한 화소 연산이 가해진다. 이처럼 변환된 영상은 래스터 변환 프로세서로 직접 입력되기도 하지만 텍스처 메모리에 저장되었다가 래스터 변환 프로세서에 입력되기도 한다.
glTextImage2D() 함수는 위 그림 청색 화살표로 표시된다. 프로세서 메모리에 저장되어 있던 텍스처를 텍스처 메모리(Texture Memory, Texture Buffer)로 이동시키는 함수다. 텍스처 메모리 역시 프레임 버퍼처럼 별도로 할당된 메모리 공간으로, GL_READ_BUFFER 라는 상수로 표시된다.
현재의 텍스처 모두 또는 일부를 변경하려면 glTexSubImage2D() 함수를 호출하는 것이 유리하다. 이 함수에 의해 기존에 할당된 텍스처 메모리 내용을 변경할 수 있고, 이렇게 함으로써 glTexImage2D()가 새로운 텍스처 메모리를 할당하는 데 소요되는 시간을 줄일 수 있다.
이 함수는 주로 텍스처 무비를 만드는 데 사용된다. 이는 물체는 그대로 있고, 물체 표면의 텍스처만 계속 바꿈으로써 애니메이션 효과를 주기 위한 것이다.
GL의 파이프라인에서는 위 그림의 적색 화살표를 따라 프레임 버퍼 내용을 텍스처 메모리로 전달할 수도 있다. 즉, 현재 화면에 보이는 그림을 텍스처로 사용할 수도 있다.
이를 위해 다음 함수를 사용한다.
void glCopyTexImage2D(GLenum targe, GLint level, GLint format, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
이 함수에서 x, y, width, height를 제외한 나머지 파라미터는 glTexImage2D() 함수의 정의와 동일하다. 만약 일부의 화소 사각형(Pixel Rectangle)만을 텍스처로 사용하려면 (x, y)로 사각형 좌하단의 좌표를 잡고 width, height로 크기를 잡으면 된다, 반드시 2^n 형태로 표시되어야 한다.
*2차원 그림 파일을 텍스처로 사용하기 위해서는 해당 파일을 배열 형태로 표시해야 한다. 그러나 대부분의 그림 파일이 다양한 형태로 표시되고, 또 압축된 형태이기 때문에 해당 파일로부터 화소 값만 직접 읽어들이기가 쉽지 않다. 이 경우 유틸리티 프로그램을 사용하여 GL의 배열 형태로 변환해야 한다.
3) 텍스처 매핑 방법 할당(Assign Texture Mapping)
: GL의 텍스처 매핑에는 자동 매핑과 수동 매핑(Manual Texture Generation)이 있다.
1- 수동 매핑
: 물체 다각형 정점마다 이에 상응하는 텍스처 좌표를 프로그래머가 직접 입력해야 한다.
glBegin(GL_POLYGON);
glNormal3f(0.0, 0.0, 1.0);
glTexCoord2f(0.2, 0.8); // 텍스처 정점 a를
glVertex3f(7.5, 10.5, 0.0); // 물체 정점 A에 할당
glNormal3f(0.0, 0.0, 1.0);
glTexCoord2f(0.4, 0.2); // 텍스처 정점 b를
glVertex3f(0.0, 3.8, 0.0); // 물체 정점 B에 할당
glNormal3f(0.0, 0.0, 1.0);
glTexCoord2f(0.8, 0.4); // 텍스처 정점 C를
glVertex3f(12.0, 0.0, 0.0); // 물체 정점 C에 할당
glEnd();
glNormal3f()는 정점 수직 벡터를 의미한다. 이는 조명에 필요한데, 조명에 의한 물체색과 텍스처에 의한 물체색을 혼합할 필요가 있을 때를 대비한다. 만약 온전히 텍스처만 입히려면 조명이 필요 없으므로 생략할 수 있다.
2- 자동 텍스처 매핑
: GL의 텍스처 좌표는 동차 좌표(s, t, r, q)로 표시된다. 동차 좌표의 정의애 의해 만약 3차원 텍스처 좌표라면 이 값은 (s/q, t/q, r/q)를 의미한다. 기본값은 q = 1.0이다 .만약 2차원 텍스처 좌표라면 r=0.0이고 r값은 사용되지 않음을 의미한다.
따라서 glTexCoord1() 함수를 호출하면 (s, 0.0, 0.0, 1.0), glTexCoord2() 함수를 호출하면 (s, t, 0.0, 1.0), glTexCoord3() 함수를 호출하면 (s, t, r, 1.0), glTexCoord4() 함수를 호출하면 (s, t, r, q) 형식으로 텍스처 좌표가 표시된다.
여기서 4차원 텍스처는 q 값의 변화에 의해 s, t, r값을 조절할 수 있음을 의미한다. 예를들어, 맨 위에[그림 11-37] 처럼 텍스처 자체에 원근변환을 가해야 할 경우 q값을 조절함으로써 가능하다.
원근에 따른 텍스처 보정(Perspective Correction)을 가하려면 다음 함수를 호출해야 한다.
void glHint(GLenum target, GLenum hint);
두 번째 파라미터인 hint는 GL_DONT_CARE, GL_NICEST, GL_FASTEST 등의 값이 들어갈 수 있다. 일반적으로 3차원 깊이 정보를 감안하여 원근에 따를 선형보간을 가하려면 GL_NICEST를 선택하고, 2차원 화면 좌표계에서 선형보간을 가하려면 GL_FASTEST를 선택한다.
GL_DONT_CARE는 두 가지 방법 모두 좋다는 뜻이다. 이러한 hint는 그래픽 드라이버에 따라 서로 다르게 해석되며, 경우에 따라서는 전혀 무시되기도 한다.
자동 매핑(Automatic Texture Generation)을 사용하면 물체 내부의 모든 정점마다 텍스처 좌표가 자동으로 할당된다. 이후 다각형 내부의 텍스처 좌표는 보간에 의해 할당된다.
자동 매핑을 위해서는 다음 함수를 호출해야 한다.
void glTexGen{ifd}[v](GLenum coord, GLenum pname, TYPE param);

위 표에서 텍스처 생성 모드(GL_TEXTURE_GEN_MODE)를 보면 GL의 텍스처 매핑 방법은 3가지다.

자동 매핑방법에서 GL의 텍스처 좌표는 기준 평면(Reference Plane)과 물체면 정점 간의 거리에 의해 할당된다.

위 코드에서 기준평면은 [1, 0, 0, 0] 이다.
이 말은 평면의 식 Ax + By + Cz + D에서 A, B, C, D의 값이 [1, 0, 0, 0] 이라는 뜻이다.
이 경우 평면에 수직인 법선 벡터는 (A, B, C) 이기 때문에 [1, 0, 0]이 평면에 수직인 벡터가 되므로 평면은 y축과 z축이 이루는 평면에 나란한 평면이라는 얘기다.
D는 원점과 평면 간의 거리와 관련된 계수로, (A, B, C)가 단위 벡터라면 D는 원점과 평면 간의 거리다. 이 경우 (1, 0, 0)이 X축의 단위 벡터이기 때문에 D는 원점과 평명간의 거리이고, 이 값이 0이기 때문에 이 평면은 원점을 통과하는 평면이다.
평면과 점사이의 거리는 평면의 법선벡터가 단위 벡터이고 원점과 평면의 거리를 나타내는 D값이 0이니까 법선벡터를 N이라고 놓고 점이 P면 N 내적 P의 값으로 구할 수 있다. (N이 단위벡터일때 N 내적 P는 P벡터의 N방향 크기를 나타낸다. D값이 있으면 D를 단순히 더해주면 된다.)
* 내적의 활용
http://ifyouwanna.tistory.com/entry/%EB%82%B4%EC%A0%81%EC%9D%98-%ED%99%9C%EC%9A%A9
GL_OBJECT_LINEAR
: 물체 정점과 기준 평면 모두 모델 좌표계를 기준으로 정의된다. 이 경우 평면과 물체간의 상대적인 위치가 고정되기 때문에 시점을 바꿔도 평면과 물체가 모두 동일한 모델 뷰 변환을 겪게 되고, 물체면에 매핑된 텍스처는 변하지 않는다. 즉, 텍스처를 물체면 위에 씌워 고정시킨 것과 같은 효과를 보인다.
GL_EYE_LINEAR
: 물체 정점과 기준 평면 모두 시점 좌표계를 기준으로 정의된다. 그러나 이 방법에서는 기준 평면을 다시 원래의 모델 좌표로 되돌린다. 즉, 물체에 모델 뷰 변환이 가해진 이후의 좌표다. 모델 변환에 의해 물체에 기하변환을 가하거나 뷰 변환에 의해 시점을 움직이면 모델 뷰 행렬이 바뀌고, 물체 정점의 위치도 바뀐다. 그러나 기준 평면에는 이러한 변환이 적용되지 않는다. 모델 뷰 행렬의 역 행렬을 곱해줌으로써 기준 평면을 이전의 모델 좌표계로 되돌려 버렸기 때문이다.
결과적으로 물체를 움직이면 기준 평면은 고정되고, 물체만 움직이게 된다. 이 경우 물체가 움직일 때마자 기준 평면과 물체와의 거리가 달라지므로 텍스처 패턴이 달라진다.
텍스처 행렬 스택(Texture Matrix Stack)을 사용할 수 있다. 이 스택은 최소 2개 이상의 행렬로 구성되며, 모델 뷰 행렬과 마찬가지로 스택 톱에 있는 행렬이 최종적으로 곱해지는 행렬이다.
* 텍스처 패턴의 기하 변환
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glRotatef(45, 0.0, 0.0, 1.0);
glTranslatef(0.5, 0.0, 0.0);
glMatrixMode(GL_ModelView);
glMatrixMode는 행렬 모드는 텍스트 행렬 모드로 바꾼다.
GL_SPHERE_MAP
: 주면 매핑을 위한 것이다.
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
위 코드는 물체 주변을 둘러싼 원구의 모습이 물체 표면에 맺히도록 텍스처 좌표 (s, t)를 할당한 것이다.
이 경우 텍스처 매핑은 GL에 의해 자동으로 이루어진다. 따라서 프로그래머는 주변 매핑을 위한 텍스처만 제시하면 된다.
4) 텍스처 파라미터 명시(Specify Texture Parameters)
: GL의 텍스처 파라미터는 크게 주어진 텍스처를 어떻게 확장할 것인지를 결정하는 파라미터와, 주어진 화소의 텍스처를 어떻게 계산할 것인지를 결정하는 파라미터로 구분할 수 있다.
파라미터를 할당하기 위한 GL 함수는 다음과 같다.
void glTexParameter{if} (GLenum target, GLenum pname, TYPE param);
아래 표는 이 함수의 파라미터를 나타낸 것이다.

target은 텍스처가 2D인지 3D인지 나타낸다.
pname은 2종류로 대별된다. GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T는 텍스처를 s, t 방향으로 어떻게 확장할 것인지 결정한다. 일명 래핑(wrapping)이라고 한다.
1- 래핑(wrapping)
: 텍스처를 s, t방향으로 어떻게 확장할 것인지 결정(GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T)
GL_REPEAT

(a)의를 3배로 반복확장하여 (b)로 만듦. [0, 1]에서 정의된 텍스처를 [0. 3] 으로 만들어 준것이다.
GL_REPEAT가 명시되면 GL은 glTexCoordf2() 함수의 파라미터를 인식하는 방법을 달리한다. 예를들어, glTexCoordf2(2.5, 2.5)를 glTexCoordf2(0.5, 0.5)로 해석한다.
GL_CLAMP

확장 영역이 경계선의 색으로 고정(clamping) 된다.
2- 해당 화소의 텍스처 선택 방법 결정
GL_TEXTURE_MAG_FILTER
: 확장관계를 말한다. 확장관계에 사용할 수 있는 필터는 2가지다.
- GL_NEAREST : 점 샘플링에 해당.
- GL_LINEAR : 양방향 선형 보간으로써, 인접한 4개의 텍셀을 보간.
GL_TEXTURE_MIN_FILTER
: 축소관계를 말한다. 축소관계에 사용할 수 있는 위 두가지 방법 이외에 4가지 필터가 더 있다.
- GL_LINEAR_MIPMAP_NEAREST : 주어진 해상도에 가장 가까운 밉맵(MIPMAP_NEAREST)을 선택한 후 양방향 선형보간을 가하는 방법.
- GL_NEAREST_MIPMAP_NEAREST : MIPMAP_NEAREST 에서 다시 점 샘플링을 가하는 방법.
- GL_LINEAR_MIPMAP_LINEAR: 밉맵 사이를 보간하여 새로운 밉맵(MIPMAP_LINEAR)을 만든 후 양방향 선형보간을 가하는 방법, 이는 3방향 선형보간에 해당함.
- GL_NEAREST_MIPMAP_LINEAR: 밉맵 사이를 보간하여 새로운 밉맵을 만든 후 점 샘플링을 가하는 방법.
* 밉맵을 생성하기 위해서는 GLU 함수 또는 GL함수를 사용해야 한다. GLU를 사용해야 할 경우에는 다음과 같이 GLU의 밉맵 생성기 함수를 호출해야 한다.
GLint gluBuild2DMipmas(GLenum target, GLint internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *texture);
5) 텍스처 환경 명시(Specify Texture Environment)
: 텍스처를 물체면에 그대로 입힐 수도 있지만 물체색과 조합할 수도 있다. GL에서 이러한 기능을 수행하는 함수가 glTexEnv*()로 텍스처 환경을 명시하는 함수라고 불린다.
void glTexEnv{if} (GLenum target, GLenum pname, GLenum TYPEparm)

첫 파라미터 target은 반드시 GL_TEXTURE_ENV로 해야한다.
파라미터 pname을 GL_TEXTURE_ENV_MODE로 하면 텍스처의 색과 물체면의 색을 어떻게 조합할 것인지를 명시할 수 있다.
GL_TEXURE_ENV_COLOR는 GL_TEXTURE_ENV_MODE의 TYPEparm이 GL_BLEND 일때만 사용할 수 있다. 즉, GL_TEXTURE_ENV_MODE에서 GL_BLEND를 호출했을 때는 이후 glTexEnv*() 함수에서 pname을 GL_TEXTURE_ENV_COLOR로 놓고 TYPEparm에 RGBA 값을 지니 매열명을 명시해야 한다.

텍스처 표현 방식은 glTexImage*D() 함수의 두번째 파라미터인 internalformat에 의해 설정되는데 이 값이 GL_RGB, GL_RGBA 경우일 때에 따라 각각의 계산방식을 표현한것이 위 표이다.
기본적으로 GL_REPLACE는 기존 물체면의 색을 텍스처의 색으로 대체하는 것이고, GL_MODULATE는 물체면의 색과 텍스처의 색을 곱하는 것이다. GL_DECAL, GL_BLEND는 물체면 위에 텍스처 색을 덧칠하는 효과를 주기 위한 것이다.
위 표에서 C(t)는 텍스처의 색이고, C(f)는 프레그먼트의 색, 즉 물체면의 색이다. 같은 규칙으로 A는 각각의 알파값을 나타낸다.
GL_BLEND에서 C(c)는 GL_TEXTURE_ENV_COLOR에 의해 명시된 색을 의미한다.
6) 텍스처 객체
: 텍스처를 적용하려면 CPU 메모리로부터 텍스처 메모리로 텍스처를 로드해야 한다. 텍스처 역시 하나의 상태 변수이고 GL 버전 1.0 에서는 이 상태 변수 하나를 공유해서 사용했기 때문에 텍스처 대상을 바꿀때 마다 텍스처 상태 변수 내용을 변경하고 텍스처를 텍스처 메모리로 올리는 작업을 매번 실행해야 했다.
이러한 단점을 개선하기 위해서 GL 1.1 부터는 텍스터 객체(Texture Object) 개념이 도입되었다.
즉, 텍스처와 해당 텍스처에 적용되는 파라미터 값을 묶어서 하나의 텍스처 객체를 정의할 수 있다.
여기서 파라미터는 해당 텍스처와 관련된 함수 호출에 의해 설정된 값을 의미한다.
또한 GL 1.1 부터는 물체마다 개별적인 텍스처 객체를 정의할 수 있으먀, 이를 위해 텍스처 메모리에는 동시에 여러 개의 텍스처를 저장할 수 있게 되었다.
GLubyte MyTextureA[8][8][3]; // 텍스처 영상 A
GLubyte MyTextureB[64][64][3]; // 텍스처 영상 B
GLuint ObjectId[2]; 2개의 텍스처 객체명을 저장하기 위한 공간, glGenTextures()에 의해 할당 됨.
glGenTextures(2, ObjectId)
glBindTexture(GL_TEXTURE_2D, ObjectId[0]); // 실제 텍스처를 표현할 객체를 생성하고 여기에 객체명을 할당한다.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_FLOAT, MyTextureA);
glTexParameteri(.....);
glTexEnvf(....);
glBindTexture(GL_TEXTURE_2D, ObjectId[1]); Object[1]을 위한 텍스처 객체 생성 및 객체명 할당.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_FLOAT, MyTextureB);
glTexParameteri(.....);
glTexEnvf(....);
....
glBindTexture(GL_TEXTURE_2D, ObjectId[0]); // ObjectId[0]이 활성화되고, 그 아래 원구를 그리는데 활용된다.
glutSolidSphere(1.0, 16, 16);
glBindTexture(GL_TEXTURE_2D, ObjectId[1]); // ObjectId[1]이 활성화되고, 그 아래 주전자를 그리는데 활용된다.
glutSolidTeapot(1.0);