버퍼 (Buffer)
목표 OpenGL 기타 버퍼 소개 버퍼 읽기와 쓰기 블렌딩 이용
버퍼 (Buffer) 버퍼는 공간 해상도 (n x m) 와 깊이(정밀도) k, 픽셀당 비트수 bits/pixel 로 정의한다
OpenGL 프레임버퍼 (Frame Buffer)
OpenGL 버퍼 컬러 버퍼는 다음에 의해 디스플레이된다. 깊이(Depth) 누적(Accumulation) Front Back Auxiliary Overlay 깊이(Depth) 누적(Accumulation) 고해상도 버퍼 스텐실(Stencil) 마스크 보관
버퍼에 쓰기 개념적으로 모든 메모리는 2차원 픽셀 배열 사각형 픽셀 블록을 읽고 쓰기 프레임버퍼는 메모리의 일부 memory Bit block transfer (bitblt) operations 프레임버퍼는 메모리의 일부 memory source frame buffer (destination) 프레임버퍼에 쓰기
쓰기 모델 소스를 쓰기 전에 목적 픽셀을 읽는다
비트(Bit) 쓰기 모드 소스와 목적 비트들은 비트별로 결합된다. 16 개 가능한 함수 (표에서 열당 하나) XOR replace OR
XOR 모드 3장에서 XOR 을 이용한 논리 연산을 참고한다 S 가 스크린이고 M 이 메뉴라고 하면 S S M M S M swaps the S and M
픽셀 파이프라인 (The Pixel Pipeline) OpenGL 은 픽셀을 위한 별도의 파이프라인을 가진다 픽셀 쓰기는 다음을 포함 픽셀을 프로세서 메모리에서 프레임버퍼로 이동 포맷 변환 매핑, 룩업(Lookups), 테스트 픽셀 읽기 Format conversion
래스터 위치 (Raster Position) OpenGL 은 래스터 위치를 상태 일부로 유지한다. Set by glRasterPos*() glRasterPos3f(x, y, z); 래스터 위치는 기하 요소이다. 기하 파이프라인을 거친다 결국은 스크린 좌표상의 2차원 위치를 갖는다 프레임버퍼 내에서 이 위치가 다음 래스터 프리미티브가 그려지는 곳이다.
버퍼 선택 (Buffer Selection) OpenGL 은 어떤 컬러 버퍼에도 읽기와 쓰기가 가능하다 (front, back, auxiliary) 디폴트는 후면 버퍼 glDrawBuffer 와 glReadBuffer 에 의해 변화한다 프레임버터내 픽셀 포맷은 프로세서 메모리에서 포맷과 다르며 이 두 타입은 다른 곳에 존재한다. 패킹과 언패킹 필요 (packing and unpacking) 읽기와 쓰기는 느려짐
비트맵(Bitmaps) OpenGL 은 1-bit pixels (bitmaps)과 multi-bit pixels (pixelmaps) 을 다르게 처리 비트맵은 프레임버퍼 내 해당 픽셀을 현재 래스터 컬러로 그릴지를 결정하는 마스크이다. 0 color unchanged 1 color changed based on writing mode 비트맵은 래스터 텍스트에 유용하다. GLUT font: GLUT_BIT_MAP_8_BY_13
래스터 컬러 (Raster Color) 마지막 glRasterPos*()에 고정된다 기하는 파랑색으로 그려짐 glColor*()로 설정되는 컬러와 동일하다 마지막 glRasterPos*()에 고정된다 기하는 파랑색으로 그려짐 비트맵 1은 빨강색을 사용한다 glColor3f(1.0, 0.0, 0.0); glRasterPos3f(x, y, z); glColor3f(0.0, 0.0, 1.0); glBitmap(……. glBegin(GL_LINES); glVertex3f(…..)
비트맵 그리기 offset from raster position 비트맵 그린 후 래스터 위치 증가 첫 번째 래스터 위치 glBitmap(width, height, x0, y0, xi, yi, bitmap) offset from raster position 비트맵 그린 후 래스터 위치 증가 첫 번째 래스터 위치 두 번째 래스터 위치
예제: Checker Board GLubyte wb[2] = {0 x 00, 0 x ff}; GLubyte check[512]; int i, j; for(i=0; i<64; i++) for (j=0; j<64, j++) check[i*8+j] = wb[(i/8+j)%2]; glBitmap( 64, 64, 0.0, 0.0, 0.0, 0.0, check);
픽셀 맵 (Pixel Maps) OpenGL 은 픽셀 맵 혹은 픽셀 이미지라고 부르는 사각형 픽셀 배열 이용 픽셀은 1 바이트(8 비트) 덩어리 밝기(gray scale) 이미지는 1 byte/pixel RGB는 3 bytes/pixel 세 종류 함수 Draw pixels: 프로세서 메모리에서 프레임버퍼로 Read pixels: 버퍼로부터 프로세서 메모리로 Copy pixels: 프레임버퍼에서 프레임버퍼로
OpenGL 픽셀 함수 size type of pixels start pixel in frame buffer glReadPixels(x,y,width,height,format,type,myimage) size type of pixels start pixel in frame buffer type of image pointer to processor memory GLubyte myimage[512][512][3]; glReadPixels(0,0, 512, 512, GL_RGB, GL_UNSIGNED_BYTE, myimage); glDrawPixels(width,height,format,type,myimage) 래스터 위치에서 시작한다
이미지 포맷 (Image Formats) 표준 이미지 포맷으로 작업하나 (JPEG, TIFF, GIF) OpenGL 에서 이러한 이미지를 어떻게 읽기/쓰기 하나? OpenGL 에서 지원 안함 OpenGL 은 이미지 포맷에 대해선 모른다 웹에서 일부 코드 제공하기도 OpenGL 에서는 간단한 포맷의 읽기 쓰기가 가능하다
PPM 이미지 디스플레이 PPM 은 아주 간단한 포맷 각 이미지 파일은 헤더와 모든 픽셀 데이터로 구성됨 헤더(Header) # comment 1 # comment 2 . #comment n rows columns maxvalue pixels
헤더 (Header) 읽기 check for “P3” in first line FILE *fd; int k, nm; char c; int i; char b[100]; float s; int red, green, blue; printf("enter file name\n"); scanf("%s", b); fd = fopen(b, "r"); fscanf(fd,"%[^\n] ",b); if(b[0]!='P'|| b[1] != '3'){ printf("%s is not a PPM file!\n", b); exit(0); } printf("%s is a PPM file\n",b); check for “P3” in first line
헤더 읽기 (계속) skip over comments by looking for # in first column fscanf(fd, "%c",&c); while(c == '#') { fscanf(fd, "%[^\n] ", b); printf("%s\n",b); } ungetc(c,fd); skip over comments by looking for # in first column
데이터 읽기 scale factor fscanf(fd, "%d %d %d", &n, &m, &k); printf("%d rows %d columns max value= %d\n",n,m,k); nm = n*m; image=malloc(3*sizeof(GLuint)*nm); s=255./k; for(i=0;i<nm;i++) { fscanf(fd,"%d %d %d",&red, &green, &blue ); image[3*nm-3*i-3]=red; image[3*nm-3*i-2]=green; image[3*nm-3*i-1]=blue; } scale factor
이미지 데이터 크기변환 파이프라인에서 이미지 크기 변환이 가능하다 glPixelTransferf(GL_RED_SCALE, s); glPixelTransferf(GL_GREEN_SCALE, s); glPixelTransferf(GL_BLUE_SCALE, s); 프로세서에 따라 프로세서 메모리에서 프레임버퍼로 갈 때 바이트들을 교환(Swap) 할 수 있다 glPixelStorei(GL_UNPACK_SWAP_BYTES,GL_TRUE);
디스플레이 콜백 (display callback) void display() { glClear(GL_COLOR_BUFFER_BIT); glRasterPos2i(0,0); glDrawPixels(n,m,GL_RGB, GL_UNSIGNED_INT, image); glFlush(); }