하드웨어와 연관이 되어 있는 OpenGL 을 사용하기는 간단하지 않다. 함수포인터를 얻어내곤 해야 되기 때문에 꽤나 귀찮기도 하고, Extension 들에 대해서 신경도 써야 한다.

그래서 GLEW[1]라는 라이브러리를 사용해서 간단하게 쉐이더를 사용할 수 있는 방법을 소개한다. 사실 간단한건데 그냥 정리해보는거다.

1. 먼저 GLEW 를 다운 받아 압축을 푼다. 그때 나오는 glew.h 와 wglew.h 를 기본적으로 include 시킨다.(이때 이전처럼 windows.h 와 gl.h, glu.h 를 별도로 넣을 필요는 없다.)

2. 그후 라이브러리는 여기서 나오는 glew32.lib 를 추가하고, 컴파일러에서 제공하는 opengl32.lib 를 추가 시킨다. 만약 그외에 gluPerspective 같은 추가 utility 함수를 사용할 경우 glu32.lib 도 추가한다.[2] GLEW32는 동적 라이브러리도 사용한다. 실행파일이 있는 곳에 glew32.dll 을 복사해둔다.

3. 기본적인 OpenGL 초기화는 설명하지 않겠다. 윈도우 생성과 OpenGL 의 초기화가 모두 끝나면, 다음과 같이 GLEW 를 초기화한다.

(Language : cpp)
if( glewInit() != GLEW_OK )
    return il4_RENDERER_INITIALIZATION_ERROR;

여기서 il4_... 어쩌구 하는것은 개인적으로 사용하는 enum 형식이니 무시하자. 이 함수에서 OpenGL 관련 함수들의 함수포인터를 얻어오는 작업등을 알아서 해준다. 따라서 아래에 쉐이더를 위해 사용할 다른 함수들의 함수포인터를 직접 얻어올필요 없이 위의 코드만으로 훨씬 편하게 OpenGL 을 사용할 수 있다.

3.5.(옵션) 쉐이더를 사용하기 위해서 하드웨어가 쉐이더를 지원하는지 확인할 필요가 있다. 가장 간단하게 OpenGL 이 2.0 이상인지 확인한다.

(Language : cpp)
const char *verstr = (const char*)glGetString( GL_VERSION );
unsigned int version;
    sscanf( verstr, "%d", &version );
    if( version < 2 )
        return il4_OPENGL_ERROR;

사실 OpenGL 1.x 에서도 GLSL 1.0 의 버전을 지원할 수 있다. 그러므로 위의 추가적으로 GL_SHADING_LANGUAGE_VERSION 의 값을 얻어내어 추가적으로 검사할 수는 있다. 하지만 일단은, 내 경우는 2.0 위주로 나간다고 가정하고 1.x 는 짤라버렸다!! -_-;

4. 이제 파일의 쉐이더 코드를 메모리로 부른다.(이것은 아래 glShaderSource 함수 호출 후 바로 메모리 해제 시켜도 된다.)

Read Shader Code from File (Language : cpp)
fs.seekg( 0, ios::end );
m_Size = fs.tellg();
char *FileData = new char[m_Size];
memset( FileData, 0, m_Size );
fs.clear();
fs.seekg( 0 );
fs.read( FileData, m_Size );

5. 그 다음 Shader 에 대한 Shader 번호를 얻어오는데, Vertex Shader는 첫번째 줄, Fragment Shader 는 두번째 줄에 있다.

(Language : cpp)
m_VertexShaderNumber = glCreateShader( GL_VERTEX_SHADER );
m_FragmentShaderNumber = glCreateShader( GL_FRAGMENT_SHADER );

6. (Fragment Shader 는 생략하고) 이 때 얻어온 번호를 가지고 각각의 쉐이더를 를 인식한다. 다음의 코드로, 위에 불러온 소스 코드가 담겨 있는 FileData를 전달해준다.(NULL은 이 파일 데이타가 Null String 이라는 뜻이다. 그렇지 않으면 파일 데이터의 크기를 전달하여야 한다.)

(Language : cpp)
glShaderSource( m_VertexShaderNumber, 1, (const char**)&FileData, NULL );

위에 설명하였듯, 이제 FileData의 메모리는 해제가 가능하다. 그 이후에는 이 소스 코드를 컴파일한다.

(Language : cpp)
glCompileShader( m_VertexShaderNumber );

7. Vertex Shader 와 Fragment Shader 를 모두 불러들였다면[3], 이것을 Shader Program(혹은 그냥 Program)으로 묶어야 한다.

(Language : cpp)
  1. ShaderID = glCreateProgram();
  2. glAttachShader( ShaderID, m_VertexShaderNumber );
  3. glAttachShader( ShaderID, m_FragmentShaderNumber )
  4. glLinkProgram( ShaderID );

(1)번은 (Shader) Program을 새로 생성하여 번호를 얻어오는 것이고,
(2), (3) 번은 이곳에 Vertex Shader 와 Fragment Shader를 아까 부여 받은 Shader 번호를 통해 붙이는 것이다. 그 후 (4)번으로 이것을 Link 시킨다.

8. 이렇게 되면 준비과정은 끝이다. 이제 이 Shader 를 사용할때는 렌더링 하기 전에 다음의 코드로 Shader 의 사용을 알린다.

(Language : cpp)
glUseProgram( ShaderID );

이때 ShaderID 대신 0 을 입력하면, Shader 를 사용하지 않고 Fixed Pipeline 을 통한 렌더링을 사용하겠다는 의미가 된다.
  1. GLEW : The OpenGL Extension Wrangler Library(http://glew.sourceforge.net) [본문으로]
  2. opengl32.lib 에 대한 정확한 테스트는 해보지 못했는데, 혹시 Microsoft Visual Studio를 사용하는데, 여기서 기본적으로 제공되는 라이브러리의 버전이 낮을 경우 각 운영체제에 맞는 Microsoft Platform SDK 를 MS 홈페이지에서 다운받아 추가로 설치한다. [본문으로]
  3. 둘중 하나만 쓰고 진행하여 나머지 하나는 지정하지 않으면 Fixed Pipeline 으로 인식된다. [본문으로]
크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)
2007/07/21 00:38 2007/07/21 00:38

트랙백 주소 :: http://www.hybrid.pe.kr/tt/trackback/232

댓글을 달아 주세요

  1. pidoli 2007/12/21 12:56  댓글주소  수정/삭제  댓글쓰기

    제가 댓끌 올려줄께요 ㅎㅎ

  2. pidoli 2007/12/21 12:57  댓글주소  수정/삭제  댓글쓰기

    글구 글 잘봤씁니닷~

  3. wswoo 2008/10/20 14:58  댓글주소  수정/삭제  댓글쓰기

    글 잘봤습니다.

  4. 걸푸짱 2009/06/20 22:44  댓글주소  수정/삭제  댓글쓰기

    좋은 정보 감사합니다. 30분 정도 해매다가 문제 해결했네요.

    HLSL만 쓰다가 이번에 GLSL쓰려고 하다보니 설정하는게 까다로운

    것 같네요. 지금은 토요일 저녁이군요. 남은 주말 즐겁게 보내세요.

[로그인][오픈아이디란?]