빌보드 기법이란 사각형이 항상 시점을 바라보도록 만드는 것을 말한다. 결과적으로 관찰자가 어느 위치로 이동하더라도 사각형은 항상 같은 면을 관찰자에게 보여주게 된다. 응용예로써 넓은 대지위에 나무를 나타내고자 할때, 나무를 메쉬(Mesh)를 사용하여 모델링하지 않고 나무 이미지만으로 구현이 가능하다.
구현에 대한 핵심은, 항상 시점을 바라보도록 사각형을 이루는 네 좌표를 조정하여야 하는데, 이를 위해 Model View 행렬을 이용한다. Model-View 행렬에는 관찰자의 시점에 대한 정수직벡터와 정우측벡터에 대한 정보가 담겨있다.
일단 OpenGL에서 Model View 행렬을 얻는 코드를 알아보자.
Glfloat viewMatrix[16];
GlGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
ViewMatrix에 저장된 Model View 행렬이 다음 그림과 같다고 할 때 벡터(m1, m5, m9)은 시선 벡터와 수직인 위쪽 벡터이고, 벡터(m0, m4, m8)는 시선 벡터와 수직인 오른쪽 벡터이다.시선과 위쪽으로 수직인 벡터를 UpVector라 하고 오른쪽 방향으로 수직인 벡터를 RightVector라 하자. 이 두 벡터를 이용하여 사각형을 이루는 4개의 좌표를 조정하기 위해, 사각형의 중심 벡터를 centerVector라고 하면, 사각형을 이루는 4개의 좌표는 다음 그림과 같다. 위의 네 좌표를 스칼라값 Size를 적용하면 다음과 같다. Size는 사각형의 크기로 생각할 수 있다.
CenterPoint + (RightVector + UpVector) * (-Size))
CenterPoint + (RightVector -UpVector) * Size
CenterPoint + (RightVector + UpVector) * Size
CenterPoint + (UpVector -RightVector) * Size
실제로 구현 코드를 살펴보자.
void GL_Window::Draw(void)
{
// Clear Screen And Depth Buffer
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity (); // Reset The Modelview Matrix
glTranslatef (0.0f, 0.0f, -6.0f); // Translate 6 Units Into The Screen
glRotatef (angle, 0.0f, 1.0f, 0.0f); // Rotate On The Y-Axis By angle
// 모델뷰 행렬을 얻는다
float mat[16];
glGetFloatv(GL_MODELVIEW_MATRIX, mat);
// 모델뷰 행렬로부터 시선방향에 대해 수직으로 오른쪽 벡터와
// 수직으로 윗쪽 벡터를 정의한다.
vector3_t right(mat[0], mat[4], mat[8]);
vector3_t up(mat[1], mat[5], mat[9]);
glBindTexture(GL_TEXTURE_2D, texture[0]); // Select Our Texture
vector3_t pos(0.0f, 0.0f, 1.0f);
glBegin(GL_QUADS);
// 빌보드 기법을 적용하지 않은 폴리곤의 경우
// Bottom Left Of The Texture and Quad
// glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// Bottom Right Of The Texture and Quad
// glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Top Right Of The Texture and Quad
// glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
// Top Left Of The Texture and Quad
// glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
// 빌보드 기법이 적용된 폴리곤의 경우
// Bottom Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3fv((pos+(right+up)*(-1)).v);
// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3fv((pos+(right-up)*(+1)).v);
// Top Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3fv((pos+(right+up)*(+1)).v);
// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3fv((pos+(up-right)*(+1)).v);
glEnd();
glFlush();
}
위의 소스에서 이미 제작된 vector 클래스를 사용하였다. vector 클래스의 사용은 크게 어렵지 않으므로 10여분정도 투자하여 소스를 분석해보면 쉽게 이해할 수 있을 것이다.
빌보드 기법을 적용하지 않은 경우에 대한 소스 코드를 주석처리하였 놓았다. 주석을 제거하여 실행해 보면서 비교해보기 바란다.