简介
Shader编译和链接是将编写好的着色器代码经过一系列封装并参与渲染流水线的过程,使其呈现我们想要的屏幕效果。
Shader编译和链接过程如下图:
实现
1. 创建Program
GLuint m_pShaderProgram;
bool Shader::InitProgram()
{
m_pShaderProgram = glCreateProgram();
if (m_pShaderProgram == 0)
{
fprintf(stderr, "ShaderProgram创建失败!!!");
return false;
}
return true;
}
2. 链接Shader
bool Shader::AttachShader(GLenum shaderType/*shader类型*/, const char* shaderFilePath/*shader文件路径*/)
{
string shaderText;
if (!Utils::ReadFile(shaderFilePath, shaderText))
{
fprintf(stderr, "读取shader文件失败!");
return false;
}
GLuint shaderObj = glCreateShader(shaderType);//创建shader对象
if (shaderObj == 0)
{
fprintf(stderr, "创建shader失败!");
return false;
}
const GLchar *p = shaderText.c_str();
GLint l = strlen(shaderText.c_str());
glShaderSource(shaderObj, 1, &p, &l);//加载shader
glCompileShader(shaderObj);//编译shader
GLint ret;
glGetShaderiv(shaderObj, GL_COMPILE_STATUS, &ret);
if (ret == 0)
{
GLchar log[1024];
glGetShaderInfoLog(shaderObj, sizeof(log), NULL, log);
fprintf(stderr, "shader%d编译失败:%s", shaderType, log);
exit(1);
}
glAttachShader(m_pShaderProgram, shaderObj);//链接shader至program
return true;
}
3. 链接激活Program
bool Shader::ValidateProgram()
{
GLint ret;
GLchar logInfo[1024];
glLinkProgram(m_pShaderProgram);//链接program
glGetProgramiv(m_pShaderProgram, GL_LINK_STATUS, &ret);
if (ret == 0)
{
glGetProgramInfoLog(m_pShaderProgram, sizeof(logInfo), NULL, logInfo);
fprintf(stderr, "链接shaderProgram失败!");
return false;
}
glValidateProgram(m_pShaderProgram);//使program生效
glGetProgramiv(m_pShaderProgram, GL_VALIDATE_STATUS, &ret);
if (ret == 0)
{
glGetProgramInfoLog(m_pShaderProgram, sizeof(logInfo), NULL, logInfo);
fprintf(stderr, "shaderProgram生效失败!");
exit(1);
}
return glGetError() == GL_NO_ERROR;
}
4. 使用Program
void Shader::UseProgram()
{
glUseProgram(m_pShaderProgram);//使用program
}