🔺
GLUT Tutorials
  • Introduction
  • GLUT 설정
  • GLUT 초기화
  • 윈도우 크기 변화에 대응하기
  • 애니메이션
  • 키보드입력
  • 키 입력 예제 : 세상을 둘러 보아요~ :)
  • 키 입력 예제 : 세상을 둘러 보아요~ 2 탄:)
  • 마우스처리
  • 팝업메뉴의 소개
  • 서브(sub, 하위)메뉴
  • 메뉴 수정하기
  • 메뉴 교체하기
  • 비트맵폰트
  • 비트맵폰트와 직교투영
  • 외곽선 폰트
  • 초당프레임수(FPS) 계산하기
  • 게임모드에 대해서
  • 보조창(subwindow)에 대해서
  • 보조창의 크기변환 처리
  • 여러 보조창에 렌더링하기
Powered by GitBook
On this page

Was this helpful?

비트맵폰트와 직교투영

2D 폰트인 비트맵폰트의 쓰임새는 대개 사용자에게 정보를 제공하는 것입니다. 예를 들면, 어플리케이션에서 초당 프레임수를 알려주기 위해서 비트맵폰트를 사용할 수 있습니다. 이러한 정보들은 사용자가 카메라를 이리저리 움직이더라도 화면의 고정된 위치에 있어야할 것입니다. 정보를 출력할 위치를 계산할 때 2D 직교투영을 사용하는 것이 원근(투시)투영을 사용하는 것보다 계산하기가 쉽습니다. 그것은 직교투영을 사용하면 픽셀단위로 위치를 정할 수 있기 때문입니다.

비트맵폰트로 글자를 출력할 때에는 우선 원근투영을 사용해서 장면을 그린 다음에, 투영방법을 직교투영으로 변환 후 문자열을 출력합니다. 문자열을 출력하고 나서는 투영방법을 이전투영방법으로 돌려놔야하는데(이 경우는 원근투영으로) 그래야만 다음 프레임때 장면을 제대로 그릴 수 있기 때문입니다.

다음에 나오는 코드는 위에서 설명한 것을 렌더링함수로 표현해본 것입니다.:

void renderScene()
{
    // 장면을 렌더링하는데 필요한 모든 작업을 수행합니다.
    ....

    setOrthographicProjection();
    glPushMatrix();
        glLoadIdentity();
        renderBitmapString(5,30,GLUT_HELVETICA_18,"3D Tech");
    glPopMatrix();
    resetPerpectiveProjection();

    glutSwapBuffers();
}

두개의 새로운 함수인 setOrthograpicProjection 과 resetPerpectiveProjection 을 볼 수 있습니다. 첫번재 함수는 카메라를 조작하기 위해서 행렬모드를 GL_PROJECTION 으로 바꾸는 것으로 시작해서 이전 환경변수(이 예제에서는 원근투영과 그 밖에 다른것들)를 저장하고 투영행렬을 glLoadIdentity() 함수를 사용해서 초기화합니다. 그 다음에 gluOrtho 함수를 사용해서 투영방법을 직교투영을 설정합니다.

setOrthographicProjection 함수는 x 축과 y 축의 범위를 정하는 것이 주된 목적입니다. y 축을 뒤집고 나서 원점을 좌측 위로 옮깁니다. 이렇게 만들면 화면좌표계상에 글씨를 쓰기가 쉽워집니다.

변수 w 과 h 는 다른 곳에서 계산됩니다.(소스코드에서 changeSize 함수를 참고하세요.)

void setOrthographicProjection()
{
    // 행렬을 투영모드로 변경합니다.
    glMatrixMode(GL_PROJECTION);
    // 원근투영에 대한 환경변수를 
    // 가지고 있는 이전 행렬을 저장합니다.
    glPushMatrix();
        // 행렬을 초기화합니다.
        glLoadIdentity();
        // 2D 직교투영을 설정합니다.
        gluOrtho2D(0, w, 0, h);
        // y 축을 뒤집습니다.
        glScalef(1, -1, 1);
        // 좌측아래의 원점을 
        // 좌측위로 옮깁니다.
        glTranslatef(0, -h, 0);
    glMatrixMode(GL_MODELVIEW);
}

resetPerspectiveProjection 함수는 아주 간단합니다. 전에 직교투영을 설정하기 전에 저장해 놓은 원근투영을 다시 돌려놓는 것인데, 행렬모드를 GL_PROJECTION 으로 바꾸고 행렬을 팝(pop)하여 예전 설정들을 다시 돌려놓고 다시 행렬모드를 GL_MODELVIEW 로 설정해 주는게 전부입니다.

void resetPerspectiveProjection()
{
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
}

위의 함수들을 사용하면 문자열을 다닥다닥 붙여서 출력합니다. 물론 빈칸(스페이스키)은 제외입니다. 문자열에서 빈칸이 있으면 빈칸이 출력되겠죠. 여백을 주기 위해서는 현재 레스터 위치마다 간격을 유지해야합니다. 즉 x 좌표 값에 약간씩 여백을 주는 것이죠. 레스터 위치에 간격을 유지하는 방법에는 두가지가 있습니다. 하나는 비트맵폰트 한 글자를 그린 다음에 간격을 계산하는 것이고 두번째는 OpenGL 의 상태기계에 현재 레스터 위치가 어디쯤 되느냐고 묻는 것입니다.

첫번째 방법을 사용하려면 문자의 치수(너비와, 높이)를 알아야됩니다. 높이는 폰트들 높이의 최고값인 상수이지만, 너비는 매우 가변적입니다. 이 점을 위해서 GLUT 에는 문자의 너비를 알려주는 함수가 있습니다. 그 함수는 glutBitmapWidth 이며 아래는 이 함수의 설명입니다.

int glutBitmapWidth(void *font, int character); 

인자 설명:
font - GLUT 에 정의 되어 있는 폰트 중 하나입니다. 설정할 수 있는 값은 앞장을 살펴보세요.
character - 너비를 알고 싶은 문자입니다.

예를들어서, 각 문자간에 일정한 간격을 두고 문자열을 출력해주는 함수를 만들고자 한다면 아래의 코드처럼 만들 수 있습니다.

void renderSpacedBitmapString( float x, float y, int spacing, void *font, char *string)
{
    char *c;
    int x1=x;
    for (c=string; *c != '\0'; c++)
    {
        glRasterPos2f(x1,y);
        glutBitmapCharacter(font, *c);
        x1 = x1 + glutBitmapWidth(font,*c) + spacing;
    }
}

비슷한 예로, 문자마다 일정한 간격을 두어서 세로로 된 문자열을 출력하려면 아래의 코드처럼 만들 수 있습니다.

void renderVerticalBitmapString( float x, float y, int bitmapHeight, void *font, char *string)
{
    char *c;
    int i;
    for (c=string,i=0; *c != '\0'; i++,c++)
    {
        glRasterPos2f(x, y+bitmapHeight*i);
        glutBitmapCharacter(font, *c);
    }
}

bitmapHeight 변수는 쉽게 계산할 수가 있는데 그 것은 각 폰트의 높이 중 최고값을 알기 때문입니다.(소스코드를 참고하세요.)

GLUT 에는 아직 설명하지 않은 비트맵폰트를 위한 함수가 있는데 glutBitmapLength 함수입니다. 이 함수는 문자열의 총 픽셀길이를 계산해줍니다. 이 함수의 반환값은 문자열 내의 모든 문자들의 너비를 더한 값입니다. 다음은 이 함수의 설명입니다.

int glutBitmapLength(void *font, char *string); 

인자 설명:
font - GLUT 에 정의 되어 있는 폰트 중 하나입니다. 설정할 수 있는 값은 앞장을 살펴보세요.
string - 총 픽셀길이를 알고 싶은 문자열입니다.
Previous비트맵폰트Next외곽선 폰트

Last updated 5 years ago

Was this helpful?

위에서 살펴본 함수들의 사용법과 쓰임새는 를 참고하세요.

예제