수색…


소개

이 예제는 셰이더를로드하고 컴파일하는 다양한 방법을 보여줍니다. 모든 예제 에는 오류 처리 코드가 포함되어야합니다 .

비고

glCreateShader 에서 생성 된 Shader 객체는 그다지 glCreateShader 이지 않습니다. 단일 스테이지에 대해 컴파일 된 코드가 포함되어 있지만 해당 스테이지의 전체 컴파일 된 코드를 포함 할 필요조차 없습니다. 여러면에서 C 및 C ++ 오브젝트 파일과 같이 작동합니다.

프로그램 개체에는 마지막으로 링크 된 프로그램이 들어 있습니다. 그러나 그들은 또한 프로그램의 유니폼 값에 대한 상태뿐만 아니라 여러 다른 상태 데이터를 보유합니다. 그들은 셰이더의 인터페이스 데이터를 인트로 스팅하기위한 API를 가지고 있습니다 (GL 4.3에서 포괄적으로되었지만). 프로그램 개체는 렌더링 할 때 사용하는 셰이더 코드를 정의합니다.

한 번 프로그램을 연결하는 데 사용 된 셰이더 개체는 다른 프로그램을 연결하는 데 사용하지 않으면 더 이상 필요하지 않습니다.

C ++에서 분리 가능한 셰이더로드

4.1

이 코드 는 단일 스테이지에 대해 별도의 셰이더 프로그램을 만드는 단일 파일을로드, 컴파일 및 연결합니다. 오류가 있으면 해당 오류에 대한 정보 로그를 얻습니다.

이 코드는 일반적으로 사용 가능한 C ++ 11 기능을 사용합니다.

#include <string>
#include <fstream>

//In C++17, we could take a `std::filesystem::path` instead of a std::string
//for the filename.
GLuint CreateSeparateProgram(GLenum stage, const std::string &filename)
{
    std::ifstream input(filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
    
    //Figure out how big the file is.
    auto fileSize = input.tellg();
    input.seekg(0, ios::beg);
    
    //Read the whole file.
    std::string fileData(fileSize);
    input.read(&fileData[0], fileSize);
    input.close();
    
    //Compile&link the file
    auto fileCstr = (const GLchar *)fileData.c_str();
    auto program = glCreateShaderProgramv(stage, 1, &fileCstr);

    //Check for errors
    GLint isLinked = 0;
    glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
    if(isLinked == GL_FALSE)
    {
        //Note: maxLength includes the NUL terminator.
        GLint maxLength = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);        

        //C++11 does not permit you to overwrite the NUL terminator,
        //even if you are overwriting it with the NUL terminator.
        //C++17 does, so you could subtract 1 from the length and skip the `pop_back`.
        std::basic_string<GLchar> infoLog(maxLength);
        glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
        infoLog.pop_back();

        //The program is useless now. So delete it.
        glDeleteProgram(program);

        //Use the infoLog in whatever manner you deem best.

        //Exit with failure.
        return 0;
    }
    
    return program;
}

C ++에서 개별 셰이더 개체 컴파일

전통적인 GLSL 컴파일 모델은 셰이더 스테이지에 대한 코드를 셰이더 개체로 컴파일 한 다음 여러 셰이더 개체 (사용하려는 모든 스테이지를 포함)를 단일 프로그램 개체로 연결하는 작업을 포함합니다.

4.2부터 하나의 셰이더 단계 만있는 프로그램 개체를 만들 수 있습니다. 이 메서드는 모든 쉐이더 스테이지를 단일 프로그램에 연결합니다.

셰이더 개체 컴파일

#include <string>
#include <fstream>

//In C++17, we could take a `std::filesystem::path` instead of a std::string
//for the filename.
GLuint CreateShaderObject(GLenum stage, const std::string &filename)
{
    std::ifstream input(filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
    
    //Figure out how big the file is.
    auto fileSize = input.tellg();
    input.seekg(0, ios::beg);
    
    //Read the whole file.
    std::string fileData(fileSize);
    input.read(&fileData[0], fileSize);
    input.close();
    
    //Create a shader name
    auto shader = glCreateShader(stage);

    //Send the shader source code to GL
    auto fileCstr = (const GLchar *)fileData.c_str();
    glShaderSource(shader, 1, &fileCstr, nullptr);

    //Compile the shader
    glCompileShader(shader);

    GLint isCompiled = 0;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
    if(isCompiled == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);

        //C++11 does not permit you to overwrite the NUL terminator,
        //even if you are overwriting it with the NUL terminator.
        //C++17 does, so you could subtract 1 from the length and skip the `pop_back`.
        std::basic_string<GLchar> infoLog(maxLength);
        glGetShaderInfoLog(shader, maxLength, &maxLength, &infoLog[0]);
        infoLog.pop_back();

        //We don't need the shader anymore.
        glDeleteShader(shader);

        //Use the infoLog as you see fit.
        
        //Exit with failure.
        return 0;
    }

    return shader;
}

프로그램 개체 연결

#include <string>

GLuint LinkProgramObject(vector<GLuint> shaders)
{
    //Get a program object.
    auto program = glCreateProgram();

    //Attach our shaders to our program
    for(auto shader : shaders)
        glAttachShader(program, shader);

    //Link our program
    glLinkProgram(program);

    //Note the different functions here: glGetProgram* instead of glGetShader*.
    GLint isLinked = 0;
    glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
    if(isLinked == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);

        //C++11 does not permit you to overwrite the NUL terminator,
        //even if you are overwriting it with the NUL terminator.
        //C++17 does, so you could subtract 1 from the length and skip the `pop_back`.
        std::basic_string<GLchar> infoLog(maxLength);
        glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
        infoLog.pop_back();
        
        //We don't need the program anymore.
        glDeleteProgram(program);

        //Use the infoLog as you see fit.
        
        //Exit with failure
        return 0;
    }

    //Always detach shaders after a successful link.
    for(auto shader : shaders)
        gldetachShader(program, shader);
        
    return program;
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow