之前我们已经创建并编译了必要的着色器对象,接着就需要将它们连接器起来,创建一个可执行的着色程序
一、定义着色程序类
class MCProgram { public: MCProgram(); virtual ~MCProgram(); //获取着色程序句柄 unsigned int GetHandle(){return m_Handle;} private: //着色程序句柄 unsigned int m_Handle; };
二、创建着色程序
(1)创建着色程序
首先,需要调用glCreateProgram函数,创建一个空的着色程序,供后续使用。
GLuint glCreateProgram()
该函数没有任何参数,调用之后会返回一个非零的整数,即着色程序句柄;如果发生错误返回0。
(2)附加着色器对象
创建了着色程序之后,就要调用glAttachShader函数,把所需着色器对象关联到这个程序中,以创建可可执行的着色程序。
void glAttachShader(GLuint program, GLuint shader)
program — 着色程序的句柄
shader — 需要关联的着色器对象的句柄
着色器对象可以再任何时候关联到着色程序中,但是它的功能只能在着色程序成功连接后才可以使用。一个着色程序对象可以同时关联多个着色程序
void glDetachShader(GLuint program, GLuint shader)
program —着色程序的句柄
shader — 解除关联的着色器对象句柄
(3)链接着色程序
在所有需要的着色器对象都被关联到着色程序之后,就可以调用glLinkProgram函数,将这些对象链接成一个可执行的着色程序。
void glLinkProgram(GLuint program)
program — 着色程序的句柄
三、状态检查
void glGetProgramiv(GLuint program, GLenum pname, GLint *params)
program — 着色程序的句柄
pname — the parameter to get information about; can be
GL_ACTIVE_ATTRIBUTES
GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
GL_ACTIVE_UNIFORM_BLOCK
GL_ACTIVE_UNIFORM_BLOCK_MAX_LENGTH
GL_ACTIVE_UNIFORMS
GL_ACTIVE_UNIFORM_MAX_LENGTH
GL_ATTACHED_SHADERS
GL_DELETE_STATUS
GL_INFO_LOG_LENGTH
GL_LINK_STATUS
GL_PROGRAM_BINARY_RETRIEVABLE_HINT
GL_TRANSFORM_FEEDBACK_BUFFER_MODE
GL_TRANSFORM_FEEDBACK_VARYINGS
GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
GL_VALIDATE_STATUS
params — 查询结果返回的地址
void glGetProgramInfoLog(GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog)
program — 着色程序的句柄
maxLength — 存储日志信息的缓存长度
length — 日志信息的长度(不包含null终止符),如果不需要获取长度,参数可以传NULL
infoLog — 获取日志信息的缓存地址
bool MCProgram::CheckStatus(unsigned int handle) { //获取链接状态 GLint Success; GL30::glGetProgramiv(handle, GL30::GL_LINK_STATUS, &Success); if (!Success) { //获取Log长度 GLint infoLen; GL30::glGetProgramiv(handle, GL30::GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 0) { char* pLogMsg = new char[infoLen]; //获取链接失败时的Log信息 GL30::glGetProgramInfoLog(handle, infoLen, NULL, pLogMsg); printf("Error linking shader program: \n%s\n", pLogMsg); delete[] pLogMsg; } return false; } return true; }
四、安装着色程序
在着色程序连接成功之后,就可以调用glUseProgram函数,启动这个着色程序。
void glUseProgram(GLuint program)
program — 着色程序的句柄
启动我们所创建的着色程序之后,OpenGL的功能就从固定管线切换到了可编程管线。为了恢复固定管线功能,可以向这个函数传递0作为program参数。
void MCProgram::UseProgram() { GL30::glUseProgram(m_Handle); }
五、删除着色程序
当着色器程序被使用完之后,还需要调用glDeleteProgram函数将其删除,释放系统资源。
void glDeleteProgram(GLuint program)
program — 着色程序的句柄
如果这个着色程序当前没有被使用,执行glDeleteProgram函数时,这个着色程序会被立即删除。否则,就这个着色程序将被标记为删除状态,当它不在使用时将自动被删除。
void MCProgram::DeleteProgram() { if(m_Handle != 0) { GL30::glDeleteProgram(m_Handle); m_Handle = 0; } }
六、配套代码
bool MCProgram::CreateProgram(MCShader* vsShader, MCShader* psShader) { //第一步:创建Program unsigned int programObj = GL30::glCreateProgram(); if(programObj == 0) { return false; } //第二步:附加着色程序 GL30::glAttachShader(programObj, vsShader->GetHandle()); GL30::glAttachShader(programObj, psShader->GetHandle()); //第三步:链接着色程序 GL30::glLinkProgram(programObj); //检查链接是否成功 if(CheckStatus(programObj)) { m_Handle = programObj; return true; } else { GL30::glDeleteProgram(programObj); return false; } }
源码下载: LinkProgram