1.24k likes | 1.47k Views
텍 스 처 매 핑. 텍스처 매핑. 살펴보기와 예제 텍스처의 명시화 필터링 텍스처 오브젝트 텍스처 함수들 텍스처 좌표의 지정 텍스처 좌표 자동으로 산출하기 진보된 특색. 텍스처 매핑의 단계. 텍스처 오브젝트를 만들고 , 오브젝트에 해당 텍스처를 명시 텍스처가 각각의 픽셀과 어떻게 연관되어 있는지 표현 텍스처 매핑을 활성화 텍스처와 기하학적 좌표가 제공된 장면을 그린다 . 텍스처 매핑은 RGBA 모드에서만 가능. 용어.
E N D
텍스처 매핑 살펴보기와 예제 텍스처의 명시화 필터링 텍스처 오브젝트 텍스처 함수들 텍스처 좌표의 지정 텍스처 좌표 자동으로 산출하기 진보된 특색
텍스처 매핑의 단계 • 텍스처 오브젝트를 만들고, 오브젝트에 해당 텍스처를 명시 • 텍스처가 각각의 픽셀과 어떻게 연관되어 있는지 표현 • 텍스처 매핑을 활성화 • 텍스처와 기하학적 좌표가 제공된 장면을 그린다. • 텍스처 매핑은 RGBA 모드에서만 가능
용어 • 텍스처: 데이터(컬러, 명도, 컬러와 알파 데이터)들의 사각형 배열 • 텍셀(texel): 텍스처 배열 각각의 값을 텍셀이라고 함 • 테셀레이션(tessellation): 폴리곤의 각 꼭지점을 명시하면 자동으로 폴리곤을 오목한 부분이 없도록 쪼개서 연출해주는 기능 • 밉맵: 기하학적 프리미티브에 사용할 텍스처에서 소스 텍스처맵의 해상도와 윈도우의 해상도가 다를 경우에 텍스처를 사용하기 위해서 해상도를 줄여놓은 텍스처 맵의 버전
텍스처 매핑의 단계 • (1) 텍스처 오브젝트를 만들고, 오브젝트에 대한 텍스처 명시하기 • 텍스처는 이미지들 처럼 2차원적인 것이 아니라 1차원도 될 수 있고, 3차원도 될 수 있다. • 텍스처를 묘사하는 데이터는 한 개, 두 개, 세 개, 혹은 네 개의 각 텍셀에 대한 원소들로 구성 • R, G, B, A 의 4개 부분으로 구성된 조절 상수 • 예제 9-1 • 하나의 텍스처 오브젝트가 하나의 텍스처를 유지하기 위해 사용
(2) 텍스처가 각 픽셀에 적용되는 방법 지정하기 • 프레그먼트 컬러와 이미지 데이터로부터 마지막 RGBA값을 계산할 때 4가지 함수 사용 • 단순히 텍스처 컬러를 최종 컬러로 사용하는 방법(대체모드)과 • 텍스처를 프레그먼트 컬러의 변조나 스케일에 사용하는 방법이 있다. • 텍스처를 조명효과와 결합할 때 유용
(3) 텍스처 매핑의 활성화 • 장면을 그리기 전에 텍스처링 활성화가 필요 • GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D 상수를 사용하여 활성화 하거나 비활성화 할 수 있음 • (4) 텍스처와 기하학적 좌표가 제공된 장면 그리기 • 텍스처가 어떻게 상대적으로 프레그먼트에 정렬되는지를 지시 • 즉 장면에 오브젝트를 나타내듯이 텍스처 좌표와 기하학적 좌표를 명시해야 함
예제 9-1 텍스처 맵이 적용된 체크판: checker.c #include <GL/glut.h> #include <stdlib.h> #include <stdio.h> /* Create checkerboard texture */ #define checkImageWidth 64 #define checkImageHeight 64 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; #ifdef GL_VERSION_1_1 static GLuint texName; #endif
void makeCheckImage(void) { int i, j, c; for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = ((((i&0x8)==0)^((j&0x8))==0))*255; checkImage[i][j][0] = (GLubyte) c; checkImage[i][j][1] = (GLubyte) c; checkImage[i][j][2] = (GLubyte) c; checkImage[i][j][3] = (GLubyte) 255; } } }
void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); makeCheckImage(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef GL_VERSION_1_1 glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_2D, texName); #endif
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #ifdef GL_VERSION_1_1 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); #else glTexImage2D(GL_TEXTURE_2D, 0, 4, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); #endif }
void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); #ifdef GL_VERSION_1_1 glBindTexture(GL_TEXTURE_2D, texName); #endif glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(-2.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(0.0, 1.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f(0.0, -1.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(2.41421, 1.0, -1.41421); glTexCoord2f(1.0, 0.0); glVertex3f(2.41421, -1.0, -1.41421); glEnd(); glFlush(); glDisable(GL_TEXTURE_2D); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -3.6); } void keyboard (unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; default: break; } }
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(250, 250); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; }
예제 프로그램 설명: checker.c • 체크판은 makeCheckImage() 로 만들어짐 • init()에서 텍스처매핑 초기화 • glGenTextures()와 glBindTexture()로 텍스처 만들고 이름을 짓는다. • glTexImage2D()에 의해 하나의 최대 텍스처 맵이 명시화됨. 변수가 크기, 타입, 위치, 텍스처 이미지 특징을 나타냄. • glTexParameter*()는 텍스처가 어떻게 덧씌워졌는지, 텍셀끼리 혹은 픽셀들끼리 매치가 안될 경우 어떻게 컬러를 채울지를 명시화 • display()에서 glEnable()에 의해 텍스처링 시작 • glTexEnv*()는 GL_REPLACE 에 그리기 모드 설정 • 현재의 텍스처링 함수 설정: GL_DECAL, GL_REPLACE, GL_MODULATE, GL_BLEND • glTexCoord*()는 일반적인 텍스처 좌표를 설정
텍스처의 명시화 • glTextImage2D()는 2차원 텍스처 이미지를 정의 • 1차원 glTextImage1D(), 3차원 glTextImage3D() • void glTextImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texels); • target 상수는 GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D의 집합 • (참고) 텍스처프록시는 OpenGL 실행환경이 특정 텍스처크기에 대해 특정 텍스처 포맷을 지원하고 있는지를 알아볼 수 있도록 함. • level: 해상도 제공시 사용. 해상도가 하나인 경우(밉맵을 사용하지 않을 경우) level은 0 • internalFormat: 이미지 텍셀을 묘사하는 R, G, B, A 구성요소들 또는 루미넌스나 밀도값. 1부터 4의 값. 혹은 38개의 심볼상수의 정수값 • GL_ALPHA, GL_ALPHA4, GL_LUMINANCE4, GL_RGB4 등 • width, height 은 텍스처 이미지의 차원(폭과 높이) 제공. 최소 64x64. 2m+2b (m은 음수가 아닌 수, b는 border 값)공식에 맞아야 함.
border는 0(테두리가 없음)이나 1(테두리 사용)로서 테두리의 폭을 나타냄. • format, type: 텍스처 이미지 데이터의 포맷과 데이터 타입을 나타냄 • format: GL_COLOR_INDEX, GL_RGB, GL_GREEN, GL_BLUE, GL_ALPHA, … • type: GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, … • texels: 텍스처 이미지 데이터
테두리를 포함하지 않는 텍스처의 높이와 너비의 여러 개의 텍셀들은 2의 거듭제곱의 수. 이 조건에 맞는 차원이 아니라면gluScaleImage() 사용하여 텍스처의 크기를 변화시킴 • Int gluScaleImage(GLenum format, GLint widthin, GLint heightin, GLenum typein, const void *datain, GLint widthout, GLint heightout, GLenum typeout, void *dataout); • datain으로 부터 데이터를 풀기 위해 적당한 픽셀 저장모드를 이용, 이미지를 스케일 • 결과 이미지는 GL_PACK* 저장모드를 이용하여 dataout에 쓰인다.
glCopyTexImage2D()는 프레임버퍼로부터 픽셀 사각형을 read, 그 사각형을 새로운 텍스처에 텍셀처럼 사용 • void glCopyTexImage2D(GLenum target, GLint level, GLint internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); • 텍셀들을 정의하기 위해 프레임 버퍼 데이터를 사용하여 2차원 텍스처를 만듬. • target 변수는 상수 GL_TEXTURE_2D로 설정되어야 함 • 텍스처 배열은 스크린 픽셀 (x, y) 좌표의 왼쪽 아래 사각형으로 시작하여 만들어짐 • width/height 는 픽셀의 사각형을 명시, 둘 다 2m+2b 의 형태 • m은 음이 아닌 정수, b는 border 값
텍스처 프록시 • OpenGL 실행 환경이 특정 텍스처 크기에 대해 특정 텍스처 포맷을 지원하고 있는지를 알아볼 수 있도록 특별히 텍스처 프록시(proxy) 제공 • OpenGL의 요청을 위한 프록시 사용을 위해 GL_PROXY_TEXTURE_2D 의 target 변수와 주어진 level, internalFormat, width, height, border, format, type을 가지는 glTexImage2D()를 호출 • 프록시를 위해 텍셀 배열을 위한 포인터로서 NULL값을 넘겨야 함 • 사용자의 텍스처에 충분한 리소스가 있는지 알아보기 위해 텍스처 프록시가 생성된 다음 glGetTexLevelParameter*()를 이용, 텍스처 상태변수를 요청 • void glGetTextLevelParameter{if}v(GLenum target, GLint level, GLenum pname, TYPE *params);
예제 9-2 텍스처 프록시 • 텍스처 프록시로 텍스처 리소스 요청하기 GLInt width; glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, 64, 64, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
텍스처 이미지의 전체 또는 부분 재배치 • 현재 존재하는 2차원 텍스처 이미지의 연속하는 하위 부분(subregion)의 전체 혹은 일부분을 대체하는 2차원 텍스처 이미지 정의 • void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *texels); • target 변수는 GL_TEXTURE_2D로 설정 • level: 밉맵 LOD(level-of-detail) • width/height: 현재 텍스처 이미지의 전체 혹은 부분을 대체하는 하위 부분의 차원 • xoffset/yoffset: x-, y- 방향의 텍셀 오프셋. 부분 이미지가 존재하는 위치
예제9-3 텍스처 서브 이미지 교체: texsub.c #include <GL/glut.h> #include <stdlib.h> #include <stdio.h> #ifdef GL_VERSION_1_1 #define checkImageWidth 64 #define checkImageHeight 64 #define subImageWidth 16 #define subImageHeight 16 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; static GLubyte subImage[subImageHeight][subImageWidth][4]; static GLuint texName;
void makeCheckImages(void) { int i, j, c; for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = (((i&0x8)==0)^((j&0x8)==0))*255; //정정 checkImage[i][j][0] = (GLubyte) c; checkImage[i][j][1] = (GLubyte) c; checkImage[i][j][2] = (GLubyte) c; checkImage[i][j][3] = (GLubyte) 255; } }
for (i = 0; i < subImageHeight; i++) { for (j = 0; j < subImageWidth; j++) { c = (((i&0x4)==0)^((j&0x4)==0))*255; //정정 subImage[i][j][0] = (GLubyte) c; subImage[i][j][1] = (GLubyte) 0; subImage[i][j][2] = (GLubyte) 0; subImage[i][j][3] = (GLubyte) 255; } } } void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST);
makeCheckImages(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_2D, texName); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); }
void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(-2.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(0.0, 1.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f(0.0, -1.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(2.41421, 1.0, -1.41421); glTexCoord2f(1.0, 0.0); glVertex3f(2.41421, -1.0, -1.41421); glEnd(); glFlush(); glDisable(GL_TEXTURE_2D); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -3.6); } void keyboard (unsigned char key, int x, int y){ switch (key) { case 's': case 'S': glBindTexture(GL_TEXTURE_2D, texName); glTexSubImage2D(GL_TEXTURE_2D, 0, 12, 44, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glutPostRedisplay(); break;
case 'r': case 'R': glBindTexture(GL_TEXTURE_2D, texName); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); glutPostRedisplay(); break; case 27: exit(0); break; default: break; } }
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(250, 250); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; }
#else int main(int argc, char** argv) { fprintf (stderr, "This program demonstrates a feature which is not in OpenGL Version 1.0.\n"); fprintf (stderr, "If your implementation of OpenGL Version 1.0 has the right extensions,\n"); fprintf (stderr, "you may be able to modify this program to make it run.\n"); return 0; } #endif
glCopyTexSubImage2D()는 프레임버퍼로 부터 픽셀의 사각형을 읽고, 존재하는 텍스처 배열의 부분을 바꿈 • void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,GLsizei width, GLsizei height); • 현존하는 2차원 텍스처 이미지의 연속적인 하위 부분의 전체 또는 부분을 대체하기 위해 프레임 버퍼의 이미지 자료 사용 • target 변수는 GL_TEXTURE_2D로 설정 • level은 세부숫자의 밉맵 레벨, xoffset,yoffset은 x,y방향의 텍셀 offset을 지정
1차원 텍스처 • 하나의 1차원 텍스처를 만들기 위해 glTexImage1D() 사용 • 한 방향으로 변화되는 텍스처 끈 모양의 그릴 때 높이가 1이고 꼭대기와 밑을 따라 테두리가 없는 1차원 텍스처 작성 • void glTexImage1D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *texels); • texels은 1차원 배열, width 값은 2m (만약 경계가 있으면 2m + 2)
1차원 텍스처의 전체 또는 일부 텍셀을 대체하기 위하여 glTexSubImage1D()를 사용 • void glTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type,const GLvoid *texels); • 현존하는 1차원 텍스처 이미지의 연속적인 하위 부분의 전체 또는 부분을 대체하는 1차원 텍스처 배열을 정의 • level, format, type 변수는 glTexImage1D()에서 사용하는 것과 같음
프레임버퍼를 새로운 1차원 텍스처의 소스나 기존의 1차원 텍스처 대체용으로 사용하기 위하여 glCopyTexImage1D()나 glCopyTexSubImage1()를 사용 • void glCopyTexImage1D(GLenum target, GLint level, GLint internalFormat, GLint x, GLint y, GLsizei width,GLint border); • 텍셀을 정의하기 위하여 프레임버퍼 자료를 이용, 1차원 텍스처를 만든다. • target은 GL_TEXTURE_1D상수로 설정되어야 함 • width: 이 행에 있는 픽셀의 수 지정. 값은 2m(경계가 있는 경우는 2m+2)
void glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); • 현존하는 1차원 텍스처 이미지의 연속적인 하위부분 전체 또는 부분을 대체하기 위해 프레임버퍼의 이미지 자료를 사용 • target 변수는 GL_TEXTURE_1D로 설정 • level: 세부 숫자의 밉맵 레벨 • xoffset: 텍셀 offset 지정
3차원 텍스처 실행 안됨 • 3차원 텍스처는 의학, 지구과학의 응용프로그램의 제작에 많이 사용됨 • 의학용 프로그램 : 단층촬영(CT), 자기공명 영상법(MRI)이미지를 나타내는데 사용 • 볼륨 렌더링 중 일부분 • 3차원 텍스처 이미지는 2차원 부분 이미지 사각형 층으로 생각 • 메모리에서 사각형은 수열로 나열 • 3차원 텍스처를 만들기 위해 glTexImage3D()사용
void glTexImage3D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *texels) • 3차원 텍스처 정의 • 모든 변수는 glTexImage2D() 와 같은 의미로 사용되나 텍셀은 3차원 배열이고 depth 변수가 추가. Depth 값은 2m(테두리가 있을 경우엔 2m+1) • 사용자는 밉맵과 프록시를 공급할 수 있으며, 동일한 필터링 옵션이 가능
3차원 텍스처의 전체 또는 부분을 대체하려면 glTexSubImage3D()를 사용 • void glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *texels); • 현존하는 3차원 텍스처 이미지를 대체하는 3차원 텍스처 배열을 정의 • target 변수는 GL_TEXTURE_3D로 해야 함 • level, format, type : glTexImage3D() 에서 사용된 것과 같다.
3차원 텍스처의 부분을 대체하는 소스로서 프레임버퍼를 사용하기 위해 glCopyTexSubImage3D()를 사용 • void glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height); • 현존하는 3차원 텍스처 이미지의 연속적인 하위 부분을 대체하기 위해, 프레임 버퍼의 이미지 자료를 사용 • target 변수는 GL_TEXTURE_3D 사용
3차원 텍스처의 픽셀 저장 모드 • 픽셀 저장값은 각 층의 행간 간격을 조절 • glPixelStore*()는 픽셀이나 텍셀 자료의 전체 사각형의 부분 사각형이 참조를 조절하는 매개변수를 사용하는 픽셀 저장모드를 설정함 • *ROW_LENGTH, *ALIGNMENT, *SKIP_PIXELS, *SKIP_ROWS(*는 GL_UNPACK_ 또는 GL_PACK_ 이다) • 3차원 텍스처 이미지 자료의 서브 볼륨을 참조하기 위해선 추가된 픽셀 저장 모드가 필요 • *IMAGE_HEIGHT,*SKIP_IMAGES 등 • 새로운 변수들은 서브 볼륨의 한계를 정하고 실행하기 위해 glTexImage3D(), glSubImage3D(), glGetTexImage() 루틴을 승인
만약 메모리에 있는 3차원 텍스처가 정의된 서브 볼륨보다 크다면 사용자는 *IMAGE_HEIGHT변수를 이용하여 하나의 부분 이미지 높이를 지정 • 서브 볼륨이 최초의 층에서 시작하지 않는다면 *SKIP_IMAGES 매개변수가 설정
*IMAGE_HEIGHT 픽셀 저장 모드 Subimage In layer 1 *ROW_LENGTH *IMAGE_ HEIGHT Subimage In layer 0 Height *SKIP_PIXELS layer1 *SKIP_ROWS layer0
세부 항목의 다중 레벨 • 텍스처 오브젝트는 시점에서 거리가 변화함에 따라 투영된 이미지 크기와 마찬가지로 크기가 감소하여야 한다. 텍스처 맵을 오브젝트로의 매핑에 적합한 크기로 필터링해야 함. => 밉맵 사용(필터 처리된 텍스처 맵의 정도 지정) • 밉매핑을 사용할 때 OpenGL은 자동적으로 매핑될 오브젝트의 크기에 기초한 텍스처의 사용을 설정 • 밉매핑을 사용하기 위해서는 맵의 크기가 가장 큰 것부터 1 * 1 크기의 맵까지 2의 지수승으로 표현할 수 있는 텍스처를 만들어 주어야 함 • 사용자의 최고 해상도 맵이 64x16 이라면, 사용자는 32x8, 16x4, 8x2, 4x1, 2x1, 1x1 크기의 맵을 제공하여야 함 • 이 텍스처들을 지정하기 위해 텍스처 맵의 분석이 이루어질 때 level, width, height,image 매개변수들의 다른 값을 가지고 있는 glTexImage2D()를 한번 호출
예제9-5 밉맵 텍스처: mipmap.c #include <GL/glut.h> #include <stdlib.h> GLubyte mipmapImage32[32][32][4]; GLubyte mipmapImage16[16][16][4]; GLubyte mipmapImage8[8][8][4]; GLubyte mipmapImage4[4][4][4]; GLubyte mipmapImage2[2][2][4]; GLubyte mipmapImage1[1][1][4]; #ifdef GL_VERSION_1_1 static GLuint texName; #endif
void makeImages(void) { int i, j; for (i = 0; i < 32; i++) { for (j = 0; j < 32; j++) { mipmapImage32[i][j][0] = 255; mipmapImage32[i][j][1] = 255; mipmapImage32[i][j][2] = 0; mipmapImage32[i][j][3] = 255; } }