본문 바로가기
Opengles 3.0 with Android

Chapter 1.1 Shader Build

by SimonLee 2024. 10. 12.

셰이더 프로그램 컴파일을 하려면 아래 절차를 수행한다.

1) glCreateShader() 사용하여, 셰이더 객체를 생성한다.

2) glShaderSource() 사용하여, 셰이더 객체에 셰이더 코드를 전달한다.

3) glCompileShader() 사용하여, 셰이더 코드를 컴파일을 한다.

4) glGetShaderIv(),  glGetShaderInfoLog() 사용하여, 셰이더 코드를 검증 할 수 있다.

5) glCreateProgram() 사용하여, 셰이더 객체를 실행가능한 프로그램으로 만들어야 한다.

6) glAttachShader() 사용하여, 셰이더 객체를 생성한 프로그램에  Attach 한다.

7) glLinkProgram() 사용하여, 프로그램을 링킹하여 최종적으로 셰이더가 파이프라인 세팅이 완료된다.

8) glGetProgramiv(), glGetProgramInfoLog() 사용하여, 프로그램이 링킹을 검증 할 수 있다.

 

 

셰이더 객체 생성, 셰이더 코드 전달 후, 셰이더 컴파일 과정이다.

셰이더 컴파일 후 셰이더 코드 검증을 한다.

GLuint loadAndCompileShader(GLenum shaderType, const char* sourceCode) {
    GLuint shader = glCreateShader(shaderType);

    if ( shader ) {
        glShaderSource(shader, 1, &sourceCode, NULL);
        glCompileShader(shader);

        GLint compiled = 0;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLint infoLen = 0;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen) {
                char* buf = (char*) malloc(infoLen);
                if (buf) {
                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
                    LOGE("Could not compile shader %d:\n%s\n", shaderType, buf);
                    free(buf);
                }
                glDeleteShader(shader);
                shader = 0;
            }
        }
    }
    return shader;
}

 

 

 

프로그램 생성, 셰이더를 프로그램에 어태치 한 후, 프로그램을 링킹한다.

프로그램 링킹 검증을 한다.

GLuint linkShader(GLuint vertShaderID, GLuint fragShaderID)
{
    if (!vertShaderID || !fragShaderID) {
        return 0;
    }

    GLuint program = glCreateProgram();
    if (program) {
        glAttachShader(program, vertShaderID);
        glAttachShader(program, fragShaderID);

        glLinkProgram(program);

        GLint linkStatus = GL_FALSE;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus != GL_TRUE) {
            GLint bufLength = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
            if (bufLength) {
                char* buf = (char*) malloc(bufLength);
                if (buf) {
                    glGetProgramInfoLog(program, bufLength, NULL, buf);
                    LOGE("Could not link program:\n%s\n", buf);
                    free(buf);
                }
            }
            glDeleteProgram(program);
            program = 0;
        }
    }
    return program;
}

 

검증

void glGetShaderiv(GLuint shader, GLenum pname, GLint *params);
  • shader: 셰이더 객체의 ID. 이 ID는 glCreateShader 함수로 생성된 셰이더 객체를 가리킵니다.
  • pname: 조회할 속성의 이름을 지정하는 GLenum 타입의 값입니다. 이 값은 OpenGL에서 미리 정의된 상수를 사용해야 하며, 셰이더와 관련된 다양한 속성을 조회할 수 있습니다.
  • params: 조회한 값이 저장될 포인터입니다. 이 포인터는 pname으로 지정한 속성의 값을 저장하게 됩니다.

 

다음은 pname 매개변수에 사용할 수 있는 주요 상수와 그 설명입니다.

  1. GL_COMPILE_STATUS:
    • 셰이더 컴파일 성공 여부를 확인할 때 사용합니다.
    • 성공 시 params에 GL_TRUE가 저장되며, 실패 시 GL_FALSE가 저장됩니다.
    • 이 값은 셰이더 컴파일이 성공적으로 완료되었는지 확인할 때 필수적으로 사용됩니다.
  2. GL_SHADER_TYPE:
    • 셰이더의 타입을 확인합니다. (예: GL_VERTEX_SHADER, GL_FRAGMENT_SHADER)
    • params에 셰이더 타입이 저장됩니다.
  3. GL_INFO_LOG_LENGTH:
    • 셰이더의 컴파일 에러 또는 경고 로그의 길이를 반환합니다. 이 값은 로그의 문자 수를 반환하며, 로그가 없을 경우 0을 반환합니다.
    • 이 값은 로그를 저장할 버퍼 크기를 할당할 때 사용됩니다.
  4. GL_SHADER_SOURCE_LENGTH:
    • 셰이더에 전달된 소스 코드의 길이를 반환합니다.
  5. GL_DELETE_STATUS:
    • 셰이더가 삭제 상태인지 확인합니다. params에 GL_TRUE가 저장되면 셰이더가 삭제된 상태를 의미하며, GL_FALSE는 아직 삭제되지 않았다는 뜻입니다.
void glGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog);
  • shader: 셰이더 객체의 ID입니다. 이 ID는 glCreateShader 함수로 생성된 셰이더 객체를 가리킵니다.
  • maxLength: 로그를 저장할 버퍼의 최대 크기를 지정합니다. 이 값은 로그를 저장할 배열의 크기를 지정하여, 로그가 너무 길어 잘리지 않도록 하기 위해 사용됩니다.
  • length: 실제 로그의 길이가 저장됩니다. 로그 문자열의 길이 (널 종료 문자는 포함하지 않음)를 반환합니다. 만약 이 정보가 필요하지 않다면 NULL을 전달할 수 있습니다.
  • infoLog: 셰이더 컴파일 또는 링크 과정에서 발생한 에러나 경고 메시지를 저장할 버퍼입니다. 이 버퍼는 문자열로 로그를 반환하며, 널(\0) 문자로 끝납니다

GL_COMPILE_STATUS를 체크해서 컴파일 정상 여부를 체크 한 뒤,

에러 인 경우, glGetShaderiv() 를 통해서 에러메시지 길이를 가져오고

버퍼 생성 한뒤, glGetShaderInfoLog()를 통해 컴파일 에러메시지를 출력한다.

 

void glGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog);
  • program: 셰이더 프로그램 객체의 ID입니다. 이 ID는 glCreateProgram 함수로 생성된 셰이더 프로그램을 가리킵니다.
  • maxLength: 로그를 저장할 버퍼의 최대 크기입니다. 이 크기만큼 로그를 저장할 수 있는 버퍼가 필요합니다.
  • length: 실제 로그의 길이입니다. 반환되는 로그 문자열의 길이를 저장하는 포인터입니다. 로그 길이를 알 필요가 없으면 NULL로 설정할 수 있습니다.
  • infoLog: 로그를 저장할 버퍼입니다. 이 버퍼에 링크 과정에서 발생한 오류나 경고 메시지가 저장됩니다. 버퍼는 널(\0) 문자로 종료된 문자열 형태로 로그를 반환합니다.