bool ShaderManager::buildProgram( ShaderComponents comp )
{
GLuint vertex = glCreateShader( GL_VERTEX_SHADER );
GLuint fragment = glCreateShader( GL_FRAGMENT_SHADER );
//----------------------------------------
// Read in from the source files and set as source
// This is ugly. Need to remake it
{
std::vector< std::string > v_source_str;
std::vector< std::string > f_source_str;
std::vector< const char* > v_source;
std::vector< const char* > f_source;
std::vector< GLint > v_length;
std::vector< GLint > f_length;
v_source_str = readSource( comp.m_Vert );
f_source_str = readSource( comp.m_Frag );
for( int i = 0; i < v_source_str.size( ); i++ )
{
v_source.push_back( v_source_str[ i ].c_str( ) );
v_length.push_back( v_source_str[ i ].length( ) );
}
for( int i = 0; i < f_source_str.size( ); i++ )
{
f_source.push_back( f_source_str[ i ].c_str( ) );
f_length.push_back( f_source_str[ i ].length( ) );
}
glShaderSource( vertex, v_source.size( ), &v_source[ 0 ], &v_length[ 0 ] );
glShaderSource( fragment, f_source.size( ), &f_source[ 0 ], &f_length[ 0 ] );
}
//----------------------------------------
// Compile
glCompileShader( vertex );
glCompileShader( fragment );
//----------------------------------------
// Error check
GLint result;
glGetShaderiv( vertex, GL_COMPILE_STATUS, &result );
if( result == GL_FALSE )
{
char info[ 512 ];
glGetShaderInfoLog( vertex, 512, NULL, info );
ToolBox::Utilities::Logger::get( )->write( 'e', "Failed to compile Vertex Shader '%s' with error:\n%s", comp.m_Vert.m_Name.c_str( ), info );
// Lets also check for fragment error as well so we dont have to fix vertex
// only to find a messed up fragment.
glGetShaderiv( fragment, GL_COMPILE_STATUS, &result );
if( result == GL_FALSE )
{
// Fragment also failed to compile
memset( info, '\0', 512 );
glGetShaderInfoLog( vertex, 512, NULL, info );
ToolBox::Utilities::Logger::get( )->write( 'e', "Failed to compile Fragment Shader '%s' with error:\n%s", comp.m_Vert.m_Name.c_str( ), info );
}
glDeleteShader( vertex );
glDeleteShader( fragment );
return false;
}
glGetShaderiv( fragment, GL_COMPILE_STATUS, &result );
// Vertex was OK. How about fragment?
if( result == GL_FALSE )
{
char info[ 512 ];
glGetShaderInfoLog( vertex, 512, NULL, info );
ToolBox::Utilities::Logger::get( )->write( 'e', "Failed to compile Fragment Shader '%s' with error:\n%s", comp.m_Vert.m_Name.c_str( ), info );
glDeleteShader( vertex );
glDeleteShader( fragment );
return false;
}
//----------------------------------------
// Attach and Bind
Shader shader;
shader.m_ID = comp.m_Frag.m_Name;
shader.m_Program = glCreateProgram( );
glAttachShader( shader.m_Program, vertex );
glAttachShader( shader.m_Program, fragment );
// We send off the final shader to another function for the potenitally
// lengthy binding process
bindAttributes( shader.m_Program, comp );
//----------------------------------------
// Link and clean up
glLinkProgram( shader.m_Program );
glGetProgramiv( shader.m_Program, GL_LINK_STATUS, &result );
if( result == GL_FALSE )
{
// Error while linking
// Get the info log and report the error
GLint logSize = 0;
glGetProgramiv( shader.m_Program, GL_INFO_LOG_LENGTH, &logSize );
std::stringstream stream;
stream << "Failed to link program for shader '" << shader.m_ID << "'! ";
if( logSize == 0 )
stream << "No Program Info Log available!";
else
{
GLchar* log = new GLchar[ logSize ];
GLsizei ret_size;
glGetProgramInfoLog( shader.m_Program, logSize, &ret_size, log );
stream << "\n" << log;
delete [] log;
}
ToolBox::Utilities::Logger::get( )->write( 'e', stream.str( ).c_str( ) );
glDeleteShader( vertex );
glDeleteShader( fragment );
glDeleteProgram( shader.m_Program );
return false;
}
glDeleteShader( vertex );
glDeleteShader( fragment );
m_Shaders.push_back( shader );
return true;
}