Error Check

void CheckForGLError()

{

for (GLenum error; (error = glGetError()) != GL_NO_ERROR;)

{

cout << "OpenGL Error: \t";

if (error == GL_INVALID_ENUM)

cout << "GL_INVALID_ENUM";

if (error == GL_INVALID_VALUE)

cout << "GL_INVALID_VALUE";

if (error == GL_INVALID_OPERATION)

cout << "GL_INVALID_OPERATION";

if (error == GL_STACK_OVERFLOW)

cout << "GL_STACK_OVERFLOW";

if (error == GL_STACK_UNDERFLOW)

cout << "GL_STACK_UNDERFLOW";

if (error == GL_OUT_OF_MEMORY)

cout << "GL_OUT_OF_MEMORY";

if (error == GL_INVALID_FRAMEBUFFER_OPERATION)

cout << "GL_INVALID_FRAMEBUFFER_OPERATION";

if (error == GL_CONTEXT_LOST)

cout << "GL_CONTEXT_LOST";

cout << (char)7 << endl; /*play sound*/

cin.get();

}

}

If an error occured, it can somtimes be hard to detect where the error occured, particularly if GL code is distributed over several files. To make it easier to detect the location of the error, a macro can be used, like this, which gives you the file and line number where the error occured the first time:

#define CHECK_GL_ERROR __CheckForGLError(__FILE__, __LINE__);

void __CheckForGLError(const char* filename, int line)

{

for (GLenum error; (error = glGetError()) != GL_NO_ERROR;)

{

cout << (char)7 << "OpenGL Error:\t" << filename << " line " << line << "\n\t";

if (error == GL_INVALID_ENUM)

cout << "GL_INVALID_ENUM";

if (error == GL_INVALID_VALUE)

cout << "GL_INVALID_VALUE";

if (error == GL_INVALID_OPERATION)

cout << "GL_INVALID_OPERATION";

if (error == GL_STACK_OVERFLOW)

cout << "GL_STACK_OVERFLOW";

if (error == GL_STACK_UNDERFLOW)

cout << "GL_STACK_UNDERFLOW";

if (error == GL_OUT_OF_MEMORY)

cout << "GL_OUT_OF_MEMORY";

if (error == GL_INVALID_FRAMEBUFFER_OPERATION)

cout << "GL_INVALID_FRAMEBUFFER_OPERATION";

if (error == GL_CONTEXT_LOST)

cout << "GL_CONTEXT_LOST";

cout << endl << endl;

cin.get();

}

}

Check for framebuffer errors:

bool CheckFramebuffer(GLuint framebuffer, GLenum target)

{

GLenum status = glCheckNamedFramebufferStatus(framebuffer, target);

if (status != GL_FRAMEBUFFER_COMPLETE)

{

cout << "OpenGL Framebuffer Error: \t";

if (status == GL_FRAMEBUFFER_UNDEFINED)

cout << "undefined framebuffer";

if (status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)

cout << "a necessary attachment is uninitialized";

if (status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)

cout << "no attachments";

if (status == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER)

cout << "incomplete draw buffer";

if (status == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER)

cout << "incomplete read buffer";

if (status == GL_FRAMEBUFFER_UNSUPPORTED)

cout << "combination of attachments is not supported";

if (status == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)

cout << "number of samples of all attachments do not match";

cout << (char)7 << endl; /*play sound*/

return false;

}

return true;

}

Checking for shader compilation and program linking errors:

Shader.h

#ifndef SHADER_H

#define SHADER_H

#include <GL/glew.h>

#include <string>

#include <list>

std::string LoadTextFile(const std::string& filepath);

std::string ShaderTypeName(GLuint shader);

bool CompileShader(GLuint shader, const std::string& sourcecode);

std::string ShaderInfoLog(GLuint shader);

bool LinkProgram(GLuint program, const std::list<GLuint>& shaderlist);

std::string ProgramInfoLog(GLuint program);

#endif // SHADER_H

Shader.cpp

#include "Shader.h"

#include <iostream>

#include <fstream>

std::string LoadTextFile(const std::string & filepath)

{

std::string result(""), line;

std::fstream f(filepath.c_str(), std::ios::in);

while (f.good())

{

std::getline(f, line);

result += line + '\n';

}

return result;

}

std::string ShaderTypeName(GLuint shader)

{

if (glIsShader(shader))

{

GLint type = 0;

glGetShaderiv(shader, GL_SHADER_TYPE, &type);

if (type == GL_VERTEX_SHADER)

return "Vertex Shader";

if (type == GL_TESS_CONTROL_SHADER)

return "Tessellation Control Shader";

if (type == GL_TESS_EVALUATION_SHADER)

return "Tessellation Evaluation Shader";

if (type == GL_GEOMETRY_SHADER)

return "Geometry Shader";

if (type == GL_FRAGMENT_SHADER)

return "Fragment Shader";

if (type == GL_COMPUTE_SHADER)

return "Compute Shader";

}

return "invalid shader";

}

bool CompileShader(GLuint shader, const std::string& sourcecode)

{

if (!glIsShader(shader))

{

std::cout << "ERROR: shader compilation failed, no valid shader specified" << std::endl;

return false;

}

if (sourcecode.empty())

{

std::cout << "ERROR: shader compilation failed, no source code specified (" << ShaderTypeName(shader) << ")" << std::endl;

return false;

}

const char* sourcearray[] = { sourcecode.c_str() };

glShaderSource(shader, 1, sourcearray, NULL);

glCompileShader(shader);

// check compile status

GLint status = 0;

glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

// successfully compiled shader

if (status == GL_TRUE)

return true;

// show compile errors

std::cout << "ERROR: shader compilation failed (" << ShaderTypeName(shader) << ")" << std::endl << ShaderInfoLog(shader) << std::endl;

return false;

}

std::string ShaderInfoLog(GLuint shader)

{

if (glIsShader(shader))

{

GLint logsize = 0;

GLchar infolog[1024] = { 0 };

glGetShaderInfoLog(shader, 1024, &logsize, infolog);

return std::string(infolog);

}

return "invalid shader";

}

bool LinkProgram(GLuint program, const std::list<GLuint>& shaderlist)

{

if (!glIsProgram(program))

{

std::cout << "ERROR: shader linking failed, no valid program specified" << std::endl;

return false;

}

// attach all shaders to the program

for (std::list<GLuint>::const_iterator it = shaderlist.begin(); it != shaderlist.end(); it++)

{

if (glIsShader(*it))

glAttachShader(program, *it);

}

// link program

glLinkProgram(program);

// detach all shaders again

for (std::list<GLuint>::const_iterator it = shaderlist.begin(); it != shaderlist.end(); it++)

{

if (glIsShader(*it))

glDetachShader(program, *it);

}

GLint status = 0;

glGetProgramiv(program, GL_LINK_STATUS, &status);

// successfully linked program

if (status == GL_TRUE)

return true;

// show link errors

std::cout << "ERROR: shader linking failed" << std::endl << ProgramInfoLog(program) << std::endl;

return false;

}

std::string ProgramInfoLog(GLuint program)

{

if (glIsProgram(program))

{

GLint logsize = 0;

GLchar infolog[1024] = { 0 };

glGetProgramInfoLog(program, 1024, &logsize, infolog);

return std::string(infolog);

}

return "invalid program";

}