[OpenGL Tutorial] Color

사용자 삽입 이미지이번 장에서는 색에 대해서 알아보도록하자. 색을 지정하는 윈도우즈 API로 RGB함수가 있다. 인자를 3개 받는데 각각 빨간색, 녹색, 파란색을 갖으며 0~255사이의 값을 갖는다. OpenGL도 마찬가지인데 조금 다른 것은 이 3개의 인자로 실수형, 정수형, 배열형 등 다양하게 취한다는 것이다. 이때 주목해야 할것은 실수형일때와 정수형일때 각 값이 갖을수있는 범위이다. 실수형에 있어서는 0~1.0사이의 값을 갖으며 정수형은 우리가 알고 있는 0~255 사이의 값을 갖는다. 또한 배열을 인자로 받는 경우 그 배열의 각 셀은 빨간색, 녹색, 파란색의 값을 갖는다. OpenGL은 이 3개의 색상값 말고도 하나의 값을 더 갖는 경우가 있는데 이것은 바로 알파(Alpha) 값이다. Alpha값은 투명도라는 특성값이다. 이장에서 Alpha에 대한 설명은 하지 않겠다. 지금까지의 설명이 색에 대한 것들의 대부분이다. 이제 실제 코딩을 통해 익혀보자. 우리는 정육면체를 생성하고 각면에 서로 다른 색을 지정해 보는 것으로 이장을 마칠까한다.

우리가 사용할 코드는 1장의 소스코드에서 시작한다.

먼저 전역 변수를 하나 선언해야 한다. 물체를 지속적으로 회전시키는데 사용하는 변수이다. 소스 코드의 전역변수를 선언하는 곳에 아래의 코드를 추가하자.

GLfloat rot = 0.0f;

이제 물체를 그리고 각면에 서로 다른 색을 입히는 코드를 만들어보자. 물체를 그려주는 코드이므로 DrawGLScene 함수서 코딩을 해주면 된다. 다음은 그 내용이다.

int DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -5.0f);
    glRotatef(rot, 1.0f, 1.0f, 0.0f);
   
    glBegin(GL_QUADS);
    glColor3f(1.0f, 0.0f, 0.0f); // 1면을 Red으로 칠한다.
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
   
    glColor3f(1.0f, 1.0f, 0.5f); // 2면을 밝은 노란색으로 칠한다.
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);
   
    glColor3f(0.0f, 0.0f, 1.0f); // 3면을 Blue로 칠한다.
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);
   
    glColor3f(1.0f, 1.0f, 0.0f); // 4면을 노란색으로 칠한다.
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
   
    glColor3f(0.0f, 1.0f, 1.0f); // 5면을 Cyan으로 칠한다.
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    
    glColor3f(1.0f, 1.0f, 1.0f); // 6면의 한쪽 꼭지점의 색 지정
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glColor3f(1.0f, 0.0f, 1.0f); // 6면의 두번째 꼭지점의 색지정
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glColor3f(0.0f, 1.0f, 0.0f); // 6면의 세번째 꼭지점의 색지정
    glVertex3f(1.0f, 1.0f, 1.0f);
    glColor3f(1.0f, 1.0f, 0.0f); // 6면의 네번째 꼭지점의 색지정
    glVertex3f(1.0f, 1.0f, -1.0f);
    glEnd();    rot+=1.0f;
    if(rot>359) rot=1.0f;   

    return TRUE;
}

위 코드에서 중요한 것은 색을 지정하는 방법이다. 일단 색이 한번 지정되면 그 이후로 만들어지는 모든 물체에 대해서 그 색이 반영이 된다. GL_QUADS으로써 면을 생성하는데 면의 생성에 앞서 색을 지정해주면 그 면에 지정된 색이 칠해지게 된다. 그런데 약간 다른 것이 하나 있는데 그것은 6번째 면에 대한 색의 지정이다. 색의 지정을 각 점을 지정할때 마다 해주었는데 이것의 효과는 한 점에서 지정된 색과 다른 한점에서 지정된 색으로 두 점 사이로 부드러운 색변화로써 색을 지정하는 것이다. 즉 우리가 많이 보는 그라이디언트로 색이 지정되는 것이다.

이제 실행해보자. 아래는 그 실행 결과이다.

사용자 삽입 이미지

실제로 6면에 대해서 다른 면과는 다른 모습으로 색이 칠해졌음을 알수있다.

이로써 색에 대한 것들을 마친다.

[OpenGL Tutorial] Translate, Rotate and Scale Objects

사용자 삽입 이미지이번에는 화면상의 물체(점, 선, 폴리곤, 그리고 이들의 조합으로 이루어진 것들)을 움직여 보고 회전 시켜 보며 크기를 변경하는 것에 대해서 살펴보자. 이 장은 1장의 소스에서 출발을 한다.

먼저 이동과 회전 그리고 크기를 조절할 대상이 되는 간단한 물체를 생성해 보자. 뭐가 좋을까? 정육면체로 하자. 정육면체는 면이 6개이며 꼭지점이 8개인 물건(?)이다. 꼭지점이 8개 이므로 우리는 8개의 좌표를 알고 있어야 한다. 다음의 코드는 화면상에 정육면체를 그려주는 glDrawGLScene 함수의 코드이다.

int DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0f,0.0f,-10.0f);
    glColor3f(1.0f, 1.0f, 1.0f);
    glBegin(GL_LINE_LOOP);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glEnd(); 
   
    glBegin(GL_LINE_LOOP);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glEnd();
   
    glBegin(GL_LINES);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glEnd();
    return TRUE;
} 	

2장을 충분이 이해하고 있다면 전혀 어려운 부분이 없다. 이해가 가지 않는 독자가 있다면 2장을 보기 바란다. 코딩을 끝마친후 실행해보자. 다음은 그 실행 결과이다.사용자 삽입 이미지

혹시 이런 질문을 던지는 독자가 있을지도 모르겠다. 정육면체라고 했는데 앞면과 뒷면의 크기가 다르지 않는가?라고… 답부터 말하자면 앞면과 뒷면의 크기는 분명이 동일하다. 달라보이는 이유는 좀더 사실적인 연출을 위해 원근감이 적용되었기 때문이다.

자, 이제 물체의 이동, 회전, 크기조절(스케일)을 할 물체가 준비되었다.

먼저 독자에게 주지 시켜야 할것이 있다. 그것은 필자가 말한 물체의 이동, 물체의 회전, 물체의 크기조절이라는 말에서 풍기는 의미전달의 오류를 바로 잡고자 한다. OpenGL에서는 이러한 작업을 좌표체계를 변경함으로써 이루어진다는 것이다. 즉 물체의 이동에 있어서 실제로 물체를 이동하는 것이 아니고 좌표축을 이동시킨후에 물체를 그려주는 것이다. 회전도 마찬가지이다. 먼저 좌표축을 지정된 각으로 회전시킨후에 그 회전 좌표축 상에 물체를 그려주는 것이다. 결국 우리가 원하는 상태의 물체를 얻을 수 있다는 것이다. 자 지금까지의 모든 것을을 이해했다면 이제 실제 우리가 원하는 것들을 해보자!!

먼저 물체를 이동시켜보자. 왼쪽으로 1.0만큼, 위쪽으로 1.0만큼 좌표체계를 이동시키는 것은 어떻게 될까? 바로 다음 한줄의 코드가 그러한 일을 한다.

glTranslatef(1.0f, 1.0f, 0.0f); 

glTranslatef 함수의 첫번째 인자는 X축으로 이동값, 두번째와 세번째는 각각 Y축과 Z축으로의 이동값이다. 이 함수를 어디에 위치시켜야 하는가? 바로 물체를 그려주기 바로 전에 사용하면 되겠다. 다음 코드의 <*> 코드가 그 주인공이다.

int DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0f,0.0f,-10.0f);
    glColor3f(1.0f, 1.0f, 1.0f);
    
    glTranslatef(1.0f, 1.0f, 0.0f); // <*>
   
    glBegin(GL_LINE_LOOP);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glEnd(); 
   
       .
       .
       .
   
    return TRUE;
}

아래는 실행 결과이다. 우리가 원하는 대로 물체가 이동되었음을 알수있다.

사용자 삽입 이미지

이제 물체를 회전시켜보는 것을 알아보자. Z축으로 45도 회전시켜보는 것으로 예를 들어보자. 다음은 좌표축을 Z축으로 45도 회전시키는 코드이다.

glRotatef(45.0f, 0.0f, 0.0f, 1.0f)

첫번째 인자는 회전각(60도)이고 나머지 인자들은 X,Y,Z축상의 값들이다. (0.0, 0.0, 1.0)이 Z축을 기준으로 회전한다는 의미데 회전을 할때는 반드시 회전축이 필요하다. 바로 (0.0, 0.0, 1.0)이 회전축을 지정해 주는 것이다. 원점에서 (0.0, 0.0, 1.0)을 잇는 선, 바로 이 선이 회전축인 것이다. 그렇다면 이 코드의 위치는 어디인가? 마찬가지로 물체를 그려주기 바로 전에 위치하면 되겠다.

int DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0f,0.0f,-10.0f);
    glColor3f(1.0f, 1.0f, 1.0f);
    
    glRotatef(45.0f, 0.0f, 0.0f, 1.0f); // <*>
    
    glBegin(GL_LINE_LOOP);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glEnd(); 
    
         .
         .
         .
    
    return TRUE;
} 

다음은 실행 결과의 화면이다.

사용자 삽입 이미지

어떤가 생각했던 대로 회전이 이루어 졌는가?

이제 다음으로 물체의 크기조절에 대한 것에 대해 알아보도록 하겠다. 물체를 Y축으로 2배 늘려보자. 다른 좌표축보다 Y축으로 2배의 값으로 증가하는 좌표축을 구성하면 물체도 그에 따라 Y축으로 2배 늘어날 것이다. 바로 아래가 그러한 일을 하는 코드이다.

glScalef(1.0, 2.0f, 1.0f);

첫번째 인자는 X축 좌표값의 증가배수값이고 두번째와 세번째가 각각 Y, Z축의 좌표값의 증가 배수이다. 두번째 값을 2.0으로 잡아줌으로써 Y축의 좌표축 값을 다른 축에 비해 2배로 증가하게 되는 것이다. 이 코드의 위치해야할 곳은 또 어디인가? 마찬가지로 물체를 그리기 바로 전에 위치하면 된다.

int DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0f,0.0f,-10.0f);
    glColor3f(1.0f, 1.0f, 1.0f);
   
    glScalef(1.0, 2.0f, 1.0f);
   
    glBegin(GL_LINE_LOOP);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glEnd(); 
   
       .
       .
       .
   
    return TRUE;
} 

또 다음은 그 실행 결과이다.

사용자 삽입 이미지

어떤가. 우리가 원하는 대로 물체가 Y축으로 2배 길어졌다.

이로써 물체의 이동, 회전, 스케이링에 대한 장을 마치겠다.