본문 바로가기
College Study/OpenGL

[그래픽스] OpenGL과 GLSL의 오류 검출

by 2den 2020. 6. 8.
728x90

* Computer Graphics Programming in OpenGL with C++ 책을 참고하였습니다.

* 책을 번역한 것이 아닌, 제가 독학 후 책을 참고하여 설명하는 게시물입니다. 따라서 책에 없는 부연 설명이 있기도 하며, 의역 또는 오역, 오개념이 있을 수 있습니다. 피드백은 댓글을 남겨주세요.

* 영어 용어를 최대한 한국어로 번역하지 않습니다. 처음부터 코드에서 사용되는, 또는 원서나 인터넷에서 사용되는 보편적 용어를 사용하여 개념을 잡는 것을 추천드립니다.

GLSL 코드의 컴파일은 C++ 런타임 중에 진행됩니다. 즉, 쉐이더 코드는 빌드 후에 컴파일이 시작되는 것입니다. 또한 GLSL 코드는 CPU가 아닌 GPU에서 실행되기 때문에, OS(운영체제)가 OpenGL 런타임 에러를 항상 잡을 수 있는 것은 아닙니다. 따라서 디버깅이 힘들고, 쉐이더에 문제가 생기더라도 이유를 알기 어렵죠.

이번 게시물에서는, 책에서 제공된 모듈을 공유하려고 합니다. 이 모듈은 GLSL 에러를 감지하고 알려주는 역할을 합니다.

[Program 2.3 Modules to Catch GLSL Errors]

void printShaderLog(GLuint shader) {
    int len = 0;
    int chWrittn = 0;
    char* log;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
    if (Len > 0) {
        log = (char*)malloc(len);
        glGetShaderInfoLog(shader, len, &chWrittn, log);
        cout << "Shader Info Log: " << log << ends;
        free(log);
    }
}

void printProgramLog(int prog) {
    int len = 0;
    int chWrittn = 0;
    char* log;
    glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
    if (len > 0) {
        log = (char*)malloc(len);
        glGetProgramInfoLog(prog, len, &chWrittn, log);
        cout << "Program Info Log: " << log << endl;
        free(log);
    }
}

bool checkOpenGLError() {
    bool foundError = false;
    int glErr = glGetError();
    while (glErr != GL_NO_ERROR) {
        cout << "glError: " << glErr << endl;
        foundError = true;
        glErr = glGetError();
    }
    return foundError;
}

이 코드는 지난 프로그램 2.2의 createShaderProgram() 함수 안에 위치하면 됩니다. 위 코드의 세 함수의 역할은 다음과 같습니다:

1. checkOpenGLError( )는 발생된 OpenGL의 에러 flag를 확인합니다.

2. ​printShaderLog( )는 GLSL의 컴파일이 실패할 경우 OpenGL의 로그(log)의 내용을 보여줍니다.

3. printProgramLog( )는 GLSL 링크(연결)에 실패할 경우 OpenGL의 로그의 내용을 보여줍니다.

이 모듈을 사용하려면 해당 함수들을 호출해 주어야겠죠? 에러 검출이 필요할 때마다 호출해서 사용하면 됩니다. 아래 코드는 같은 프로그램에서 사용된 예제입니다.

// main.cpp createShaderProgram()

glCompileShader(vShader);
checkOpenGLError();
glGetShaderiv(vShader, GL_COMPILE_STATUS, &vertCompiled);
if (vertCompiled != 1) {
    cout << "vertex compilation failed" << endl;
    printShaderLog(vShader);
}

glCompileShader(fShader);
checkOpenGLError();
glGetShaderiv(fShader, GL_COMPILE_STATUS, &fragCompiled);
if (fragCompiled != 1) {
    cout << "fragment compilation failed" << endl;
    printShaderLog(fShader);
}

GLuint vfProgram = glCreateProgram();
glAttachShader(vfProgram, vShader);
glAttachShader(vfProgram, fShader);
    
glLinkProgram(vfProgram);
checkOpenGLError();
glGetProgramiv(vfProgram, GL_LINK_STATUS, &linked);
if (linked != 1) {
    cout << "linking failed" << endl;
}

이 모듈을 사용하는 것 외에도 어느 쉐이더 코드에 문제가 있는지 찾아내는 방법은 얼마든지 있습니다. 틀릴 수 없는 코드를 대체하여 결과를 지켜보는 방법도 이에 해당됩니다. 하지만, 이러한 모듈을 사용하면 시간을 훨씬 많이 절약할 수 있습니다.

모둘을 적용시킨 결과, 쉐이더 코드에서 오류가 발생하면 CLI에 오류에 대한 정보가 잘 출력됩니다.

 

728x90

댓글