2012.03.06 22:56 Android/OpenGL




먼저 이전에 텍스쳐는 2의 제곱수여야만 한다는 전제가 있었습니다.
그럼! 모든 이미지를 2의 제곱수로 만들어야 하나? 말도안되지요..

1. 2의 제곱수가 아닌 이미지 출력하기
안드로이드 프로젝트 생성시 포함되어있는 아이콘이 72*72군요. 2의 제곱수가 아닙니다~! 이걸로 해봅시다.

GLView.java
 onSurfaceCreated() 함수안에 만들어놓았던 소스를 변경하겠습니다.
Bitmap bmp = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher);
panda -> ic_launcher로 이미지를 바꾸어주었습니다.
빌드 후 실행해보면..

역시 이미지가 출력되지 않는군요~

GLGameRenderer.c
 setTextureData()함수에서 2의 제곱수만큼의 비어있는 버퍼를 생성하고 현재 픽셀값을 넣어주는 작업을 합니다.

int makeWidth, makeHeight;
char *makeBuf;
만들어질 버퍼의 가로, 세로 그리고 픽셀데이터를 저장할 버퍼를 선언합니다.

	makeWidth = makeHeight = 2;

	while( makeWidth < width )
		makeWidth = makeWidth << 1;

	while( makeHeight < height )
		makeHeight = makeHeight << 1;

	makeBuf = (char *)malloc((sizeof(char)*makeWidth*makeHeight)<<2);
가로와 세로는 2의 제곱수로 만들어야 하기 때문에 초기값을 2로 주겠습니다.
두개의 while문은 기존의 이미지를 모두 포함해야하기 때문에 기존 이미지보다 크면서 가장 가까운 2의 제곱수를 찾는 것입니다.
마지막으로 위에서 만든 가로, 세로만큼의 픽셀데이터를 가질 버퍼를 생성합니다.

RGBA 변환을 마친 후 데이터를 정리해보겠습니다.
아래 이미지중에서 검은색 배경부분은 새로 생성한 128*128크기의 버퍼입니다.
흰색 배경부분은 72*72이미지 입니다.
현재 검은색 버퍼를 완성한 상태이고, 아래 그림과같이 원하는 이미지를 정렬해서 넣어주는 작업이 필요합니다.



	int row, col;

	row = -1;
	col = 0;
	for ( i = 0; i < width*height*4; i += 4 )
	{
		if ( i % (width<<2) == 0 )
		{
			row++;
			col = 0;
		}

		makeBuf[(row*makeWidth<<2)+col] = buf[i];
		makeBuf[(row*makeWidth<<2)+col+1] = buf[i+1];
		makeBuf[(row*makeWidth<<2)+col+2] = buf[i+2];
		makeBuf[(row*makeWidth<<2)+col+3] = buf[i+3];
		col += 4;
	}
두개의 변수가 추가로 필요하네요. row(행)와 col(렬)
위 코드는 흰색배경부분의 픽셀을 검은색 배경 0,0위치부터 붙여나갑니다.
그러다가 흰배경부분 1줄을 다 그렸을때 2번째 줄을 이어서 그리면? 안되죠!
2번째 줄은 검은색 배경에도 2번째 줄부터 그려주어야 합니다. 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, makeWidth, makeHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)makeBuf);
텍스쳐의 가로, 세로 그리고 버퍼 부분이 바뀌었습니다.
새롭게 생성한 makeWidth, makeHeight크기의 텍스쳐를 생성할 것이며, 픽셀 데이터는 변환된 makeBuf를 넣어주어야지요.

사용한 메모리를 해제해 주는것도 잊지맙시다.
free(makeBuf);

빌드 후 실행해보면 ~ 



이미지는 정상 출력되는데... 뭔가 이상합니다.. 뭔가가...

우리가 원하는것은 72*72 크기의 이미지만을 그려주는 것이였는데 말이죠..


	GLfloat	g_textureWidth;
	GLfloat	g_textureHeight;

	g_textureWidth = (GLfloat)g_nPandaWidth / (GLfloat)makeWidth;
	g_textureHeight = (GLfloat)g_nPandaHeight / (GLfloat)makeHeight;
전역 변수로 g_textureWidth와 g_textureHeight를 추가시켜줍니다.
실제 텍스쳐의 크기 비율을 저장할 것입니다.

그리고 계속해서 코드를 추가시킵니다.
새롭게(makeBuf) 만든 텍스쳐의 크기중에 실제 텍스쳐가 차지하는 비율을 계산하고있습니다.
전체가 1이라고 보면 0.xxxx가 되겠지요?

setTextureData()에서 해야할 일은 끝이났습니다!

이젠 drawPanda()함수로 이동합니다.
texture 배열 부분이 있죠?
	GLfloat texture[8] = {
			0				, g_textureHeight,
			g_textureWidth	, g_textureHeight,
			0				, 0,
			g_textureWidth	, 0
	};
0을 제외한 부분이 1이였는데 이 값을 텍스쳐에서 실제 이미지가 해당되는 비율로 바꾸어주면 됩니다.

빌드 후 실행!
 



뭔가... 높이가 안맞아 보이는듯하네요.. 폰에서는 제대로 보입니다.

그런데, 자꾸 뒷배경이 검은색으로 나오네요..
이유는 ? 알파값! 투명처리가 안되고있습니다.

onSurfaceChanged() 함수에 

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
두줄을 추가시킵니다.

glEnable(GL_BLEND); 
 블렌딩 효과를 활성화.
 블렌딩이 적용되면 새로지정된 색상과 기존색상이 결합되어 옵션에 따라 효과가 달라집니다.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 음... 두 인자에따라 RGB에 계산을 하는데... 위 소스는 알파값을 적용하기 위한 효과이고.. 나머지는 찾아보시길..

두줄을 onSurfaceChanged()에 추가시킨 이유는 다른 블렌딩 효과를 사용안하고 그냥 알파값을 항상 사용하기때문에...-,.- 

빌드 후 확인해보면..



드디어 원하던 이미지 그대로 나왔습니다!


setTextureData() 함수에 변형부분이 많아 최종 소스를
 

void setTextureData(char *data, int width, int height)
{
	int i;
	int row, col;
	int makeWidth, makeHeight;
	char *buf;
	char *makeBuf;

	makeWidth = makeHeight = 2;

	while( makeWidth < width )
		makeWidth = makeWidth << 1;

	while( makeHeight < height )
		makeHeight = makeHeight << 1;

	makeBuf = (char *)malloc((sizeof(char)*makeWidth*makeHeight)<<2);
	buf = (char *)malloc((sizeof(char)*width*height)<<2);

	for (i = 0; i < width*height*4; i += 4)
	{
		buf[i]   = data[i+2];
		buf[i+1] = data[i+1];
		buf[i+2] = data[i];
		buf[i+3] = data[i+3];
	}


	row = -1;
	col = 0;
	for ( i = 0; i < width*height*4; i += 4 )
	{
		if ( i % (width<<2) == 0 )
		{
			row++;
			col = 0;
		}

		makeBuf[(row*makeWidth<<2)+col] = buf[i];
		makeBuf[(row*makeWidth<<2)+col+1] = buf[i+1];
		makeBuf[(row*makeWidth<<2)+col+2] = buf[i+2];
		makeBuf[(row*makeWidth<<2)+col+3] = buf[i+3];
		col += 4;
	}

	g_nPandaWidth = width;
	g_nPandaHeight = height;

	g_textureWidth = (GLfloat)g_nPandaWidth / (GLfloat)makeWidth;
	g_textureHeight = (GLfloat)g_nPandaHeight / (GLfloat)makeHeight;

	glGenTextures(1, &g_textureName);
	
	glBindTexture(GL_TEXTURE_2D, g_textureName);
	
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, makeWidth, makeHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)makeBuf);

	free(buf);
	free(makeBuf);
}
요래~



posted by 베라뷰