opengl이나 다이렉트x에서 텍스트를 표시할때는 주로 글씨자체를 텍스쳐화 시켜서 표현하고는 합니다.
일반적으로 텍스트를 그냥 그리는것은 그자리에서 이미지를 만들고 렌더링을 하기때문에 속도도 느려지고
어느부분은 지원을 안해주는곳도 있습니다. 여기서 이미지를 만들고 렌더링하는 부분을 따로 만드는것이
이번 테크닉의 핵심입니다. 물론 퍼포먼스 자체도 텍스쳐화 하는것이 더 좋습니다. 처음에 한번 이미지를
만들고 나중엔 렌더링만 하기 때문이죠.
클래스에서 다른부분은 제끼고 텍스쳐생성 부분만 설명하겠습니다. 다른부분은 조금만 공부해도
알수있는 부분입니다.
public class Text3d {
private IntBuffer mVertexBuffer;
private IntBuffer mColorBuffer;
private ByteBuffer mIndexBuffer;
private FloatBuffer mfTexBuffer;
private int mTextureID;
public Text3d(){
int one = 50;
int vertices[] = {
0, one, 0,
one, one, 0,
0, 0, 0,
one, 0, 0,
};
float tex[] = {
0.0f ,0.0f,
1.0f,0.0f,
0.0f ,1.0f,
1.0f,1.0f,
};
one = 100000;
int colors[] = {
one, one, one, one,
one, one, one, one,
one, one, one, one,
one, one, one, one,
};
byte indices[] = {
0, 1, 2,
1, 3, 2,
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
mVertexBuffer = vbb.asIntBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
ByteBuffer tbb = ByteBuffer.allocateDirect(tex.length*4);
tbb.order(ByteOrder.nativeOrder());
mfTexBuffer = tbb.asFloatBuffer();
mfTexBuffer.put(tex);
mfTexBuffer.position(0);
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
cbb.order(ByteOrder.nativeOrder());
mColorBuffer = cbb.asIntBuffer();
mColorBuffer.put(colors);
mColorBuffer.position(0);
mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
mIndexBuffer.put(indices);
mIndexBuffer.position(0);
}
public void TexCreate(GL10 gl,Context mContext)
{
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
mTextureID = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_REPLACE);
Bitmap mBitmap;
Canvas mCanvas;
Bitmap.Config config = Bitmap.Config.ARGB_8888;
mBitmap = Bitmap.createBitmap(128, 128, config);
mCanvas = new Canvas(mBitmap);
mBitmap.eraseColor(0);
mCanvas.drawColor(0x00ffffff);
Paint Pnt = new Paint();
Pnt.setColor(0xff00ff00);
Pnt.setTextSize(128);
Pnt.setAntiAlias(false);
Pnt.setTextScaleX(1);
mCanvas.drawText("B", 0, 128, Pnt);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
mBitmap.recycle();
}
public void draw(GL10 gl)
{
gl.glFrontFace(GL10.GL_CW);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glColor4f(1f, 1f, 1f, 1f);
gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_MODULATE);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glActiveTexture(GL10.GL_TEXTURE0);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mfTexBuffer);
gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
}
}
위 클래스의 TexCreate함수를 가져왔습니다. 여기서 하나하나 설명 하겠습니다.
public void TexCreate(GL10 gl,Context mContext)
{
여기는 텍스쳐를 생성하고 id에 연결하는 부분입니다. 그렇게 어렵지는 않습니다. 패스!
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
mTextureID = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_REPLACE);
여기서 부터가 핵심입니다.
Bitmap mBitmap; 비트맵입니다
Canvas mCanvas; 켄버스입니다.
Bitmap.Config config = Bitmap.Config.ARGB_8888; 비트맵을 설정해줍니다 ARGB_8888
mBitmap = Bitmap.createBitmap(128, 128, config); 128x128 ARGB_8888 비트맵을 생성합니다
mCanvas = new Canvas(mBitmap); 비트맵으로 켄버스를 생성합니다. 켄버스에
그려지는 그림은 비트맵에 그려지게 됩니다.
비트맵은 2의 승수로 만드시길 추천합니다.
잘못하면 안나오는수가 있습니다.
mBitmap.eraseColor(0); 비트맵을 지정색으로 지워줍니다
mCanvas.drawColor(0x00ffffff); 켄버스에 드로우컬러를 설정해줍니다. 글씨로 그려지는
나머지 부분이 그려집니다. 투명하게 하고싶으면 알파값을
빼줍시다...
Paint Pnt = new Paint(); 페인트 객체를 생성합니다.
Pnt.setColor(0xff00ff00); 페인트의 색을 결정해 줍시다. 즉 글씨의 색이 됩니다. 지금은 녹색!
Pnt.setTextSize(128); 텍스트의 사이즈를 정해줍니다.128짜리 사이즈니까 꽉차게 되겠죠!
Pnt.setAntiAlias(false); 안티얼라이즈 취향에 맞게 선택해 줍시다.. true로 하면 조금
부드러운 글씨가 나옵니다. 하지만 텍스트 사이즈가 작으면 작
으면 작을수록 형체를 알아보기 힘듭니다. 사이즈가 클때 추천!
Pnt.setTextScaleX(1); 장평을 설정해줍니다. 1이니까 그대로 나옵니다.
mCanvas.drawText("B", 0, 128, Pnt); 드디어 대망에 그리기입니다! 비트맵에 B가 찍혀서 나옵니다.
여기서 원하시는 단어나 문장을 입력하시면 되겠죠..
지금은 텍스쳐에 글씨를 꽉 차게 그립니다. 문장을 쓰시려면
텍스트 사이즈를 작게 잡거나 비트맵을 크게 잡으셔야 합니다.
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0); 비트맵을 텍스쳐로 보내줍니다..
mBitmap.recycle(); 비트맵을 해재시켜줍니다...
}
이제 만들어진 텍스쳐를 위에 draw함수처럼 폴리곤에 적용만 시켜주면 화면에 B가 찍혀나오는것을
볼수있습니다. 테크닉 자체가 3d를 쓰려면 필수이긴하지만 어느정도 난이도가 있는 테크닉입니다.