Friday, April 10, 2015

OpenGL BMP 텍스처 저장

OpenGL에서 현재 texture를 눈으로 확인하며 디버깅하고 싶을 때 texture를 bmp파일로 저장하여 디버깅 할때 아래와 같이 한다.

이때 중요한 함수가 glGetTexLevelParameteriv인데 이것은 현재 texture 현재 mipmap level예제에서는 level가 1개 이므로 0이다.)의 parameter를 얻는 함수이다. 저장할 때는 32비트 bmp로 저장한다. glGetTexImage는 현재 texture의 pixel을 얻어온다.

이때 32비트 bmp는 GL_BGRA이므로 format을 GL_RGBA로 하면 색깔이 뒤집힌다.

#define GL_BGRA 0x80E1 // Use this for 32bit bmp

GLint cx, cy, format, bpp;

// 저장할 texture를 bind
glBindTexture(GL_TEXTURE_2D, id);

// cx,cy는 현재 texture의 width, height이다.
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cx);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cy);

// 현재 texture의 internal format을 얻는다. 여기서는 GL_RGBA만 대상으로 한다.
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);

if (format == GL_RGBA)
{
size_t data_size = 4 * cx*cy;

// 32비트 bmp텍스처의 픽셀버퍼 메모리할당
unsigned char *data = new unsigned char[4 * cx*cy];

// 현재 texture의 픽셀을 얻어온다.
glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, data);

// bmp구조를 만든다음 저장한다.
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
bfh.bfType = 0x4d42;

// Entire file size(40+14+data_size)
bfh.bfSize = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) + data_size;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = 54;// offset(14+40)

// major
bih.biSize = sizeof(BITMAPINFOHEADER);//40
bih.biWidth = cx;
bih.biHeight = cy;
bih.biPlanes = 1;
bih.biBitCount = 32;

// minor
bih.biCompression = BI_RGB;
bih.biSizeImage = data_size;
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;

FILE *fp = fopen("out.bmp", "wb");
if (fp) {
fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);
fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);
fwrite(data, 1, data_size, fp);
fclose(fp);
}
delete[] data;
}

// texture를 unbind
glBindTexture(GL_TEXTURE_2D, 0);

No comments:

Post a Comment