Scientia Conditorium

[OpenGL002] glew 설치 및 에러 수정 본문

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

[OpenGL002] glew 설치 및 에러 수정

크썸 2024. 9. 30. 01:48

이전 글 : [OpenGL001] Visual Studio 2022 with OpenGL,GLFW (tistory.com)

 

[OpenGL001] Visual Studio 2022 with OpenGL,GLFW

※ 본 글은 Window10 + Visual Studio 2022 버전에서 작성했지만 Window11에서도 동일합니다. 본격적인 컴퓨터 그래픽스에 앞서서 환경 설정 셋팅을 하도록 하겠습니다. 비쥬얼 스튜디오 설치 방법은 생

molonlabe.tistory.com


GLEW

glew는 OpenGL Extension Wrangler Library 약자로 글루라고 하거나 한 글자씩 읽습니다. OpenGL 버전은 다양하지만 어떤 버전이든지 반드시 제공해야 하는 기능은 코어 라이브러리(core library)에 들어있습니다. 그러나 경우에 따라서 특정 기능이 필요할 때가 있습니다. 게다가 이 특정 기능이 많은 사람들이 사용하고 있다면 표준화시켜 놓습니다. 핵심 기능은 아니지만 많은 사람들이 사용하다 보니 표준화시켜서 확장 버전(extension)으로 제공하고 있습니다. 핵심 기능에 포함시키지 않고 확장 버전에 넣은 이유는 기술의 발전이 워낙 빠르기 때문입니다. 그래픽 카드 발달 속도가 OpenGL 표준을 정하는 속도보다 빠르니 우선 확장 버전에 넣어서 테스트 및 검증 과정을 거친 후, 나중에 OpenGL 정식 버전이 올라갈 때 핵심 기능으로 넣는 방식입니다. 따라서 확장 라이브러리를 사용하면 최신 기능을 더 효과적으로 구현/사용할 수 있게 됩니다.

 

glew는 OpenGL의 모든 버전의 사용을 지원하고 extension 사용을 도와주는 라이브러리 입니다. 어떤 확장이 사용 가능한지 확인하고 현재 내 그래픽 카드 상태에 따라 사용 가능한지 도와줍니다. 

 

glew 다운로드

구글에 glew를 검색하거나 glew 다운로드 사이트에 접속합니다. 24년 9월 기준으로 2.1.0 버전을 제공하고 있습니다. 소스코드랑 바이너리 둘 다 제공하고 있지만 소스 코드 컴파일하기 귀찮으니 바이너리로 다운로드 해줍니다.

'Binaries Windows 32-bit and 64-bit' 링크를 누르면 소스포지 사이트로 이동하게 됩니다. 약 5초 정도의 카운트 다운이 지나면 다운로드가 자동으로 되니 조금 기다려주시면 되겠습니다. 그러면 'glew-2.1.0-win32.zip' 파일이 다운로드 되는데, 파일명은 win32 이지만 내용물은 64bit로 컴파일 되어있는 게 들어있습니다. 설치 방법은 이전 게시글의 glfw 설치 방법과 동일합니다.

 

glew 설치

다운로드한 파일을 압축 해제해서 include, lib, bin 폴더의 내용물들만 사용합니다. 먼저 이전 게시글을 잘 따라했다면 include/GLFW 폴더가 있을 것입니다. 압축 폴더 안의 include/GL 폴더 안에서 GL 폴더를 그대로 복사하여 가져옵니다. 실행하려는 프로젝트의 include 폴더에는 다음과 같이 들어있어야 합니다.

OpenGL002 블로그 글 시점 include 폴더 구조

 

다음으로 아래 파일들을 전부 프로젝트가 있는 폴더로 복사합니다.

  • glew-2.1.0//bin/Release/x64/glew32.dll
  • lib/Release/x64/glew32.lib
  • lib/Release/x64/glew32s.lib

glew는 설치가 잘 되었는지 제공하는 별도의 프로그램도 제공합니다. 이 프로그램은 glew32.dll 파일과 같이 있습니다. glewinfo.exe 프로그램을 실행하면 glewinfo.txt 파일을 생성하는데 지원되는 OpenGL 버전과 확장(extension), 함수 등이 적혀있습니다. 즉, 현재 실행한 컴퓨터의 그래픽 카드가 OpenGL 버전 몇을 지원하는지 보여줍니다. 또 다른 프로그램인 visualinfo.exe 프로그램 역시 실행하면 visualinfo.txt 파일을 생성해줍니다. 이 파일에는 OpenGL 확장 리스트와 프레임 버퍼를 설정할 떄 어느 정도 성능이 지원되는지를 알려줍니다. 프레임 버퍼가 현재 무슨 말인지 모르셔도 상관없습니다. 이 블로그를 계속 따라하시다보면 무엇인지 알 수 있게 되니 지금은 그냥 하드웨어가 어디까지 지원하는지 보여준다 정도만 알고 계시면 충분하겠습니다.

 

라이브러리 파일들 복사가 완료되었으면 정상 동작하는지 확인을 해야 합니다. glew 확인을 위한 함수로는 glewInit() 을 호추하면 됩니다. 전체 코드는 아래와 같습니다.

#include "GL/glew.h"
#include "GLFW/glfw3.h"

int main()
{
	GLFWwindow* window;

	if (!glfwInit())
	{
		return -1;
	}

	window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		return -1;
	}

	glfwMakeContextCurrent(window);
    
	glewInit();

	while (!glfwWindowShouldClose(window))
	{
		glClear(GL_COLOR_BUFFER_BIT);
		glBegin(GL_TRIANGLES);
		glColor3f(1.0f, 0.0f, 0.0f);
		glVertex2f(-0.5f, 0.0f);
		glVertex2f(0.0f, 0.5f);
		glVertex2f(0.5f, 0.0f);
		glEnd();

		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwTerminate();
	return 0;
}

// 위 코드를 실행 시 빨간색 삼각형이 나오면 정상 동작

 

위 코드가 문제없이 동작하면 성공입니다.

만약 에러가 발생했다면 어디서 발생했는지 하나하나 알아보도록 하겠습니다.

 

에러1. glew.h 선언 순서

glew.h include 순서는 glfw3.h 헤더보다 먼저 호출되어야 합니다. 즉 아래처럼 glfw3.h가 glew.h 보다 먼저 선언되면 컴파일 에러가 발생합니다.

glew.h가 나중에 선언되면
gl.h가 먼저 include 되었다고 에러 메시지를 출력한다.

 

그 이유는 glew.h 안의 아래 코드 때문입니다.

#ifndef __glew_h__
#define __glew_h__
#define __GLEW_H__

#if defined(__gl_h_) || defined(__GL_H__) || defined(_GL_H) || defined(__X_GL_H)
#error gl.h included before glew.h
#endif

glew.h 내부 코드를 보면 85번째 줄에 #error gl.h included before glew.h 를 확인할 수 있습니다. 즉, glew.h 헤더를 쓰기 전에 다른 곳에서 __gl_h_, __GL_H__, _GL_H, __X_GL_H 네 가지 중 1개가 이미 정의되어 있으면 오류를 출력하도록 되어있습니다. openGL 함수를 사용하기 위해 gl.h 라던가 glu.h 를 사용할 때가 있는데, 이럴 경우 glew.h 와 충돌이 있을 수 있습니다. 따라서 glew 확장 라이브러리를 사용한다면 가장 먼저 include 시켜주어야 합니다. 다시 정리하자면 glew.h include 순서는 glfw3.h 헤더보다 먼저 호출되어야 합니다.

 

에러2. glewInit() error - Missing GL version

glew.h를 glfw3.h 보다 먼저 선언해야 한다는 생각 때문에 glewInit() 함수 역시 glfwInit() 보다 먼저 호출해야된다고 생각할 수 있습니다. 그러나 이렇게 할 경우 아래와 같은 에러 코드를 반환하게 됩니다.

int main
{
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
    	std::cerr << "glewInit failed : " << glewGetErrorString(err) << "\n";
        return -1;
    }

    if (!glfwInit())
    {
        std::cerr << "glfwInit failed\n";
        return -1;
    }
    
    ...
}

// 위 코드 실행 시 에러 반환

 

 

glewGetErrorString() 함수는 에러값을 문자열로 바꿔서 보여주는 함수입니다. 이 오류가 나오는 이유는 렌더링할 창(window)이 없기 때문입니다. 창(window)가 없다는 말은 컨텍스트(context)가 없다는 의미이고 이는, 컨텍스트(context) 없이는 OpenGL 함수나 glewInit()을 호출할 수 없다는 말과 같습니다. 또한 glew 홈페이지의 Usage 챕터를 보면 이에 대한 설명도 나와 있습니다.

Initializing GLEW
First you need to create a valid OpenGL rendering context and call glewInit() to initialize the extension entry points. If glewInit() returns GLEW_OK, the initialization succeeded and you can use the available extensions as well as core OpenGL functionality.

 

정리하자면 우리는 glfw를 사용하고 있기 때문에 glfwMakeContextCurrent(window) 함수 다음에 glewInit() 함수를 호출해주어야 합니다. 따라서 코드를 수정하면 아래와 같이 됩니다.

int main
{
    ...
    
    if (!glfwInit())
    {
        std::cerr << "glfwInit failed\n";
        return -1;
    }
    
    ...
    
    glfwMakeContextCurrent(window);
    
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
    	std::cerr << "glewInit failed : " << glewGetErrorString(err) << "\n";
        return -1;
    }
    
    ...
}

// 정상 코드

 

glad

glad는 multi-language GL/GLX/WGL loader-generator의 약자로 라이브러리 자체를 제공하는 것이 아니라 소스 코드를 직접 생성해줍니다.  glad는 라이브러리를 설치한다는 개념이 아니고 소스 코드를 내 프로젝트에 직접 넣는 방식입니다. 하는 역할은 glew와 동일하다고 보면 되겠습니다. 역할이 동일하기 때문에 glew 나 glad 둘 중 하나만 선택해야 합니다. 이 블로그에서는 glew를 설치하여 사용하도록 하겠습니다.