Skip to content

OpenGL

긴 여정을 시작하기 전에 먼저 OpenGL이 실제로 무엇인지 알아야 합니다. OpenGL은 그래픽과 이미지를 조작하는 데 사용할 수 있는 다양한 함수를 제공하는 API 입니다. 그러나 OpenGL 자체는 API가 아니라 크로노스 그룹에서 개발하고 관리하는 사양(모양)일 뿐입니다.

OpenGL 사양은 각 함수의 결과와 출력, 그리고 실행 방식만을 명시합니다. 따라서 이 사양을 어떤 방식으로 구현하는지는 온전히 개발자의 몫입니다. OpenGL 사양은 구현 세부 정보를 제공하지 않으므로, 실제로 개발된 OpenGL 버전은 결과가 사양을 준수하는 한(즉, 사용자에게 동일한 결과를 제공하는 한) 서로 다른 구현 방식을 가질 수 있습니다.

실제 OpenGL 라이브러리를 개발하는 사람들은 보통 그래픽 카드 제조업체입니다. 구입하는 각 그래픽 카드는 해당 카드(시리즈)에 맞춰 특별히 개발된 특정 버전의 OpenGL을 지원합니다. Apple 시스템(맥북 등)을 사용하는 경우, OpenGL 라이브러리는 Apple에서 직접 관리하며, Linux에서는 그래픽 공급업체의 버전과 오픈소스 기여자들이 이러한 라이브러리를 변형한 버전이 함께 제공됩니다. 따라서 OpenGL이 예상치 못한 이상한 동작을 보일 경우, 이는 그래픽 카드 제조업체(또는 라이브러리를 개발/관리하는 업체)의 잘못일 가능성이 높습니다.

대다수의 그래픽 카드 구현은 그래픽 카드 제조업체에서 직접 제작하므로, 구현에 버그가 발생할 경우 일반적으로 비디오 카드 드라이버를 업데이트하면 해결됩니다. 드라이버에는 카드가 지원하는 최신 버전의 OpenGL이 포함되어 있습니다. 따라서 그래픽 드라이버를 주기적으로 업데이트하는 것이 좋습니다.

크로노스 그룹에서는 모든 OpenGL 버전에 대한 사양 문서를 공개합니다. 이것에 대해 관심이 있다면 3.3 버전(이번에 사용할 버전)의 OpenGL 사양을 여기에서 확인할 수 있습니다. OpenGL에 대한 자세한 내용을 알고 싶다면 참고할 만한 자료입니다(대부분 구현 내용이 아닌 결과만 설명합니다). 또한 이 사양은 해당 함수의 정확한 작동 방식을 찾는 데 유용한 참고 자료입니다.

코어 프로파일과 즉시 모드

예전에는 OpenGL을 사용하면 즉시 모드(Immediate mode)(또는 고정 기능 파이프라인이라고 함)로 개발할 수 있었습니다. 이는 그래픽을 그리는 사용하기 쉬운 방법이었습니다. OpenGL의 기능 대부분은 라이브러리 내부에 숨겨져 있었고 개발자는 OpenGL의 계산 방식을 크게 제어할 수 없었습니다. 결국 개발자들은 더 큰 유연성을 갈망하게 되었고, 시간이 지남에 따라 사양도 더욱 유연해졌습니다. 개발자는 그래픽에 대한 제어력을 더 많이 확보하게 되었습니다. 즉시 모드는 사용하고 이해하기 매우 쉽지만 매우 비효율적입니다. 이러한 이유로 OpenGL 사양에서는 3.2 버전부터 즉시 모드 사용을 권장하지 않게 되었고(deprecate), 개발자들이 코어 프로파일(Core-profile)을 사용하여 개발하도록 동기를 부여하기 시작했습니다. 코어 프로파일 모드는 조금 더 현대적인 OpenGL 모드로, 오래되고 사용을 권장하지 않는 모든 기능이 제거된 모드입니다.

즉시 모드는 조금 더 사용하기 쉽지만 비효율적이고, 기능이 제한되어 있습니다. 그리고 코어 프로파일 모드에선 더 이상 사용되지 않는 함수 등이 제거되어 있고, 개발자가 그래픽 프로그래밍에 관여할 수 있는 부분이 조금 더 많은 현대적인 모드입니다.

OpenGL의 코어 프로파일을 사용할 때 OpenGL은 최신 방식을 사용하도록 강요합니다. OpenGL의 더 이상 사용되지 않는 함수 중 하나를 사용하려고 할 때마다 OpenGL은 오류를 발생시키고 그리기를 중단합니다. 최신 방식을 배우는 장점은 매우 유연하고 효율적이라는 것입니다. 하지만 배우기가 더 어렵다는 단점도 있습니다. 즉시 모드는 OpenGL이 수행하는 실제 연산에서 많은 부분을 추상화했기 때문에 배우기는 쉬웠지만 OpenGL의 실제 작동 방식을 파악하기는 어려웠습니다. 최신 방식을 사용하려면 개발자가 OpenGL과 그래픽 프로그래밍에 대한 진정한 이해를 요구하며, 다소 어렵기는 하지만 훨씬 더 높은 유연성과 효율성을 제공하고, 무엇보다도 그래픽 프로그래밍에 대한 이해도를 높여줍니다.

이 책이 핵심 OpenGL 버전 3.3을 기반으로 작성된 이유도 바로 여기에 있습니다. 비록 더 어렵더라도, 그만한 가치가 충분히 있습니다.

현재 OpenGL의 상위 버전(4.6 작성 시점)을 선택할 수 있는데, "OpenGL 4.6이 나왔는데 왜 OpenGL 3.3을 배워야 하나요?"라는 의문이 들 수 있습니다. 이 질문에 대한 답은 비교적 간단합니다. 3.3부터 시작되는 향후 모든 OpenGL 버전은 OpenGL의 핵심 메커니즘을 변경하지 않고 OpenGL에 유용한 추가 기능을 추가합니다. 최신 버전은 동일한 작업을 수행하는 데 약간 더 효율적이거나 유용한 방법이 존재할 뿐입니다. 결과적으로 OpenGL 3.3 이상의 버전은 기본적인 작동 방식이 동일하므로 OpenGL 3.3을 사용합니다. 많은 경험이 쌓였다면 새로운 OpenGL 기술을 응용하기 더 쉬워질 것입니다.

최신 버전의 OpenGL 기능을 사용하는 경우, 최신 그래픽 카드에서만 애플리케이션을 실행할 수 있습니다. 이러한 이유로 대부분의 개발자는 일반적으로 하위 버전의 OpenGL을 사용하고, 선택적으로 상위 버전의 기능을 활성화합니다.

일부 장에서는 더욱 현대적인 기능을 사용할 수 있으며, 그러한 기능은 그대로 기록되어 있습니다.

2025년 기준으로도 마지막 OpenGL 버전은 2017년에 출시된 4.6이며, Vulkan이라는 새로운 API가 나왔기 때문에 더 업데이트 될 것 같지는 않으나, Vulkan은 OpenGL과 많이 다르고 사용하기 훨신 어렵기 때문에 컴퓨터 그래픽스를 처음 사용한다면 OpenGL을 사용해주세요. Vulkan은 나중에 해도 충분합니다.
그리고 더 이상 업데이트 되지 않는것에서 두려움을 느낀다면 걱정하지 마세요. OpenGL은 아직도 많이 사용되는 API입니다.

확장 기능

OpenGL의 가장 큰 특징 중 하나는 확장 기능 지원입니다. 그래픽 회사가 새로운 기술이나 렌더링 최적화를 도입할 때마다 드라이버에 구현된 확장 기능을 통해 이를 확인할 수 있습니다. 애플리케이션이 실행되는 하드웨어가 이러한 확장 기능(Extensions)을 지원하면 개발자는 해당 확장 기능이 제공하는 기능을 사용하여 더욱 고급적이고 효율적인 그래픽을 구현할 수 있습니다. 이렇게 하면 그래픽 개발자는 OpenGL이 향후 버전에 해당 기능을 포함할 때까지 기다릴 필요 없이, 그래픽 카드에서 해당 확장 기능을 지원하는지 확인하는 것만으로 새로운 렌더링 기술을 계속 사용할 수 있습니다. 일반적으로 확장 기능이 널리 사용되거나 매우 유용하면 향후 OpenGL 버전에 포함되는 경우가 많습니다.

개발자는 이러한 확장 기능을 사용하기 전에(또는 OpenGL 확장 라이브러리를 사용하기 전에) 사용 가능한 확장 기능이 있는지 확인해야 합니다. 이를 통해 개발자는 확장 기능의 사용 가능 여부에 따라 작업을 더 효율적으로 수행할 수 있습니다.

if(GL_ARB_extension_name)
{
    // 멋진 신기술을 사용해 보세요.
}
else
{
    // 오래된 방법을 사용해봅시다.
}

OpenGL 버전 3.3에서는 대부분 기술에 확장 기능이 거의 필요하지 않지만, 필요한 경우 적절한 지침이 제공됩니다.

상태 머신

OpenGL은 그 자체로 하나의 거대한 상태 머신(State machine)입니다. 상태 머신이란 OpenGL이 현재 어떻게 작동해야 하는지를 정의하는 변수들의 모음입니다. OpenGL의 상태는 일반적으로 OpenGL 컨텍스트(context)라고 불립니다. OpenGL을 사용할 때, 우리는 종종 몇 가지 옵션을 설정하거나 버퍼를 조작하여 상태를 변경한 다음, 현재 상태에 따라 렌더링합니다.

예를 들어 삼각형 대신 선을 그리도록 OpenGL에 지시할 때마다, OpenGL이 그림을 그리는 방식을 설정하는 컨텍스트 변수를 변경하여 OpenGL의 상태를 바꿉니다. 컨텍스트를 변경하여 OpenGL에 선을 그리도록 지시하는 순간, 이후의 그리기 명령은 삼각형 대신 선을 그리게 됩니다.

OpenGL을 사용하다 보면 컨텍스트를 변경하는 여러 상태 변경(state-changing) 함수와 OpenGL의 현재 상태에 따라 연산을 수행하는 여러 상태 사용(state-using) 함수를 접하게 됩니다. OpenGL이 기본적으로 하나의 거대한 상태 머신이라는 점을 명심하면 대부분의 기능을 쉽게 이해할 수 있습니다.

객체

OpenGL 라이브러리는 C 언어로 작성되었으며 다른 언어로 파생될 수 있는 부분이 많지만, 핵심은 여전히 ​​C 라이브러리라는 점입니다. C 언어의 여러 구문들이 다른 고급 언어로 잘 변환되지 않는 경우가 많기 때문에, OpenGL은 여러 추상화 개념을 염두에 두고 개발되었습니다. 그중 하나가 OpenGL의 객체(object)입니다.

OpenGL에서 객체는 OpenGL 상태의 일부를 나타내는 옵션들의 모음입니다. 예를 들어, 드로잉 창의 설정을 나타내는 객체가 있을 수 있으며, 이 객체를 통해 창의 크기, 지원하는 색상 수 등을 설정할 수 있습니다. 객체는 C 언어의 구조체와 유사한 형태로 시각화할 수 있습니다:

struct object_name {
    float  option1;
    int    option2;
    char[] name;
};
일반적으로 객체를 사용하려는 경우 다음과 같은 형태를 띨 수 있습니다(OpenGL의 컨텍스트는 큰 구조체로 시각화됨).
// OpenGL의 상태
struct OpenGL_Context {
    ...
    object_name* object_Window_Target;
    ...     
};
// 객체 만들기
unsigned int objectId = 0;
glGenObject(1, &objectId);
// 컨텍스트에 객체를 바인딩하고 할당
glBindObject(GL_WINDOW_TARGET, objectId);
// 현재 GL_WINDOW_TARGET에 바인딩된 객체의 옵션 설정
glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_WIDTH,  800);
glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_HEIGHT, 600);
// 컨텍스트 대상을 기본값으로 되돌리기
glBindObject(GL_WINDOW_TARGET, 0);

이 작은 코드 조각은 OpenGL을 사용할 때 자주 접하게 되는 워크플로입니다. 먼저 객체를 생성하고 해당 객체에 대한 참조를 ID로 저장합니다(실제 객체 데이터는 내부적으로 저장됩니다). 그런 다음 객체 ID(objectId)를 사용하여 윈도우 대상 컨텍스트(GL_WINDOW_TARGET)에 객체를 바인딩합니다. 다음으로 윈도우 옵션을 설정하고 마지막으로 윈도우 대상 컨텍스트의 현재 객체 ID를 0으로 설정하여 객체 바인딩을 해제합니다. 설정한 옵션은 objectId로 참조되는 객체에 저장되며, 객체를 GL_WINDOW_TARGET에 다시 바인딩하는 즉시 설정 값이 원래대로 되돌아갑시다.

지금까지 제공된 코드 예제는 OpenGL의 작동 방식을 대략적으로 보여주는 것에 불과하며, 책 전체를 통해 실제 예제를 충분히 접하게 될 것입니다.

이러한 객체를 사용하는 가장 큰 장점은 애플리케이션에서 여러 개의 객체를 정의하고 각 객체의 옵션을 설정할 수 있다는 것입니다. OpenGL의 상태를 사용하는 작업을 시작할 때마다 원하는 설정으로 객체를 바인딩하기만 하면 됩니다. 예를 들어 3D 모델 데이터(집이나 캐릭터)를 담는 컨테이너 객체가 있는데, 이러한 객체 중 하나를 그리고 싶을 때마다 모델 데이터가 담긴 객체를 바인딩하면 됩니다(이러한 객체는 미리 생성하고 옵션을 설정해 둡니다). 여러 개의 객체를 사용하면 다양한 모델을 지정할 수 있고, 특정 모델을 그리고 싶을 때는 그리기 전에 해당 객체를 바인딩하기만 하면 되므로 모든 옵션을 다시 설정할 필요가 없습니다.

자 이제 시작이야

지금까지 여러분은 OpenGL이라는 명세와 라이브러리에 대해 간략하게 알아보고, OpenGL이 내부적으로 어떻게 작동하는지, 그리고 OpenGL에서 사용하는 몇 가지 특별한 기능에 대해서도 배웠습니다. 모든 내용을 다 이해하지 못했더라도 걱정하지 마세요. 이 책을 통해 각 단계를 차근차근 설명하고 충분한 예제를 통해 OpenGL을 확실히 이해할 수 있도록 도와드리겠습니다.

참고자료

opengl.org: OpenGL 공식 웹사이트 OpenGL registry: 모든 OpenGL 버전에 대한 사양과 확장기능