Download presentation
Presentation is loading. Please wait.
1
텍 스 처 매 핑
2
텍스처 매핑 살펴보기와 예제 텍스처의 명시화 필터링 텍스처 오브젝트 텍스처 함수들 텍스처 좌표의 지정
텍스처 좌표 자동으로 산출하기 진보된 특색 2010-2학기 가상현실
3
텍스처 매핑의 단계 텍스처 오브젝트를 만들고, 오브젝트에 해당 텍스처를 명시
텍스처가 각각의 픽셀과 어떻게 연관되어 있는지 표현 텍스처 매핑을 활성화 텍스처와 기하학적 좌표가 제공된 장면을 그린다. 텍스처 매핑은 RGBA 모드에서만 가능 2010-2학기 가상현실
4
용어 텍스처: 데이터(컬러, 명도, 컬러와 알파 데이터)들의 사각형 배열
텍셀(texel): 텍스처 배열 각각의 값을 텍셀이라고 함 테셀레이션(tessellation): 폴리곤의 각 꼭지점을 명시하면 자동으로 폴리곤을 오목한 부분이 없도록 쪼개서 연출해주는 기능 밉맵: 기하학적 프리미티브에 사용할 텍스처에서 소스 텍스처맵의 해상도와 윈도우의 해상도가 다를 경우에 텍스처를 사용하기 위해서 해상도를 줄여놓은 텍스처 맵의 버전 2010-2학기 가상현실
5
텍스처 매핑의 단계 (1) 텍스처 오브젝트를 만들고, 오브젝트에 대한 텍스처 명시하기
텍스처는 이미지들 처럼 2차원적인 것이 아니라 1차원도 될 수 있고, 3차원도 될 수 있다. 텍스처를 묘사하는 데이터는 한 개, 두 개, 세 개, 혹은 네 개의 각 텍셀에 대한 원소들로 구성 R, G, B, A 의 4개 부분으로 구성된 조절 상수 예제 9-1 하나의 텍스처 오브젝트가 하나의 텍스처를 유지하기 위해 사용 2010-2학기 가상현실
6
(2) 텍스처가 각 픽셀에 적용되는 방법 지정하기
프레그먼트 컬러와 이미지 데이터로부터 마지막 RGBA값을 계산할 때 4가지 함수 사용 단순히 텍스처 컬러를 최종 컬러로 사용하는 방법(대체모드)과 텍스처를 프레그먼트 컬러의 변조나 스케일에 사용하는 방법이 있다. 텍스처를 조명효과와 결합할 때 유용 2010-2학기 가상현실
7
GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D 상수를 사용하여 활성화 하거나 비활성화 할 수 있음
(3) 텍스처 매핑의 활성화 장면을 그리기 전에 텍스처링 활성화가 필요 GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D 상수를 사용하여 활성화 하거나 비활성화 할 수 있음 (4) 텍스처와 기하학적 좌표가 제공된 장면 그리기 텍스처가 어떻게 상대적으로 프레그먼트에 정렬되는지를 지시 즉 장면에 오브젝트를 나타내듯이 텍스처 좌표와 기하학적 좌표를 명시해야 함 2010-2학기 가상현실
8
예제 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 2010-2학기 가상현실
9
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; } 2010-2학기 가상현실
10
glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); makeCheckImage();
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 2010-2학기 가상현실
11
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, #endif } 2010-2학기 가상현실
12
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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); 2010-2학기 가상현실
13
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0);
glEnd(); glFlush(); glDisable(GL_TEXTURE_2D); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); 2010-2학기 가상현실
14
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: 2010-2학기 가상현실
15
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; } 2010-2학기 가상현실
16
2010-2학기 가상현실
17
예제 프로그램 설명: checker.c 체크판은 makeCheckImage() 로 만들어짐 init()에서 텍스처매핑 초기화
glGenTextures()와 glBindTexture()로 텍스처 만들고 이름을 짓는다. glTexImage2D()에 의해 하나의 최대 텍스처 맵이 명시화됨. 변수가 크기, 타입, 위치, 텍스처 이미지 특징을 나타냄. glTexParameter*()는 텍스처가 어떻게 덧씌워졌는지, 텍셀끼리 혹은 픽셀들끼리 매치가 안될 경우 어떻게 컬러를 채울지를 명시화 display()에서 glEnable()에 의해 텍스처링 시작 glTexEnv*()는 GL_REPLACE 에 그리기 모드 설정 현재의 텍스처링 함수 설정: GL_DECAL, GL_REPLACE, GL_MODULATE, GL_BLEND glTexCoord*()는 일반적인 텍스처 좌표를 설정 2010-2학기 가상현실
18
텍스처의 명시화 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 값)공식에 맞아야 함. 2010-2학기 가상현실
19
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: 텍스처 이미지 데이터 2010-2학기 가상현실
20
datain으로 부터 데이터를 풀기 위해 적당한 픽셀 저장모드를 이용, 이미지를 스케일
테두리를 포함하지 않는 텍스처의 높이와 너비의 여러 개의 텍셀들은 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에 쓰인다. 2010-2학기 가상현실
21
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 값 2010-2학기 가상현실
22
텍스처 프록시 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); 2010-2학기 가상현실
23
예제 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); 2010-2학기 가상현실
24
target 변수는 GL_TEXTURE_2D로 설정 level: 밉맵 LOD(level-of-detail)
텍스처 이미지의 전체 또는 부분 재배치 현재 존재하는 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- 방향의 텍셀 오프셋. 부분 이미지가 존재하는 위치 2010-2학기 가상현실
25
예제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; 2010-2학기 가상현실
26
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; } 2010-2학기 가상현실
27
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); 2010-2학기 가상현실
28
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, &texName);
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); } 2010-2학기 가상현실
29
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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); 2010-2학기 가상현실
30
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0);
glEnd(); glFlush(); glDisable(GL_TEXTURE_2D); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); 2010-2학기 가상현실
31
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; 2010-2학기 가상현실
32
glBindTexture(GL_TEXTURE_2D, texName);
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); default: } } 2010-2학기 가상현실
33
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; } 2010-2학기 가상현실
34
int main(int argc, char** argv) {
#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 2010-2학기 가상현실
35
실행결과 2010-2학기 가상현실
36
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을 지정 2010-2학기 가상현실
37
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) 2010-2학기 가상현실
38
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()에서 사용하는 것과 같음 2010-2학기 가상현실
39
텍셀을 정의하기 위하여 프레임버퍼 자료를 이용, 1차원 텍스처를 만든다.
프레임버퍼를 새로운 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) 2010-2학기 가상현실
40
현존하는 1차원 텍스처 이미지의 연속적인 하위부분 전체 또는 부분을 대체하기 위해 프레임버퍼의 이미지 자료를 사용
void glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); 현존하는 1차원 텍스처 이미지의 연속적인 하위부분 전체 또는 부분을 대체하기 위해 프레임버퍼의 이미지 자료를 사용 target 변수는 GL_TEXTURE_1D로 설정 level: 세부 숫자의 밉맵 레벨 xoffset: 텍셀 offset 지정 2010-2학기 가상현실
41
3차원 텍스처 실행 안됨 3차원 텍스처는 의학, 지구과학의 응용프로그램의 제작에 많이 사용됨
의학용 프로그램 : 단층촬영(CT), 자기공명 영상법(MRI)이미지를 나타내는데 사용 볼륨 렌더링 중 일부분 3차원 텍스처 이미지는 2차원 부분 이미지 사각형 층으로 생각 메모리에서 사각형은 수열로 나열 3차원 텍스처를 만들기 위해 glTexImage3D()사용 2010-2학기 가상현실
42
사용자는 밉맵과 프록시를 공급할 수 있으며, 동일한 필터링 옵션이 가능
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) 사용자는 밉맵과 프록시를 공급할 수 있으며, 동일한 필터링 옵션이 가능 2010-2학기 가상현실
43
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() 에서 사용된 것과 같다. 2010-2학기 가상현실
44
3차원 텍스처의 부분을 대체하는 소스로서 프레임버퍼를 사용하기 위해 glCopyTexSubImage3D()를 사용
void glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height); 현존하는 3차원 텍스처 이미지의 연속적인 하위 부분을 대체하기 위해, 프레임 버퍼의 이미지 자료를 사용 target 변수는 GL_TEXTURE_3D 사용 2010-2학기 가상현실
45
3차원 텍스처의 픽셀 저장 모드 픽셀 저장값은 각 층의 행간 간격을 조절
glPixelStore*()는 픽셀이나 텍셀 자료의 전체 사각형의 부분 사각형이 참조를 조절하는 매개변수를 사용하는 픽셀 저장모드를 설정함 *ROW_LENGTH, *ALIGNMENT, *SKIP_PIXELS, *SKIP_ROWS(*는 GL_UNPACK_ 또는 GL_PACK_ 이다) 3차원 텍스처 이미지 자료의 서브 볼륨을 참조하기 위해선 추가된 픽셀 저장 모드가 필요 *IMAGE_HEIGHT,*SKIP_IMAGES 등 새로운 변수들은 서브 볼륨의 한계를 정하고 실행하기 위해 glTexImage3D(), glSubImage3D(), glGetTexImage() 루틴을 승인 2010-2학기 가상현실
46
서브 볼륨이 최초의 층에서 시작하지 않는다면 *SKIP_IMAGES 매개변수가 설정
만약 메모리에 있는 3차원 텍스처가 정의된 서브 볼륨보다 크다면 사용자는 *IMAGE_HEIGHT변수를 이용하여 하나의 부분 이미지 높이를 지정 서브 볼륨이 최초의 층에서 시작하지 않는다면 *SKIP_IMAGES 매개변수가 설정 2010-2학기 가상현실
47
*IMAGE_HEIGHT 픽셀 저장 모드 Subimage *ROW_LENGTH In layer 1 *IMAGE_ HEIGHT
*SKIP_PIXELS layer1 *SKIP_ROWS layer0 2010-2학기 가상현실
48
세부 항목의 다중 레벨 텍스처 오브젝트는 시점에서 거리가 변화함에 따라 투영된 이미지 크기와 마찬가지로 크기가 감소하여야 한다. 텍스처 맵을 오브젝트로의 매핑에 적합한 크기로 필터링해야 함. => 밉맵 사용(필터 처리된 텍스처 맵의 정도 지정) 밉매핑을 사용할 때 OpenGL은 자동적으로 매핑될 오브젝트의 크기에 기초한 텍스처의 사용을 설정 밉매핑을 사용하기 위해서는 맵의 크기가 가장 큰 것부터 1 * 1 크기의 맵까지 2의 지수승으로 표현할 수 있는 텍스처를 만들어 주어야 함 사용자의 최고 해상도 맵이 64x16 이라면, 사용자는 32x8, 16x4, 8x2, 4x1, 2x1, 1x1 크기의 맵을 제공하여야 함 이 텍스처들을 지정하기 위해 텍스처 맵의 분석이 이루어질 때 level, width, height,image 매개변수들의 다른 값을 가지고 있는 glTexImage2D()를 한번 호출 2010-2학기 가상현실
49
예제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 2010-2학기 가상현실
50
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; } 2010-2학기 가상현실
51
mipmapImage16[i][j][0] = 255; mipmapImage16[i][j][1] = 0;
for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { mipmapImage16[i][j][0] = 255; mipmapImage16[i][j][1] = 0; mipmapImage16[i][j][2] = 255; mipmapImage16[i][j][3] = 255; } } for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { mipmapImage8[i][j][0] = 255; mipmapImage8[i][j][1] = 0; mipmapImage8[i][j][2] = 0; mipmapImage8[i][j][3] = 255; 2010-2학기 가상현실
52
mipmapImage4[i][j][0] = 0; mipmapImage4[i][j][1] = 255;
for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { mipmapImage4[i][j][0] = 0; mipmapImage4[i][j][1] = 255; mipmapImage4[i][j][2] = 0; mipmapImage4[i][j][3] = 255; } } for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { mipmapImage2[i][j][0] = 0; mipmapImage2[i][j][1] = 0; mipmapImage2[i][j][2] = 255; mipmapImage2[i][j][3] = 255; 2010-2학기 가상현실
53
glEnable(GL_DEPTH_TEST); glShadeModel(GL_FLAT);
mipmapImage1[0][0][0] = 255; mipmapImage1[0][0][1] = 255; mipmapImage1[0][0][2] = 255; mipmapImage1[0][0][3] = 255; } void init(void) { glEnable(GL_DEPTH_TEST); glShadeModel(GL_FLAT); glTranslatef(0.0, 0.0, -3.6); makeImages(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 2010-2학기 가상현실
54
glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_2D, texName);
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_MIPMAP_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipmapImage32); 2010-2학기 가상현실
55
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 16, 16, 0,
GL_RGBA, GL_UNSIGNED_BYTE, mipmapImage16); glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipmapImage8); glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipmapImage4); glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipmapImage2); glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipmapImage1); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glEnable(GL_TEXTURE_2D); } 2010-2학기 가상현실
56
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #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, 8.0); glVertex3f(-2.0, 1.0, 0.0); glTexCoord2f(8.0, 8.0); glVertex3f(2000.0, 1.0, ); glTexCoord2f(8.0, 0.0); glVertex3f(2000.0, -1.0, ); glEnd(); glFlush(); } 2010-2학기 가상현실
57
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, ); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void keyboard (unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; default: break; } } 2010-2학기 가상현실
58
int main(int argc, char** argv) { glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize (500, 500); glutInitWindowPosition (50, 50); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } 2010-2학기 가상현실
59
실행 결과 2010-2학기 가상현실
60
자동화된 밉맵 생성 만약 레벨 0이나 그 이상 최고 해상도의 맵을 만들었다고 가정한다면 gluBuildD1Mipmaps(), gluBuild2DMipmaps(), gluBuild3DMipmaps() 루틴은 1 * 1 해상도로 감소하는 피라미드 형태의 밉맵을 만들고 정의 int gluBuild1DMipmaps(GLenum target, GLint internalFormat, GLint width, GLenum format,GLenum type, void *texels); int gluBuild2DMipmaps(GLenum target, GLint internalFormat, GLint width, GLenum height, GLenum format, GLenum type, void *texels); int gluBuild3DMipmpas(GLenum target, GLint internalFormat, GLint width, GLenum height, GLenum depth, GLenum format, GLenum type, void *texels); 일련의 밉맵을 만들고 이미지를 읽기 위해서 glTexImage*D()를 호출한다. 모든 밉맵들이 성공적으로 만들어지면 0값을 반환하고 실패시 GLU 에러코드 반환 2010-2학기 가상현실
61
발전된 밉맵의 세부 사항 밉매핑 계산은 텍스처 이미지와 픽셀로 텍스처 되는 폴리곤 크기 사이의 스케일 인자에 의존
= log2 , :스케일 인자 <= 0.0 텍스처는 폴리곤 크기보다 작고, 확대필터 사용 > 0.0 텍스처는 폴리곤 크기보다 크고, 축소필터 사용 예를 들어, 텍스처 이미지가 64x64 픽셀이고, 폴리곤 크기가 32x32픽셀이면 = 2.0, = 1.0 텍스처 이미지가 64x32이고, 폴리곤 크기가 8x16픽셀이면 = 8.0, = 3.0 2010-2학기 가상현실
62
OpenGL은 밉매핑 레벨들을 조절하는 새로운 매개변수 포함
GL_TEXTURE_BASE_LEVEL, GL_TEXTURE_MAX_LEVEL, GL_TEXTURE_MIN_LOD, GL_TEXTURE_MAX_LOD BASE_LEVEL 사용되는 밉맵 레벨의 최대 해상도 레벨 기본값은 0 MAX_LEVEL 사용된 최소 해상도 밉맵 기본값은 1000 밉매핑 작업 BASE_LEVEL과 최대 가능 레벨을 포함한 그 사이의 모든 밉맵들이 읽혀져야 함 최대 가능 레벨은 MAX_LEVEL 보다 작거나 같은 값이거나, 밉맵의 크기가 1텍셀(1, 1x1, 1x1x1)일 때의 레벨 2010-2학기 가상현실
63
밉매핑 레벨 매개변수 제어하기 매개변수 표현 값 GL_TEXTURE_BASE_LEVEL
사용시 가장 높은 해상도를 가지는 텍스처의 레벨(가장 낮은 숫자의 밉맵 레벨) 양의 정수의 값 GL_TEXTURE_MAX_LEVEL 사용시 가장 낮은 해상도를 가지는 텍스처의 레벨(가장 높은 숫자의 밉맵 레벨) 2010-2학기 가상현실
64
세부적 제어의 밉맵 레벨 MIN_LOD와 MAX_LOD는 밉맵 축소의 값( ,텍스처 이미지에 폴리곤으로의 스케일 인자)의 최대, 최소값을 제공 BASE_LEVEL과 MAX_LEVEL을 사용하여 glTexParameter*()는 MIN_LOD와 MAX_LOD를 설정 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 2.5); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4.5); 2010-2학기 가상현실
65
자동화된 밉맵 부분 집합 생성 밉맵 레벨의 발전된 제어를 통해 gluBuild*DMipmaps()로정의된 밉맵의 부분 집합을 만들 필요가 있다. 밉멥 레벨들의 부분집합의 계산과 읽기를 위하여 gluBuild*DMipmapLevels()를 호출 int gluBuild1DMipmapLevels(GLenum target, GLint internalFormat, GLint width, GLenum format, GLenum type, GLint level,GLint base, GLint max, void *texels); int gluBuild2DMipmapLevels(GLenum target, GLint internalFormat, GLint width, Glint height, GLenum format, GLenum type, GLint level,GLint base, GLint max, void *texels); int gluBuild3DMipmapLevels(GLenum target, GLint internalFormat, GLint width, Glint height, GLint depth,GLenum format, GLenum type, GLint level,GLint base, GLint max, void *texels); 2010-2학기 가상현실
66
필 터 링 텍스처 맵은 정사각형 또는 직사각형이기 때문에 폴리곤이나 표면으로 매핑, 좌표 변환시 화면 이미지의 각각의 픽셀에 대응하기가 힘듬 어떠한 텍셀값이 사용되어야 하고 평균, 보간되는지를 위한 필터링 옵션 제공 glTexParameter*()는 확대, 축소 필터링 방법을 지정한다. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2010-2학기 가상현실
67
확대와 축소를 위한 필터링 방법 GL_NEAREST(최근점법): 픽셀의 중심에 가까운 좌표를 가지는 텍셀이 확대와 축소를 위해 사용 GL_LINEAR(보간법): 픽셀의 중심에 가까이 위치한 텍셀의 2x2배열의 조정된 선형 평균 사용 GL_NEAREST_MIPMAP_NEAREST: 각각의 밉맵내에서 가장 가까운 텍셀값을 선택 GL_NEAREST_MIPMAP_LINEAR: 각각의 밉맵 내에서 선형적으로 보간 매개변수 값 GL_TEXTURE_MAG_FLITER GL_NEAREST 또는 GL_LINEAR GL_TEXTURE_MIN_FILTER GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR 2010-2학기 가상현실
68
GL_LINEAR_MIPMAP_NEAREST: 두 개의 맵 중에서 가장 가까운 텍셀을 선택하고 이 두 개의 값을 선형적으로 보간
GL_LINEAR_MIPMAP_LINEAR: 두 개의 맵에 있는 값들을 계산하기 위해 선형 보간법을 사용하고, 두 개의 값을 선형적으로 보간 2010-2학기 가상현실
69
OpenGL 튜토리얼 - 텍스처 2010-2학기 가상현실
70
텍스처 오브젝트 텍스처 데이터를 저장하고, 사용 가능한 형태로 준비 텍스처 오브젝트 사용은 텍스처를 적용하는 가장 빠른 방법
텍스처 오브젝트 재사용이 glTexImage*() 보다 빠름 텍스처 데이터를 위한 텍스처 오브젝트 사용 과정 텍스처 이름을 만든다. 이미지 배열과 텍스처 속성을 포함하여 텍스처 데이터에 텍스처 오브젝트를 만든다 만약 사용자의 실행 환경이 높은 수행 텍스처의 한정된 작업 집합을 제공한다면 텍스처 오브젝트 전체적으로 충분한 공간을 가지는지 확인 텍스처 오브젝트를 묶어서 그것들의 데이터가 텍스처된 모델에 즉시 적용될 수 있도록 한다. 2010-2학기 가상현실
71
텍스처 오브젝트의 명명 void glGenTextures(GLsizei n, GLuint *textureNames)
texture Names 배열에 있는 텍스처 오브젝트의 n개의 사용되지 않은 이름을 반환 GLboolean glIsTexture(GLuint textureName); 텍스처 이름이 실질적으로 사용되었는지 판정 텍스처 이름이 반환되나 아직 등록이 되지 않았다면 GL_FALSE를 반환 2010-2학기 가상현실
72
텍스처 오브젝트의 생성과 사용 glBindTexture()는 텍스처 오브젝트를 만들고 사용
void glBindTexture(GLenum target, GLuint texture); 처음에 0 이 아닌 부호 없는 정수의 textureName을 이용할 때 새로운 텍스처 오브젝트가 만들어지고, 그 이름을 사용 사전에 만들어진 텍스처 오브젝트에 묶여질 때 이 텍스처 오브젝트는 활성화 0의 값을 가지는 textureName에 묶을 때 OpenGL은 텍스처 오브젝트 사용을 중단, 명명되지 않은 디폴트 텍스처에 반환 2010-2학기 가상현실
73
예제9-7 텍스처 오브젝트 바인딩: texbind.c
#include <GL/glut.h> #include <stdlib.h> #include <stdio.h> #ifdef GL_VERSION_1_1 #define checkImageWidth 64 #define checkImageHeight 64 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; static GLubyte otherImage[checkImageHeight][checkImageWidth][4]; static GLuint texName[2]; 2010-2학기 가상현실
74
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; c = ((((i&0x10)==0)^((j&0x10))==0))*255; 2010-2학기 가상현실
75
otherImage[i][j][0] = (GLubyte) c; otherImage[i][j][1] = (GLubyte) 0;
} void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); 2010-2학기 가상현실
76
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(2, texName);
makeCheckImages(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(2, texName); glBindTexture(GL_TEXTURE_2D, texName[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); 2010-2학기 가상현실
77
glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, otherImage); glEnable(GL_TEXTURE_2D); } 2010-2학기 가상현실
78
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, texName[0]); 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); glEnd(); 2010-2학기 가상현실
79
glBindTexture(GL_TEXTURE_2D, texName[1]); glBegin(GL_QUADS);
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( , 1.0, ); glTexCoord2f(1.0, 0.0); glVertex3f( , -1.0, ); glEnd(); glFlush(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); 2010-2학기 가상현실
80
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0);
glLoadIdentity(); gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0); glMatrixMode(GL_MODELVIEW); glTranslatef(0.0, 0.0, -3.6); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; 2010-2학기 가상현실
81
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(); glutReshapeFunc(reshape); glutDisplayFunc(display); glutKeyboardFunc (keyboard); glutMainLoop(); return 0; } 2010-2학기 가상현실
82
int main(int argc, char** argv) {
#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 2010-2학기 가상현실
83
실행 결과 2010-2학기 가상현실
84
텍스처 오브젝트를 묶거나 풀어버릴 때 그 데이터들은 사용자의 텍스처 리소스의 어딘가에 여전히 존재
텍스처 오브젝트의 초기화 텍스처 오브젝트를 묶거나 풀어버릴 때 그 데이터들은 사용자의 텍스처 리소스의 어딘가에 여전히 존재 만약 텍스처 리소스가 한정되어 있을 때 텍스처 제거는 리소스 확보의 한 방법 void glDeleteTexture(GLsizei n, const GLuint *textureName); textureNames 배열의 원소들로 명명된 n개의 텍스처 오브젝트를 삭제 2010-2학기 가상현실
85
상주하는 텍스처의 작업 집합 몇 가지 실행환경은 상주(resident)라고 불리는 높은 수행 텍스처의 작업 집합을 제공
GLboolean glAreTexturesResident(GLsizei n, const GLuint *textureNames, GLboolean *residences); 사용자가 많은 텍스처 상주상태를 알고 싶을 때 사용 textureNames 배열의 이름을 갖는 n개 텍스처 오브젝트의 상주 상태를 조회 residences는 텍스트 상주 상태가 textureNames 배열에 있는 텍스처 오브젝트의 텍스처 존재 상태가 반환되는 배열 glAreTexturesResident()는 현재의 존재 상태를 반환 텍스처 리소스들은 상당히 동적이며, 존재 상태는 아무 때나 바뀜 2010-2학기 가상현실
86
텍스처 우선순위 몇 개의 텍스처가 다른 것보다 더 자주 사용된다면 텍스처의 존재성을 증가 시키기 위해 오브젝트에 우선순위 설정
void glPrioritizeTextures(GLsizei n, const GLuint, *textureNames, const GLclampf * priorities); n개의 textureNames에서 명명되고, priorities 배열에 해당하는 원소들보다 미리 존재하는 텍스처 오브젝트를 지정 priorities 배열의 우선순위값은 [0.0, 1.0] 사이의 값으로 고정된다. 0은 가장 낮은 순위를 나타내며 1은 가장 높은 순위를 나타낸다. 2010-2학기 가상현실
87
텍스처 함수 텍스처링 없이 만들어진 표면의 컬러를 조정하거나, 텍스처맵의 컬러를 표면 원래의 색과 혼합하는데 텍스처 맵의 값을 사용 glTexEnv*()에 적절한 인수를 적용하여 4개 중 하나의 텍스처 함수를 선택 void glTexEnv{if}(GLenum target, GLenum pname,m TYPE param); void glTexEnv{if}v(GLenum target, GLenum pname,m TYPE *param); 현재의 텍스처링 함수를 설정, target은 GL_TEXTURE_ENV 이다 pname은 GL_TEXTURE_ENV_MODE, GL_TEXTURE_ENV_COLOR … 등 param은 어떻게 텍스처값이 실행되는 프레그먼트의 컬러값과 혼합되는지를 나타내는, GL_DECAL, GL_REPLACE, GL_MODULATE, GL_BLEND 텍스처링 함수와 베이스의 내부 형태의 혼합은 텍스처가 어떻게 각각의 구성 요소에 적용되는지를 판정 2010-2학기 가상현실
88
텍스처의 교체와 변조 함수 (GL_REPLACE, GL_MODULATE)
S: source, f: fragment 텍스처의 교체와 변조 함수 (GL_REPLACE, GL_MODULATE) 베이스 내부 형식 텍스처 교체 함수 텍스처 변조 함수 GL_DECAL GL_ALPHA C = Cf A = As A = AfAs 정의되지 않음 GL_LUMINANCE C = Cs A = Af C = CfLs GL_ALUMINANCE_ALPHA C = Af GL_INTENSITY A = If A = AfIs GL_RGB C = CfCs GL_RGBA C = Cf(1-As)+CsAs 2010-2학기 가상현실
89
텍스처의 전사와 블렌딩 함수 (GL_BLEND, GL_ADD)
c: GL_TEXTURE_ENV_COLOR 텍스처의 전사와 블렌딩 함수 (GL_BLEND, GL_ADD) 베이스 내부 형식 GL_BLEND 함수 GL_ADD 함수 GL_ALPHA C = Ct A = AfAs C = Cf GL_LUMINANCE C=Cf(1-Cs)+CcCs A = Af C = Cf + Cs GL_LUMINANCE_ALPHA GL_INTENSITY A=Af(1-As)+AcAs A = Af + As GL_RGB GL_RGBA 2010-2학기 가상현실
90
변조할 때(GL_MODULATE) 프레그먼트의 컬러는 텍스처의 구성요소로 변조된다.
텍스처 전사 함수(GL_DECAL)는 교체함수(GL_REPLACE)와 비슷하나 RGB와 RGBA 내부 형태에서만 작동하며, 알파값을 상이하게 처리한다는 점에서 다름 변조할 때(GL_MODULATE) 프레그먼트의 컬러는 텍스처의 구성요소로 변조된다. 내부 형식이 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_INTENSITY일 때 컬러값은 같은 값으로 곱해진다. GL_RGB와 GL_RGBA 내부 형태에서 각각의 입력되는 컬러 요소는 텍스처의 해당되는 값과 곱해진다. 변조는 라이팅된 폴리곤 컬러가 텍스처 컬러를 묽게 만든다는 점에서 빛의 효과로 사용 2010-2학기 가상현실
91
텍스처 좌표의 지정 텍스처 맵 영상을 그릴 때 각각의 정점에 대한 오브젝트 좌표와 텍스처 좌표를 제공해야 함
변환 이후 오브젝트의 좌표는 특정한 정점이 위치하는 화면상의 위치를 정함 텍스처 좌표는 텍스처 맵의 어떠한 텍셀이 그 정점을 지정하는지 정함 void glTexCoord{1234}{sifd}(TYPE coords); void glTexCoord{1234}v{sifd}(TYPE *coords); 텍스처 좌표(s, t, r, q)를 설정 오브젝트좌표 ( x, y, z, w)와 구분하기 위해 다르게 표현 2010-2학기 가상현실
92
텍스처의 순환과 클램핑 [ 0, 1 ] 범위 외부에 텍스처 좌표를 설정할 수 있고, 텍스처 맵 내부에 고정되거나 순환하게 할 수 있다. 다른 가능성은 텍스처 좌표를 클램프 하는 것 1.0보다 큰값은 1.0으로 설정 0.0보다 작은값은 0.0으로 설정 테두리를 갖는 텍스처를 사용하거나, 텍스처 테두리의 컬러를 설정했다면 래핑 모드와 필터링 방법 둘 다 테두리 정보가 사용되는지에 대해 영향을 미침 2010-2학기 가상현실
93
테두리나 테두리 컬러가 존재할 경우, 텍스처와 테두리 컬러는 다음과 같이 사용됨
만약 사용자가 필터링 메소드로 GL_LINEAR를 선택했다면 텍스처 응용을 위해 컬러 자료의 2 * 2배열의 조작된 조합이 사용 테두리나 테두리 컬러가 존재할 경우, 텍스처와 테두리 컬러는 다음과 같이 사용됨 래핑모드 GL_REPEAT: 경계는 항상 무시됨 래핑모드 GL_CLAMP: 경계로부터 텍셀은 조작된 텍셀의 2x2 배열에 사용됨 래핑모드 GL_CLAMP_TO_EDGE: 테두리는 항상 무시됨. void glTexParameter{if}(GLenum target, GLenum pname, TYPE param); void glTexParameter{if}v(GLenum target, GLenum pname, TYPE *param); 텍스처가 프레그먼트에 적용되거나, 텍스처 오브젝트에 저장되는 방법을 조종하는 다양한 변수를 설정 2010-2학기 가상현실
94
예제: 9-1에서 glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); glTexCoord2f(0.0, 3.0); glVertex3f(-2.0, 1.0, 0.0); glTexCoord2f(3.0, 3.0); glVertex3f(0.0, 1.0, 0.0); glTexCoord2f(3.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, 3.0); glVertex3f(1.0, 1.0, 0.0); glTexCoord2f(3.0, 3.0); glVertex3f( , 1.0, ); glTexCoord2f(3.0, 0.0); glVertex3f( , -1.0, ); glEnd(); 2010-2학기 가상현실
95
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 2010-2학기 가상현실
96
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 2010-2학기 가상현실
97
glTexParameter*() 매개변수들
GL_TEXTURE_WRAP_S GL_CLAMP, GL_CLAMP_TO_EDGE, GL_REPEAT GL_TEXTURE_WRAP_T GL_TEXTURE_WRAP_R GL_TEXTURE_MAG_FILTER GL_CLAMP, GL_LINEAR GL_TEXTURE_MIN_FILTER GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GLLINEAR_MIPMAP_NEAREST, GL_LINER_MIPMAP_LINEAR 2010-2학기 가상현실
98
GL_TEXTURE_BORDER_COLOR [0.0, 1.0] 사이의 어떤 4개값 가능
매개변수 변수들 GL_TEXTURE_BORDER_COLOR [0.0, 1.0] 사이의 어떤 4개값 가능 GL_TEXTURE_PRIORITY [0.0, 1.0]에서 현재의 텍스처 오브젝트 GL_TEXTURE_MIN_LOD 소수점값은 어떤 값이든 가능 GL_TEXTURE_MAX_LOD GL_TEXTURE_BASE_LEVEL 양의 정수값은 어떤 값이든 가능 GL_TEXTURE_MAX_LEVEL 2010-2학기 가상현실
99
텍스처 좌표 자동으로 산출하기 모델의 윤곽을 그리거나, 임의의 빛나는 모델의 환경에서 도출되는 반사를 가짜로 표현하기 위해 텍스처 매핑을 사용 가능 glTextureCoord*() 보다는 OpenGL이 자동으로 텍스처 좌표를 산출하도록 한다. void glTexGen{ifd}(GLenum coord, GLenum pname, TYPE param); void glTexGen{idf}v(GLenum coord, GLenum pname, TYPE *param); 첫 번째 매개변수 coord는 텍스처 좌표가 산출되는지를 지시하기 위해 GL_S, GL_T, GL_R, GL_Q 사용 pname은 GL_TEXTURE_GEN_MODE, GL_OBJECT_PLANE, GL_EYE_PLANE param은 GL_OBJECT_LINEAR, GL_EYE_LINEAR, GL_SPHERE_LINEAR 2010-2학기 가상현실
100
GL_TEXTURE_GEN_MODE와 GL_OBJECT_LINEAR가 설정되었을 때
윤곽선 그리기 GL_TEXTURE_GEN_MODE와 GL_OBJECT_LINEAR가 설정되었을 때 산출 함수는 정점(x0, y0, z0, w0)좌표의 선형 조합 산출된 좌표 = p1x0 + p2y0 + p3z0 + p4w0 p1~4은 GL_OBJECT_PLANE 에서 나온 pname 집합과 함께 glTextGen*v()의 param 인수로 제공 p1~4가 정규화 되었을 때 이 함수는 정점과 평면 사이의 거리를 제공 예를 들어, p2=p3=p4=0이고, p1=1이면 이 함수는 정점과 x=0 평면 사이의 거리를 제공한다. 거리는 평면의 한 면에서는 양수이고, 다른 면에서는 음수이며, 정점이 그 평면 위에 있을 때는 0이다. 2010-2학기 가상현실
101
static Glfloat xequalzero[] = {1.0, 0.0, 0.0, 0.0}; x=0 평면의 좌표
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, xequalzero); 윤곽선들이 모두 밑바닥과 수직 위치가 된다. Static GLFloat slanted[] = {1.0, 1.0, 1.0, 0.0}; 곡선 줄무늬는 x+y+z=0 평면과 평행, 비스듬하게 지나감. GL_OBJECT_LINEAR 함수 모델의 좌표시스템 텍스처 좌표를 계산한다. 주전자의 위치나 관점에 상관 없이 주전자의 밑면에 수직으로 남는다. 2010-2학기 가상현실
102
평면과의 거리 계산을 위하여 벡터(p1, p2, p3, p4)를 모델뷰 행렬의 역행렬과 곱한다.
GL_EYE_LINEAR 함수 윤곽선이 시각 좌표 시스템과 관련되어 계산됨 평면과의 거리 계산을 위하여 벡터(p1, p2, p3, p4)를 모델뷰 행렬의 역행렬과 곱한다. (p1’, p2’, p3’, p4’) = (p1, p2, p3, p4) M-1 (xe, ye, ze, we): 벡터의 시각좌표 (p1, p2, p3, p4)는 pname이 GL_EYE_PLANE 으로 설정되었을 때 glTexGen*()의 param 인수로 제공됨 산출된 좌표 = p1’ xe + p2’ ye + p3’ ze + p4’ we 2010-2학기 가상현실
103
예제9-8 자동 텍스처 좌표 생성: texgen.c
#include <GL/glut.h> #include <stdlib.h> #include <stdio.h> #define stripeImageWidth 32 GLubyte stripeImage[4*stripeImageWidth]; #ifdef GL_VERSION_1_1 static GLuint texName; #endif 2010-2학기 가상현실
104
void makeStripeImage(void){ int j;
for (j = 0; j < stripeImageWidth; j++) { stripeImage[4*j] = (GLubyte) ((j<=4) ? 255 : 0); stripeImage[4*j+1] = (GLubyte) ((j>4) ? 255 : 0); stripeImage[4*j+2] = (GLubyte) 0; stripeImage[4*j+3] = (GLubyte) 255; } static GLfloat xequalzero[] = {1.0, 0.0, 0.0, 0.0}; static GLfloat slanted[] = {1.0, 1.0, 1.0, 0.0}; static GLfloat *currentCoeff; 2010-2학기 가상현실
105
static GLenum currentPlane; static GLint currentGenMode;
void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); makeStripeImage(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef GL_VERSION_1_1 glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_1D, texName); 2010-2학기 가상현실
106
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
#endif glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); #ifdef GL_VERSION_1_1 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, stripeImageWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, stripeImage); #else glTexImage1D(GL_TEXTURE_1D, 0, 4, stripeImageWidth, 0, 2010-2학기 가상현실
107
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
currentCoeff = xequalzero; currentGenMode = GL_OBJECT_LINEAR; currentPlane = GL_OBJECT_PLANE; glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, currentGenMode); glTexGenfv(GL_S, currentPlane, currentCoeff); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_1D); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); 2010-2학기 가상현실
108
glEnable(GL_NORMALIZE); glFrontFace(GL_CW); glCullFace(GL_BACK);
glMaterialf (GL_FRONT, GL_SHININESS, 64.0); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); glRotatef(45.0, 0.0, 0.0, 1.0); 2010-2학기 가상현실
109
glBindTexture(GL_TEXTURE_1D, texName); #endif glutSolidTeapot(2.0);
#ifdef GL_VERSION_1_1 glBindTexture(GL_TEXTURE_1D, texName); #endif glutSolidTeapot(2.0); glPopMatrix (); glFlush(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); 2010-2학기 가상현실
110
glOrtho (-3.5, 3.5, -3.5*(GLfloat)h/(GLfloat)w,
if (w <= h) glOrtho (-3.5, 3.5, -3.5*(GLfloat)h/(GLfloat)w, 3.5*(GLfloat)h/(GLfloat)w, -3.5, 3.5); else glOrtho (-3.5*(GLfloat)w/(GLfloat)h, 3.5*(GLfloat)w/(GLfloat)h, -3.5, 3.5, -3.5, 3.5); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } 2010-2학기 가상현실
111
void keyboard (unsigned char key, int x, int y) { switch (key) {
case 'e': case 'E': currentGenMode = GL_EYE_LINEAR; currentPlane = GL_EYE_PLANE; glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, currentGenMode); glTexGenfv(GL_S, currentPlane, currentCoeff); glutPostRedisplay(); break; 2010-2학기 가상현실
112
currentGenMode = GL_OBJECT_LINEAR; currentPlane = GL_OBJECT_PLANE;
case 'o': case 'O': currentGenMode = GL_OBJECT_LINEAR; currentPlane = GL_OBJECT_PLANE; glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, currentGenMode); glTexGenfv(GL_S, currentPlane, currentCoeff); glutPostRedisplay(); break; case 's': case 'S': currentCoeff = slanted; 2010-2학기 가상현실
113
currentCoeff = xequalzero;
case 'x': case 'X': currentCoeff = xequalzero; glTexGenfv(GL_S, currentPlane, currentCoeff); glutPostRedisplay(); break; case 27: exit(0); default: } 2010-2학기 가상현실
114
int main(int argc, char** argv) { glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(256, 256); glutInitWindowPosition(100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } 2010-2학기 가상현실
115
실행결과 2010-2학기 가상현실
116
환경 매핑 생략 환경매핑의 목표 오브젝트가 완벽하게 반사하는 것처럼 만들어서 그것의 표면의 컬러와 모양이 주위 환경에서 반사되어 보이도록 하는 것 환경매핑은 환경에 있는 오브젝트들이 반사하는 물체의 표면과 떨어져 있음을 가정하여 기초로 한 근사값 윤기가 나고 반사하는 은빛 오브젝트를 볼 때, 반사되는 오브젝트의 관찰은 시점과 은빛 오브젝트의 표면 각에 의존 완벽하게 올바른 텍스처 맵을 만들기 위해 사용자는 큰 은빛의 구를 만들고, 무한대로 멀리 떨어지고, 무한대의 초점 거리를 가지는 사진기로 일부 환경 내에서 사진을 찍고, 그것을 주사하여야 한다. 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); 2010-2학기 가상현실
117
텍스처 행렬 스택 생략 사용자의 모델 좌표가 만들어지기 전의 행렬로 변형되면, 텍스처 좌표는 어떠한 텍스처 매핑이 발생하기 전에 4*4행렬과 곱해짐 기본값에 의해 텍스처 행렬은 동일, 정의하거나 자동으로 산출된 텍스처 행렬을 수정한다면 텍스처가 표면에 미끄러지거나, 그 근처에서 회전하고, 뻗어지고, 오그라들거나 세 가지 조합을 수행하게 됨 텍스처 행렬은 스택의 꼭대기 행렬인데, 적어도 두 행렬의 내부에 스택을 가진다. glPushMatrix(), glPopMatrix(), glMultMatrix(), glRotate*() 등의 모든 표준 행렬 조작 명령이 텍스처 행렬에 적용될 수 있다. 현재의 텍스처 행렬을 수정하기 위해서는 행렬 모드를 GL_TEXTURE 로 설정 glMatrixMode(GL_TEXTURE) 2010-2학기 가상현실
118
멀티텍스처링 생략 텍스처링에서 하나의 텍스처 이미지는 하나의 폴리곤에 적용
OpenGL 1.2에서는 몇 가지의 텍스처들이 하나씩 같은 폴리곤에 적용되는 것을 허용 멀티 텍스처링을 할 경우 텍스처 유닛의 나열을 가짐 각각의 텍스처 유닛은 모든 정의된 유닛이 완결될 때까지 하나의 텍스처링 연산을 수행, 다른 텍스처 유닛으로 이동 멀티텍스처링은 라이팅 효과, 전사, 합성, 세부적 텍스처 등의 기술 제공 2010-2학기 가상현실
119
2) 각각의 텍스처링 유닛에 대해 텍스처 이미지, 필터, 환경, 좌표 산출 그리고 행렬을 포함하는 텍스처링 상태를 설정
멀티 텍스처링의 단계 1) 멀티텍스처 확장이 제공되었는지 확인 2) 각각의 텍스처링 유닛에 대해 텍스처 이미지, 필터, 환경, 좌표 산출 그리고 행렬을 포함하는 텍스처링 상태를 설정 3) 정점을 지정할 때 하나의 정점에 대해 하나 혹은 그 이상의 텍스처 좌표를 설정하는 GLMULTITEXCOORD*ARB()를 사용하라 2010-2학기 가상현실
120
텍스처 유닛의 확립 멀티텍스처링은 각각이 추가적인 텍스처 응용프로그램 패스를 갖고 있는 다중 텍스처 유닛을 말한다.
원래 텍스처링 상태에 존재하는 동일한 가능성을 가짐 다음과 같은 것들이 포함되는 텍스처링 상태를 관리 텍스처 이미지 필터링 변수 환경 응용 텍스처 행렬 스택 자동 텍스처 좌표 산출 정점 배열 지정(필요할 때) 2010-2학기 가상현실
121
void glActiveTextureARB(GLenum texUnit); 텍스처링 루틴에 의해 변경되는 텍스처 유닛을 선택
만약 사용자가 텍스처 오브젝트를 사용한다면 사용자는 텍스처를 현재의 텍스처 유닛으로 한정할 수 있다. 2010-2학기 가상현실
122
정점 지정과 텍스처 좌표 멀티텍스처링에서, 하나의 정점에 하나의 텍스처 좌표 집합을 가지는 것은 충분하지 않다
각각의 정점에 하나의 텍스처 유닛의 집합을 갖도록 할 경우 void glMultiTexCoord{1234}{sifd}ARB(GLenum texUnit, TYPE coords); void glMultiTexCoord{1234}{sifd}vARB(GLenum texUnit, TYPE *coords); 텍스처 유닛을 texUnit에서 사용하기 위해 coords의 텍스처 좌표 자료 (s, t, r, q)를 설정 texUnit 의 열거된 값들은 glActiveTextureARB() 의 나열된 값과 같다. 2010-2학기 가상현실
123
텍스처 좌표 지정의 다른 방법 glMultiTexCoored*ARB()외에 다른 2 가지 방법은 자동 텍스처 좌표 산출을 사용하거나 정점 배열을 이용 하는 것이다. 멀티텍스처링 중이고, 자동 텍스처 좌표 산출을 사용한다면 glActiveTextureARB()는 어떠한 텍스처 유닛이 다음의 자동 텍스처 좌표 산출 루틴의 영향을 받는지를 지정 glTexGen*(..) glEnable(GL_TEXTURE_GEN_..) glDisable(GL_TEXTURE_GEN_..) 2010-2학기 가상현실
124
멀티텍스처링 중이면서 정점 배열로 텍스처 좌표를 지정한다면
glClientActiveTextureARB()는 glTexCoordPointer()가 어떤 텍스처 유닛의 좌표 자료를 지정할지를 지정 void glClientActiveTextureARB(GLenum texUnit); 정점 배열을 이용한 텍스처 좌표 자료 산출이 이루어질 현재의 텍스처 유닛을 선택 texUnit은 glActiveTextureARB()에서 사용된 것과 같은 값을 가지는 GL_TEXTUREi_ARB 형태의 상징적인 상수 2010-2학기 가상현실
Similar presentations