프로그래밍/컴퓨터그래픽스

Hello OpenGL 예제 분석: Freeglut 기반 기초 코드 설명

studylida 2025. 4. 4. 18:34

 

전체 코드 (주석 포함)

// HelloGL.cpp : 이 파일에는 'main' 함수가 포함됩니다. 거기서 프로그램 실행이 시작되고 종료됩니다.

#include <iostream>
#include ".\include\GL\freeglut.h"  // Freeglut 헤더 포함

// 전역 변수: 윈도우의 초기 가로, 세로 크기
int Width = 600, Height = 600;

// 콜백 함수 선언
void Render();             // 화면을 그리는 함수
void Reshape(int w, int h); // 창 크기가 바뀔 때 호출되는 함수

int main(int argc, char **argv)
{
    // Freeglut 초기화
    glutInit(&argc, argv);

    // 윈도우 크기 설정
    glutInitWindowSize(Width, Height);

    // 디스플레이 모드 설정: 더블 버퍼링 + RGBA 색상
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);

    // 윈도우 생성
    glutCreateWindow("Hello OpenGL");

    // 콜백 함수 등록
    glutDisplayFunc(Render);    // 화면을 그릴 때 호출될 함수
    glutReshapeFunc(Reshape);   // 창 크기가 변경될 때 호출될 함수

    // 이벤트 루프 진입 (계속해서 콜백 함수들을 처리함)
    glutMainLoop();
    return 0;
}

void Render()
{
    // 배경 색상 설정 (흰색)
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    // 색상 버퍼 초기화 (배경색으로 지움)
    glClear(GL_COLOR_BUFFER_BIT);

    // 투영 행렬 설정: 관측 공간 지정
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-10.0, 10.0, -10.0, 10.0);  // 2D 직교 좌표계 설정

    // 모델뷰 행렬 선택 (모델링 좌표계)
    glMatrixMode(GL_MODELVIEW);

    // 빨간 삼각형 그리기
    glColor3d(1.0, 0.0, 0.0);               // 빨간색 설정
    glBegin(GL_TRIANGLES);                // 삼각형 그리기 시작
    glVertex2d(-2.0, -1.0);               // 첫 번째 꼭짓점
    glVertex2d(2.0, -1.0);                // 두 번째 꼭짓점
    glVertex2d(0.0, 3.0);                 // 세 번째 꼭짓점
    glEnd();                              // 그리기 끝

    // 파란 삼각형 그리기
    glColor3d(0.0, 0.0, 1.0);              // 파란색 설정
    glBegin(GL_TRIANGLES);
    glVertex2d(-2.0, 1.0);
    glVertex2d(0.0, -3.0);
    glVertex2d(2.0, 1.0);
    glEnd();

    // 버퍼 교환 (백 버퍼 -> 프론트 버퍼)
    glutSwapBuffers();
}

void Reshape(int w, int h)
{
    // 뷰포트 설정: 윈도우 전체 영역을 그리기 공간으로 사용
    glViewport(0, 0, w, h);
    // 전역 변수 업데이트
    Width = w;
    Height = h;
}

프로그램 구조 이해하기

OpenGL + Freeglut 프로그램은 다음과 같은 단계로 구성됩니다:

  1. 초기화 – glutInit, glutInitWindowSize, glutInitDisplayMode
  2. 윈도우 생성 – glutCreateWindow
  3. 콜백 등록 – glutDisplayFunc, glutReshapeFunc
  4. 이벤트 루프 진입 – glutMainLoop
  5. 렌더링 함수에서 도형 그리기 – Render()

더블 버퍼링이란?

더블 버퍼링(Double Buffering)은 깜빡임 없는 부드러운 화면 출력을 위해 사용하는 기법입니다.

  • OpenGL에서는 그림을 먼저 백 버퍼(화면 뒤쪽 메모리)에 그립니다.
  • 그리기가 끝나면 glutSwapBuffers()를 호출하여 백 버퍼와 프론트 버퍼(사용자에게 보이는 화면)를 교체합니다.
  • 이 방식 덕분에 도중에 그려지는 과정이 화면에 드러나지 않고, 완성된 그림만 사용자에게 보여집니다.

비유: 칠판에 그림을 다 그려놓고 한 번에 보여주는 방식! (그리는 도중은 사용자에게 보이지 않음)


초기화와 윈도우 설정

  • glutInit : Freeglut 라이브러리를 초기화합니다.
  • glutInitWindowSize : 생성할 윈도우의 크기를 설정합니다.
  • glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA) : 더블 버퍼링과 RGBA 색상 모드를 설정합니다.
  • glutCreateWindow("Hello OpenGL") : 실제 윈도우를 생성하고 타이틀을 설정합니다.

콜백 함수 등록과 이벤트 처리

  • glutDisplayFunc(Render) : 화면을 다시 그릴 때 호출될 함수를 등록합니다.
  • glutReshapeFunc(Reshape) : 창 크기가 바뀔 때 호출될 함수를 등록합니다.

OpenGL은 이벤트 기반으로 동작하며, 이 콜백 함수들은 glutMainLoop 내부에서 자동으로 호출됩니다.


Render 함수 분석: 도형을 그리는 핵심

배경색 설정 및 초기화

glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
  • 배경을 흰색으로 설정하고, 색상 버퍼를 초기화합니다.

좌표계 설정

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-10.0, 10.0, -10.0, 10.0);
  • 카메라 시점(투영 행렬)을 설정하고, 2D 직교 투영 좌표계를 구성합니다.

도형 그리기

glColor3d(1.0, 0.0, 0.0); // 빨간색
// 첫 번째 삼각형
...

glColor3d(0.0, 0.0, 1.0); // 파란색
// 두 번째 삼각형
...
  • glColor3d로 색상을 지정한 후, glBegin ~ glEnd 사이에 정점들을 나열하여 삼각형을 그립니다.

버퍼 교환

glutSwapBuffers();
  • 더블 버퍼링을 이용하여 백 버퍼에 그린 내용을 프론트 버퍼로 교환합니다.

Reshape 함수 분석: 창 크기 대응

glViewport(0, 0, w, h);
  • 창의 크기가 바뀌면 새로운 크기에 맞게 뷰포트를 다시 설정합니다.
  • OpenGL 좌표계를 창 크기에 맞게 매핑해주는 중요한 단계입니다.

실습 아이디어

  • 색상 바꿔 보기 (예: 초록색 glColor3d(0.0, 1.0, 0.0))
  • 삼각형 위치 바꾸기 (정점 좌표 수정)
  • 사각형 등 다른 도형 그리기 (GL_QUADS, GL_LINES 등 사용)
  • 좌표계 범위 변경 (gluOrtho2D 값 조정)

🔧 예제 1: 사각형 그리기

glColor3d(0.0, 1.0, 0.0); // 초록색
// 초록색 사각형
glBegin(GL_QUADS);
glVertex2d(-4.0, -4.0);
glVertex2d(4.0, -4.0);
glVertex2d(4.0, 4.0);
glVertex2d(-4.0, 4.0);
glEnd();
  • GL_QUADS는 네 개의 꼭짓점을 연결해 사각형을 만듭니다.
  • 중심이 원점인 정사각형을 화면에 그릴 수 있습니다.

🔧 예제 2: 좌표계 범위 변경하기

// Render 함수 내 gluOrtho2D 부분을 다음과 같이 바꿔보세요
gluOrtho2D(-20.0, 20.0, -15.0, 15.0);
  • 기존보다 더 넓은 가상 좌표계를 정의합니다.
  • 도형이 상대적으로 작게 보이며, 더 많은 공간을 표현할 수 있습니다.