我正在尝试制作一个使用 OpenGL 的框架。
然而,重新加载着色器程序时遇到问题。
这就是我现在所拥有的。
我加载并编译了一个顶点着色器和一个片段着色器(两者都包含主)。
比我与他们链接一个程序。
起初,它没有问题。无论我刷新着色器多少时间。(如果我按下 Refresh Shader,应用程序会创建新的着色器、程序资源并用它们替换原来的)
比,如果我加载一个网格并执行一些绘图调用(使用 VBO),这次刷新着色器失败并显示以下消息。
我不知道我的绘图调用或 VBO 函数调用如何可能与着色器链接相关......
我什至不确定这是否是确切的原因。
着色器类:
class Shader : public Named
{
// -------------------------------------------------------
// --------------- Defs ----------------------------------
public:
typedef void (*ErrFunc)( Shader* pShader, const char* const errMsg );
// -------------------------------------------------------
// --------------- Funcs ---------------------------------
public:
//
// Shader Controls
//
// pre: source is string contains source
Shader( const std::string& name, GLenum type);
~Shader( void );
// pre: file to loast source. Give nullptr to load from lastly loaded file
void ShaderSourceFromFile( const char* file );
void ShaderSource( const std::string& source );
void Compile( void );
void AttachTo( GLuint program );
void DetachFrom( GLuint program );
GLuint GetId( void );
void SetId( GLuint shaderId );
GLint GetType( void );
GLint GetCompileStatus( void );
const char* const GetShaderInfoLog( void );
//
// Err Control
//
public:
void Error ( const char* pErrMsg );
static ErrFunc SetErrFunc( ErrFunc fpNewErrFunc );
// -------------------------------------------------------
// ----------- Vars --------------------------------------
private:
// id of the shader
GLuint _shaderId;
// type of the shader
GLenum _type;
// error func
static ErrFunc s_fpErrFunc;
}; // class Shader
//
// Shader
//
Shader::ErrFunc Shader::s_fpErrFunc = nullptr;
Shader::Shader( const std::string& name, GLenum type) :
Named(name),
_shaderId(GL_INVALID_RESOURCE_ID),
_type(type)
{
// Create shader
GLint id = glCreateShader(type);
// Failed to create shader?
if ( id == GL_INVALID_RESOURCE_ID )
Error("(Shader::Shader) Failed to create shader resource");
// Set shader id
SetId(id);
}
Shader::~Shader( void )
{
// Delete shader
glDeleteShader(GetId());
// Error Check
if( glGetError() == GL_INVALID_VALUE )
Error("(Shader::~Shader) given id to delete was not shader");
}
void Shader::Compile( void )
{
// Compile shader
glCompileShader(_shaderId);
switch( glGetError() )
{
case GL_NO_ERROR:break;
case GL_INVALID_VALUE: Error("shader is not a value generated by OpenGL.");break;
case GL_INVALID_OPERATION: Error("shader is not a shader object.");break;
default:Error("Unkown Error");
}
// ErrorCheck
if( GetCompileStatus() == GL_FALSE )
Error("(Shader::Compile) Compilation Failed.");
}
void Shader::ShaderSourceFromFile( const char* file )
{
ShaderSource(ReadEntireFile(file));
}
// pre: source is string contains source
void Shader::ShaderSource( const std::string& source )
{
const GLchar* pSource = source.c_str();
glShaderSource( GetId(), // shader id
1, // count of source. only one at a time at the moment
&pSource, // buffer that source is stored
nullptr); // length is not specified, yet null terminated
switch( glGetError() )
{
case GL_NO_ERROR:
break;
case GL_INVALID_VALUE:
Error("invalid shader or bufsize is less than 0");
break;
case GL_INVALID_OPERATION:
Error("shader is not a shader object.");
break;
default:
Error("Unkown Error");
break;
}
}
void Shader::AttachTo( GLuint program )
{
glAttachShader(program, GetId());
if( glGetError() != GL_NO_ERROR )
{
Error("(Shader::AttachTo) Error Happend Performing glAttachShader");
}
}
void Shader::DetachFrom( GLuint program )
{
glDetachShader(program, GetId());
switch( glGetError() )
{
case GL_NO_ERROR:
break;
case GL_INVALID_VALUE:
Error("(Shader::DetachFrom)either program or shader is a value that was not generated by OpenGL.");
break;
case GL_INVALID_OPERATION:
Error("(Shader::DetachFrom)program is not a program object. or "
"shader is not a shader object. or "
"shader is not attached to program.");
break;
default:
Error("(Shader::DetachFrom)Unkown Error");
break;
}
}
GLuint Shader::GetId( void )
{
return _shaderId;
}
void Shader::SetId( GLuint shaderId )
{
_shaderId = shaderId;
}
GLint Shader::GetType( void )
{
return _type;
}
void Shader::Error ( const char* pErrMsg )
{
if( s_fpErrFunc )
s_fpErrFunc(this, pErrMsg);
}
Shader::ErrFunc Shader::SetErrFunc( ErrFunc fpNewErrFunc )
{
ErrFunc prev = s_fpErrFunc;
s_fpErrFunc = fpNewErrFunc;
return prev;
}
GLint Shader::GetCompileStatus( void )
{
GLint status;
glGetShaderiv(GetId(), GL_COMPILE_STATUS, &status );
GLint err = glGetError();
switch( err )
{
case GL_NO_ERROR:
break;
case GL_INVALID_ENUM:
Error("(Shader::GetCompileStatus) Invalid Enum passed to glGetShaderiv");
break;
case GL_INVALID_VALUE:
Error("(Shader::GetCompileStatus) Invalid Shader id passed to glGetShaderiv");
break;
case GL_INVALID_OPERATION:
Error("(Shader::GetCompileStatus) Invalid Shader id or shader does not support");
break;
default:
Error("(Shader::GetCompileStatus) Unkown Error");
break;
}
return status;
}
const char* const Shader::GetShaderInfoLog( void )
{
static const unsigned s_bufSize = 0x1000;
static GLchar s_buf[s_bufSize] = {0};
// Get InfoLog
glGetShaderInfoLog(GetId(), s_bufSize, nullptr, s_buf);
// Error Check
if( glGetError() != GL_NO_ERROR )
Error("(Shader::GetCompileStatus) There was Error performing glGetShaderInfoLog");
// return buffer
return s_buf;
}
提神功能:
void GLShaderManager::Refresh( void )
{
// Gets current shader
Shader* pVertexPrev = _shaderMap["Vertex"];
Shader* pFragPrev = _shaderMap["Fragment"];
// Delete them(glDeleteShader call is included)
if( pVertexPrev && pFragPrev )
{
delete pVertexPrev;
delete pFragPrev;
}
// Loads shader
LoadShader("Vertex", GL_VERTEX_SHADER, s_vertexFile);
LoadShader("Fragment", GL_FRAGMENT_SHADER, s_fragmentFile);
// Delete Current Program
glDeleteProgram(_program);
// Create new Program
GLuint newProgram = glCreateProgram();
_program = newProgram;
// Attach Shaders
UseShader("Vertex");
UseShader("Fragment");
// Linking
glLinkProgram(_program);
const unsigned bufSize = 0x1000;
char buf[bufSize] = { '\0' };
GLint status = 0;
glGetProgramiv(_program, GL_LINK_STATUS, &status );
if( status )
Gui::Get().Output("Shader program linked successfully.");
glGetProgramInfoLog(_program, bufSize, nullptr, buf);
Gui::Get().Output(buf);
s_uniformErrHistory.clear();
}
void GLShaderManager::LoadShader( const std::string& name, GLenum type, const std::string& sourceFile )
{
Shader* pShader = _shaderMap[name] = new Shader(name, type);
if( pShader )
{
pShader->ShaderSourceFromFile(sourceFile.c_str());
pShader->Compile();
if( pShader->GetCompileStatus() )
Gui::Get().Output( (pShader->GetName() + " shader successfully compiled.").c_str());
Gui::Get().Output(pShader->GetShaderInfoLog());
}
}
void GLShaderManager::UseShader( const std::string& name )
{
Shader* pShader = _shaderMap[name];
if( pShader )
{
pShader->AttachTo(_program);
}
}