[App 개발] NeHe Lesson 5
본문
피라밋의 색상은 Smooth Coloring을 이용하여 색칠하고, 육면체는 각각의 면에 다른 색깔을 칠해보도록 하겠습니다.
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);
glRotatef(rtri,0.0f,1.0f,0.0f);
glBegin(GL_TRIANGLES);
여러분중에는 지난 시간 코드를 이용해서 따로 3차원 물체를 만들어보신 분이 계실지 모르겠습니다. 그중에 많은 분들이 “내가 만든 물체가 축을 따라서 회전하지 않고 제멋대로 화면을 휘젓고 다니고 있어요”하고 하소연하는 분들이 계십니다. 여러분이 만든 물체가 축을 따라 회전하게 만들려면 물체를 그 축을 따라서 만들어야 합니다. 기억하셔야 할 것은 물체의 정 가운데는 항상 x=0, y=0, z=0이어야 합니다.
다음은 중심 축 주위로 피라밋을 만들어 보겠습니다. 피라밋의 맨 가운데 꼭지는 중앙의 가장 높은 부분에 있고, 피라밋 가장 밑부분은 중앙의 가장 밑에 놓습니다. 가운데 꼭지점은 정가운데 (0점) 에 놓이게 되며, 밑면은 중심으로부터 1유닛씩 좌우로 펼쳐져 있습니다.
잘 보시면 모든 삼각형이 반시계방향으로 그려지는 것을 알 수 있을 것입니다. 나중에 자세히 설명할 것입니다만, 지금은 한 번 시계방향이나 반시계방향으로 만들어보시는 것도 좋은 연습이 되겠습니다. 하지만, 그 두 가지를 특별한 이유 없이 섞어 쓰지는 마십시오.
이제 앞면부터 그려나가겠습니다. 모든 점이 가운데 꼭지점을 공유하고 있기 때문에 그 점을 모든 삼각형에서 빨간색으로 지정할 것입니다. 삼각형 밑에 있는 두 점의 색깔은 상대적으로 만약 앞면의 왼쪽이 녹색 오른쪽이 파란색이었다면 오른쪽 면의 삼각형은 왼쪽이 파란색 오른쪽을 녹색으로 놓습니다. 이렇게 놓음으로써 피라밋의 밑꼭지점이 각각 같은 색을 갖게 됩니다.
glColor3f(1.0f,0.0f,0.0f); // 빨간색
glVertex3f( 0.0f, 1.0f, 0.0f); // 위꼭지점
glColor3f(0.0f,1.0f,0.0f); // 녹색
glVertex3f(-1.0f,-1.0f, 1.0f); // 왼쪽 꼭지점
glColor3f(0.0f,0.0f,1.0f); // 파란색
glVertex3f( 1.0f,-1.0f, 1.0f); // 오른쪽 꼭지점
이제 오른쪽면을 그립니다. 밑에 두 꼭지점이 오른쪽에 놓이게 될 것이고, 위 꼭지점은 y축으로 하나 올라가 있고, x축의 값은 가운데로부터 밑의 두 점간의 기울기를 결정하는 역할을 하게 됩니다.
그리고 이번에는 왼쪽이 파란색입니다. 그렇게 하면 앞면의 오른쪽과 같은 색깔을 갖게 되어, 파란색이 한 점을 중심으로 양쪽 면을 향하여 퍼져 나가는 모습이 피라밋의 오른쪽 앞면에 만들어지게 됩니다.
그리고 모든 삼각형 그리는 루틴이 동일한 glBegin(GL_TRIANGLES) glEnd() 함수 사이에 놓여있습니다. 왜냐하면 지금 그리는 모든 물체는 삼각형이기 때문에 계속해서 기록되는 세 점이 삼각형을 표현한다는 것을 OpenGL이 알고 있기 때문입니다. 그래서 처음에 세 점으로 삼각형을 그리고 났는데 또 다시 세 점이 있으면 다른 삼각형을 그리는 것으로 간주하게 됩니다. 만약에 다음에 네 점이 놓여있다면, OpenGL은 처음의 세 점을 가지고 삼각형을 그리고 마지막 한 점을 새로운 삼각형의 출발점으로 간주하지, 절대로 사각형을 그리지 않습니다. 실수로 점을 하나 더 집어넣는 일이 없도록 주의하십시오.
glColor3f(1.0f,0.0f,0.0f); // 빨간색
glVertex3f( 0.0f, 1.0f, 0.0f); // 위 꼭지점
glColor3f(0.0f,0.0f,1.0f); // 파란색
glVertex3f( 1.0f,-1.0f, 1.0f); // 왼쪽 꼭지점
glColor3f(0.0f,1.0f,0.0f); // 녹색
glVertex3f( 1.0f,-1.0f, -1.0f); // 오른쪽 꼭지점
이제 뒷면을 그립니다. 색깔 놓는 것이 다시 바뀌어서 왼쪽 꼭지점이 녹색입니다. 오른쪽 면의 만나는 꼭지점이 녹색이기 때문입니다.
glColor3f(1.0f,0.0f,0.0f); // 빨간색
glVertex3f( 0.0f, 1.0f, 0.0f); // 위 꼭지점
glColor3f(0.0f,1.0f,0.0f); // 녹색
glVertex3f( 1.0f,-1.0f, -1.0f); // 왼쪽 꼭지점
glColor3f(0.0f,0.0f,1.0f); // 파란색
glVertex3f(-1.0f,-1.0f, -1.0f); // 오른쪽 꼭지점
마지막으로 왼쪽면을 그립니다. 한번 더 색상이 바뀌어서 이번에는 왼쪽을 파란색으로 칠해서 뒷면의 오른쪽 꼭지점으로부터 파란색이 퍼져나가게 만들 것입니다. 오른쪽은 녹색으로 칠해서 앞면의 왼쪽 꼭지점에서 녹색이 퍼져나가도록 만듭니다.
이렇게 해서 피라밋을 다 그렸습니다. 예제에서 피라밋은 y축을 중심으로 회전할 것이고 우리는 밑면을 볼 일이 없기 때문에 밑을 그릴 필요는 없습니다. 만약 그리고 싶으시다면 사각형으로 밑면을 그려 보시고 x축으로 회전시켜서 제대로 잘 그렸는지 확인해 보십시오. 그릴 적에 피라밋 밑 꼭지점들의 색깔하고 잘 맞추도록 주의하십시오.
glColor3f(1.0f,0.0f,0.0f); // 빨간색
glVertex3f( 0.0f, 1.0f, 0.0f); // 위 꼭지점
glColor3f(0.0f,0.0f,1.0f); // 파란색
glVertex3f(-1.0f,-1.0f,-1.0f); // 왼쪽 꼭지점
glColor3f(0.0f,1.0f,0.0f); // 녹색
glVertex3f(-1.0f,-1.0f, 1.0f); // 오른쪽 꼭지점
glEnd(); // 피라밋을 다 그렸다
이제 육면체를 그릴 시간입니다. 여섯 개의 사각형을 모두 반시계방향으로 그리게 될 것입니다. 따라서 시작점이 오른쪽 위, 두 번째는 왼쪽 위, 세 번째는 왼쪽 밑, 마지막은 오른쪽 밑의 순서로 사각형을 그립니다. 뒷면을 그릴 때에는 마치 시계방향으로 그리는 것처럼 보일 것입니다만, 만약 우리가 뒤에서 육면체를 관찰한다고 하면 왼쪽 사각형은 오른쪽에 놓이게 되고, 오른쪽 사각형은 왼쪽에 놓이게 됩니다.
이번 예제에서는 육면체를 화면 바깥으로 조금 더 멀리 밀어놓아서 육면체 크기와 삼각형 크기를 비슷하게 맞추어 놓을 것입니다. 만약 육면체를 6유닛만 밀어놓으면 피라밋보다 엄청 크게 보이게 되어서 물체의 일부분이 화면 끝에 가려서 안 보이게 되기 때문입니다. 직접 값을 바꾸어 보면서 육면체가 멀리 갈 수록 조그맣게 보이고 가까이 올수록 크게 보이는지를 확인해 보십시오. 이런 효과가 나는 이유는 Perspective 모드이기 때문입니다. 멀리 있는 물체는 작게 보이는 게 정상이죠. :)
glLoadIdentity();
glTranslatef(1.5f,0.0f,-7.0f); // 화면 오른쪽으로 축을 이동
glRotatef(rquad,1.0f,1.0f,1.0f); // 육면체를 회전시킨다
glBegin(GL_QUADS); // 사각형 그리기 시작
먼저 육면체의 윗면부터 그려보겠습니다. 육면체의 중앙으로부터 1유닛 위로 이동하기 때문에 y축 값이 항상 1이 됩니다. z평면에 사각형을 그리게 되기 때문에 결과적으로 화면 안쪽으로 사각형을 그리게 됩니다. 윗면의 오른쪽 위 꼭지점부터 그리기 시작합니다. 오른쪽으로 1유닛, 화면 안쪽으로 1유닛 이동합니다. 두 번째 점은 왼쪽으로 1 유닛, 화면 안쪽으로 1 유닛 이동합니다. 이제 밑 꼭지점을 그립니다. 이번에는 관찰자 쪽을 향하여 화면 밖으로 1유닛 움직여 꼭지점을 그립니다.
glColor3f(0.0f,1.0f,0.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); // 오른쪽 아래
밑면을 그리는 방법은 밑으로 한 유닛 이동하는 것 외에는 동일합니다. 따라서 y축으로는 항상 1입니다. 만약 밑에서 육면체를 관찰한다고 하면 밑면으로 만든 사각형의 오른쪽 위 꼭지점이 관찰자에 가까운 점입니다. 멀리 있는 점부터 그리지 않고 가까운 점부터 먼저 그리도록 하겠습니다. 그리고는 왼쪽에 있는 가까운 점, 그리고 화면 밖으로 나가 있는 두 점 순서로 그리겠습니다.
만약에 다각형 그리는 순서가 시계방향인지 아닌지에 별로 신경쓰고 싶지 않으시다면 그냥 위쪽 면을 그리던 코드를 갖다가 복사해서 붙여 넣으시고 y축 값을 1로 바꾸시면 되기는 됩니다만, 나중에 텍스쳐 매핑이나 그런 것 할 때에 그렇게 하시면 아주 요상한 결과를 가져오게 될 것입니다.
glColor3f(1.0f,0.5f,0.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); // 오른쪽 아래
이제 정면 사각형을 그릴 차례입니다. 중앙으로부터 관찰자 방향으로 1유닛 떨어져서 정면을 그립니다. 따라서 z축의 값은 모두1입니다. 피라밋을 그릴 때에는 z축 값이 항상 1이 아니었고 위 꼭지점의 z값이 0이었습니다. 만약 여기서 z축의 값을 0으로 놓게 되면 그 점으로 경사가 져서 사각형이 그려지게 됩니다. 지금은 그런 사각형을 그릴 때가 아닙니다.
glColor3f(1.0f,0.0f,0.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); // 오른쪽 아래
뒷면은 앞면 그리는 방법과 비슷하지만 화면 깊숙히 들어가 있습니다. 따라서 z축의 값이 모두 1입니다.
glColor3f(1.0f,1.0f,0.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); // 왼쪽 위
앞으로 두 개 남았군요. 지금까지 그랬던 것처럼 한 축의 값은 언제나 동일합니다. 이번에는 x축의 값이 모두 1입니다. 왜냐하면 이번에 그릴 면은 육면체의 왼쪽 면이어서 모든 꼭지점이 중심에서 왼쪽에 놓이기 때문입니다.
glColor3f(0.0f,0.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); // 오른쪽 아래
이제 마지막 면만 그리면 완성입니다. 이번에는 x축 값이 모두 1입니다. 반시계방향으로 그리고 있습니다. 만약 원하시면 이 부분은 놔두시고 상자를 만들어 보셔도 됩니다.
뭔가 다른 것을 해보고 싶으시다면, 각각의 꼭지점에 다른 색상을 지정하여 피라밋에서 했던 것처럼 색 번짐을 육면체에도 만들어보셔도 됩니다. 제 웹페이지에 있는 Evil’s first GL demo 에서 blended cube 예제를 받아서 해보세요. 실행하고 탭 키를 누르시면 모든 면으로 색상이 퍼져나가는 아름다운 색상의 육면체를 보실 수 있을 것입니다.
glColor3f(1.0f,0.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(); // 사각형 그리기 끝
rtri+=0.2f;
rquad-=0.15f;
return TRUE;
}
최신글이 없습니다.
최신글이 없습니다.
댓글목록 0